第一章:初识Android
1.1 Android目录结构
src: 放置java代码的地方,activity.java就在这个目录下
gen: 这里的内容都是自动生成的,主要有R.java文件,你在项目中的任何资源的id都在这个文件中,永远不要手动修改它
assets: 存放一些随程序打包的文件,程序运行时可以动态读取到这些文件的内容,若使用了WebView加载本地网页,则网页相关文件会存放在这个目录下
bin: 包含一些编译时自动产生的文件,其中会有一个当前项目编译好的安装包,也就是apk文件,拷在手机上就可以直接安装了
libs: 若项目中使用了第三方的jar包,就把jar包放在这个目录下,放在这个目录下的jar包都会被自动添加到构建路径中去,
res: 这个目录下的内容有点多了,项目中使用到的图片,布局,字符串等资源都要存放在这个目录下,R.java也是根据这个目录下的文件生成的,图片在drawable目录 下,布局在layout目录下,字符串在value目录下。
AndroidManifest.xml: 这是整个项目的配置文件,程序中定义的四大组件都要在这里注册,这个文件还可以给应用添加权限声明,还可以重新指定程序最低兼容版本和目标版本。
project.properties: 这个文件非常简单,通过一行代码指定了编译程序是所使用的sdk的版本。
1.2 Android四大组件
ActivityService Broadcast Receivercontent provider 引用:http://www.cnblogs.com/pepcod/archive/2013/02/11/2937403.html
1.3 Android 日志工具Log
1. Log.v() 这个方法用于打印那些最琐碎的,意义最小的日志信息,对应级别verbose(啰嗦),是日志级别最低的一种
2. Log.d() 这个方法用于打印一些调试用的信息,这些信息对调试程序应该是有用的,对应级别debug,比verbose高一级
3. Log.i() 这个方法用于打印一些比较重要的信息,这些数据应该是你最想看到的,可以帮助你分析用户行为的那种。对应级别info,比debug高一级
4. Log.w() 这个方法用于打印一些警告信息, 提示这个地方可能会有潜在的危险,最好去修复一下这些出现警告的信息,对应级别warn,比info高一级
5. Log.e() 这个方法用于打印程序中出现的错误信息,对应级别error,比warn高一级
查看日志时,低等级的日志可以看到高等级的日志,高等级日志的看不到低等级的日志。
如果logcat中没有打印出你要的log信息,有可能是因为当前设备失去焦点了,去DDMS->Devices中点击一下当前设备,打印信息就会出来了。
第二章:Activity的相关内容
2.1 什么是活动
活动(Activity)是一种可以包含用户界面的控件,主要用于和用户进行交互,一个应用程序可以包含零个或多个活动,但不包含活动的应用程序很少见,谁也不想让自己的应用无法被用户看见。
2.2 创建一个活动
项目中的任何活动都需要重写Activity的OnCreate()方法。
2.3 创建和加载布局
android:id是给当前元素定义一个唯一的标识符,之后可以再代码中对这个元素进行操作,若要在xml文件中定义一个id则要使用@+id/id_name这个语法,若要在xml文件中引用一个id,则要用@id/id_name这个语法。在宽度和高度的设置中,match_parent表示让当前元素与父元素一样宽(高),wrap_content表示当前元素的高度只要能刚好包含里面的内容就行。
加载布局:在Activity文件的OnCreate()中加入 setContentView(R.layout.first_layout); setContentView()方法中要传入一个布局的id,通过R.layout.first_layout可以得到first_layout.xml布局的id,将这个值传入setContentView()中即可。
2.3.1 给活动注册
所有的活动都要在AndroidManifest.xml中注册,注册声明要放在
这两句声明是让firstActivity成为这个程序的主活动,即点击桌面图标进来的就是这个活动
2.3.2 隐藏标题栏
通过在OnCreate()方法中添加requestWindowFeature(Window.FEATURE_NO_TITLE);注意这句代码一定要在setContentView()前执行,不然会报错。
2.3.3 在活动中使用toast
Toast是Android系统提供的一种非常好的提醒方式,在程序中可以使用它将一些短小的信息通知给用户,就像“再按一次退出”那样的提示语句,这些信息会在一段时间后自动消失
首先要设立一个触发点:
Button button = (Button)findViewById(R.id.button1);
//给button添加listener动作
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(First_Activity.this, "This is toast !", Toast.LENGTH_SHORT).show();
}
在活动中可以通过findViewById()方法获取到在布局文件中定义的元素,findViewById()返回的是一个View对象,需向下转型为Button对象,得到了按钮的实例后,通过调用setOnClickListener()为按钮注册一个监听器,点击按钮就会执行监听器中的onClick()方法。
Toast通过静态方法makeText()创建出一个Toast对象,然后用show()方法将它显示出来就可以了,makeText需要传入三个参数,context上下文,第二个是toast要显示的内容,第三个是显示时间长短,Toast.LENGTH_SHORT或Toast.LENGTH_LONG。
2.3.4 在活动中创建菜单
在menu.xml文件中添加
@Override
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.main,menu);
return true;
}
通过getMenuInflater()方法可以得到MenuInflater对象,再调用它的inflate()方法就可以给当前活动创建菜单了,inflate()方法接收两个参数,第一个指定资源文件,第二个指定将菜单项添加到哪个Menu对象中,然后给这个方法返回true,表示允许创建的菜单显示出来,如果返回false,将无法显示创建的菜单。
在FirstActivity中重写onOptionItemSelected()方法,定义菜单相应事件
@Override
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case R.id.add_item:
Toast.makeText(this, "you press add.", Toast.LENGTH_SHORT).show();;
break;
case R.id.move_item:
Toast.makeText(this, "you press remove.", Toast.LENGTH_SHORT).show();;
break;
default:
}
return true;
}
通过调用item.getItemId()来判断点击的是哪一个菜单项,然后可以加入自己的逻辑处理。可以按下Menu键将菜单调出来。
2.3.5 销毁一个活动
通过使用finish()来销毁一个活动,效果跟按下back键相同。
2.4 使用intent在活动间穿梭
intent是Android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据,intent一般可被用于启动活动、启动服务以及发送广播等场景。
intent的用法大致分为两种,显式intent和隐式intent
2.4.1 使用显示intent
在FirstActivity中修改按钮点击事件,
public void onClick(View v) {
Intent intent = new Intent(First_Activity.this, Second_Activity.class);
startActivity(intent);
}
首先创建一个Intent,传入FirstActivity.this作为上下文,传入SecondActivity.class作为目标活动,然后通过startActivity()方法来执行这个Intent。可以达到在FirstActivity上打开SecondActivity这个活动。
2.4.2 使用隐式intent
通过在
android:name=".Second_Activity"
android:label="@string/title_activity_second_" >
在action中指定了当前活动可以响应com.example.testapp.ACTION_START这个action,只有修改FirstActivity中的点击事件
Intent intent = new Intent("com.example.testapp.ACTION_START");
startActivity(intent);
android.intent.category.DEFAULT是默认category,会被自动加入到Intent中。
每个intent只能有一个action但可有多个category。
2.4.3 更多的隐式intent的用法
使用隐式的intent,我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动,使得Android多个应用程序之间的功能共享成为了可能,写个调动系统浏览器打开网页的例子:
public void onClick(View v) {
//intent调用浏览器
Intent intent = new Intent(Intent.ACTION_VIEW);
//用uri.parse将字符串解析成uri,再用setdata将uri对象传递进去
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
还可以在1.android:scheme 用于指定数据的协议部分,如http
2.android:host 用于指定数据的主机名部分,如上例中的www.baidu.com
3.android:port 用于指定数据的端口部分,一般紧随在主机名之后
4.android:path 用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容
5.android:mimeType 用于指定可以处理的数据类型,允许使用的通配符的方式进行指定
只有标签中指定的内容和Intent中携带的Data完全一致时,当前活动才能相应该Intent,
写一个调用系统拨号界面:
public void onClick(View v) {
//在程序中调用系统拨号
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:18271682724"));
startActivity(intent);
}
2.4.4 向下一个活动传递数据
Intent提供了一系列的putExtra()方法的重载,可以把要传递的数据暂存在Intent中,启动另一个活动后,只需要把这些数据再从Intent中取出来。putExtra()方法接收两个参数,第一个是键,第二个是值。将数据从FirstActivity中传递到SecondActivity中
public void onClick(View v) {
//向下一个活动传数据
String str = "hello secendApp";
Intent intent = new Intent(First_Activity.this, Second_Activity.class);
//putExtra将数据暂时存储在intent中
intent.putExtra("data", str);
startActivity(intent);
}
//取出firstActivity传来的数据并打印出来
Intent intent = getIntent();
String data = intent.getStringExtra("data");
2.4.5 返回数据给上一个活动
startActivityForResult()方法也是用于启动活动的,但这个方法期望在活动销毁的时候能够返回一个结果给上一个活动,这个方法接收两个参数,第一个还是Intent,第二个参数是请求码,用于在之后的回调中判断数据的来源。请求码只要是唯一值就可以。
public void onClick(View v) {
//返回数据给上一个活动
Intent intent = new Intent(First_Activity.this, Second_Activity.class);
startActivityForResult(intent,1);
}
这样就可以通过startActivityForResult()方法启动SecondActivity了。
在SecondActivity中添加返回数据的逻辑
public void onClick(View v) {
//向上一个activity传值
Intent intent = new Intent();
intent.putExtra("data", "hello FirstApp");
setResult(RESULT_OK, intent);
finish();
}
setResult()方法是专门向上一个活动返回数据的,接收两个参数,第一个参数用于向上一个活动返回处理结果,一般使用RESULT_OK或RESULT_CANCELED这两个值,第二个参数则是把带有数据的Intent传递回去,然后调用finish()来销毁活动。
由于是使用startActivityForResult()方法启动SecondActivity的,在SecondActivity被销毁之后会回调上一个活动的onActivityResult()方法,因此需要在FirstActivity中重写这个方法来得到返回的数据:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(requestCode){
case 1:
if(requestCode == RESULT_OK){
String returnData = data.getStringExtra("data");
Log.d("First_Activity", returnData);
}
break;
default:
}
};
onActivityResult()方法带有三个参数,第一个参数requestCode,即启动活动时传入的请求码。第二个参数resultCode,即返回数据时传入的处理结果。第三个参数data,即携带者返回数据的Intent。通过检查requestCode的值来判断数据来源,再通过resultCode来判断处理结果是否成功,最后从data中取值并打印出来,这样就完成了向上一个活动返回数据的工作。
若想通过按下back键,回到FirstActivity并传回数据的话,要重写onBackPressed()方法来解决这个问题,
@Override
public void onBackPressed(){
Intent intent = new Intent();
intent.putExtra("data", "hello FirstApp");
setResult(RESULT_OK,intent);
finish();
}
当按下back键时,就会执行onBackPressed()中的代码。
2.5 活动的生命周期
2.5.1返回栈
android是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(Back Stack)。当启动一个新的活动时,它会在返回栈中入栈,并处于栈顶的位置。而当我们按下back键或调用finish()方法去销毁一个活动时,处于栈顶的活动会出栈,这时前一个入栈的活动就会重新处于栈顶的位置,系统总是会显示处于栈顶的活动给用户。
2.5.2 活动状态
每个活动在其生命周期中最多可能会有四种状态:运行状态、暂停状态、停止状态、销毁状态
运行状态:当一个活动位于返回栈栈顶时,这时活动就处于运行状态。
暂停状态:当一个活动不在处于栈顶位置,但仍然可见时,比如弹出一个对话框,后面的内容还是可见的,这时后面的内容就处于暂停状态。
停止状态:当一个活动不在处于栈顶位置,并且完全不可见时,就进入停止状态。
销毁状态:当一个活动从返回栈中移除后就变成了销毁状态。
2.5.3 活动的生存期
Activity类中定义了七个回调方法,覆盖了活动生命周期的每一个环节,七种方法分别是:
1.OnCreate():它会在活动第一次被创建时调用,应该在这个方法中完成活动的初始化操作,比如加载布局、绑定事件等。
2.onStart():这个方法在活动由不可见变为可见时调用。
3.onResume():这个方法在活动准备好和用户进行交互的时候调用,此时的活动一定处于返回栈的栈顶,并且处于运行状态。
4.onPause:这个方法在系统准备去启动或者恢复另一个活动的时候调用。
5.onStop():这个而方法在活动不可见的时候调用,它和onPause()方法的主要区别在于,如果启动的新活动是一个对话框式的活动,那么onPause()方法会得到执行,而onStop()方法并不会执行。
6.onDestroy():这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态。
7.onRestart():这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重启了
2.5.5 活动被回收了怎么办
Activity中提供了一个onSaveInstanceState()回调方法,这个方法会保证一定在活动被回收之前调用,因此可以通过这个方法来解决活动被回收时临时数据得不到保存的问题。
在MainActivity中添加如下代码:
//保存stop前的临时数据
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
String tempData = "Test temp data save.";
outState.putString("data_key", tempData);
}
putString()是保存字符串,putInt()可以保存整型数据,以此类推,里面的参数是键值对,第一个是键,用于后面从Bundle中取值。OnCreate()方法中有一个Bundle类型的参数,当活动被系统回收之前通过onSaveInstanceState()方法来保存数据的话,这个参数就会带有之前所保存的全部数据,修改OnCreate()代码来取出数据:
//取出临时数据
if(savedInstanceState != null){
String tempData = savedInstanceState.getString("data_key");
//取出来之后可以做别的操作,如复制到文本框等等
Log.d(Tag, tempData);
}
2.6.1 standard
standard是活动默认的启动模式,在standard模式下,每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置。系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。
2.6.2 singleTop
使用singleTop模式,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。
2.6.3 singleTask
使用singleTask模式,每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,如果存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。
2.6.4 singleInstance
指定为singleInstance模式的活动会启用一个新的返回栈来管理这个活动,不管哪个应用程序来访问这个活动,都共用的同一个返回栈,也就解决了共享活动实例的问题。
《第一行代码》的前两章的学习内容到这里就结束了。第一章主要是初步认识一下android。第二章介绍了Activity的相关内容,从活动的基本用法,到启动活动和传递数据的方式,再到活动的生命周期,以及活动的启动模式。这才刚刚开始,小伙子,继续前进吧!!!