活动
基本用法
-
创建Activity子类
-
创建和加载布局
-
在manifest文件中注册
-
隐藏标题栏
-
销毁活动
-
在活动中使用Toast
-
在活动中使用Menu
活动间通讯(Intent)
Intent用于各组件(活动、服务、广播等)之间进行交互。
- 显式使用Intent
button1.setOnClickListener(newOnClickListener(){
@Override
publicvoid onClick(View v){
Intent intent =newIntent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
}
})
- 隐式使用Intent
<activityandroid:name=".SecondActivity">
<intent-filter>
<actionandroid:name="com.example.activitytest.ACTION_START"/>
<categoryandroid:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
只有<action>
和<category>
中的内容同时能够匹配上Intent中指定的action和category时,这个活动才能响应该Intent。
button1.setOnClickListener(newOnClickListener(){
@Override
publicvoid onClick(View v){
Intent intent =newIntent("com.example.activitytest.ACTION_START");
startActivity(intent);
}
});
这里没有指定category是因为使用了默认的category。
每个Intent中只能指定一个action,但却能指定多个category。
button1.setOnClickListener(newOnClickListener(){
@Override
publicvoid onClick(View v){
Intent intent =newIntent("com.example.activitytest.ACTION_START");
intent.addCategory("com.example.activitytest.MY_CATEGORY");
startActivity(intent);
}
});
使用隐式Intent不仅可以启动自己程序内的活动,还可以启动其他程序的活动。
button1.setOnClickListener(newOnClickListener(){
@Override
publicvoid onClick(View v){
Intent intent =newIntent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});
Intent.ACTION_VIEW是Android内置的动作,然后通过setData()将Uri对象传递进去。与此对应,我们还可以在intent-filter
标签中再配置一个<data>
标签,用于更精确地指定当前活动能够响应什么类型的数据。
- 活动间传递数据
-
向下个活动传递数据
首先向Intent中放入数据intent.putExtra("key", data);
,然后取出数据String data = getIntent().getStringExtra("key");
-
返回数据给上个活动
Activity还有一个startActivityForResult()方法也是用来启动活动的。两个参数,intent和请求码。后者只需要是唯一值就可以。我们使用这个方法来创建SecondActivity。
button1.setOnClickListener(newOnClickListener(){
@Override
publicvoid onClick(View v){
Intent intent =newIntent(FirstActivity.this,SecondActivity.class);
startActivityForResult(intent,1);
}
});
然后,在SecondActivity中添加返回数据的逻辑,可以添加新的按钮,或者重写back操作——onBackPressed()。
@Override
publicvoid onBackPressed(){
Intent intent =newIntent();
intent.putExtra("data_return","Hello FirstActivity");
setResult(RESULT_OK, intent);
finish();
}
最后,重写FirstActivity的onActivityResult方法来获得返回的数据。
@Override
protectedvoid onActivityResult(int requestCode,int resultCode,Intent data){
switch(requestCode){
case1:
if(resultCode == RESULT_OK){
String returnedData = data.getStringExtra("data_return");
Log.d("FirstActivity", returnedData);
}
break;
default:
}
}
生命周期
-
返回栈
Android使用任务(Task)来管理活动,一个任务就是一组存放在返回栈中的活动。
-
活动状态
状态 | 活动所处位置 | 活动可见性 | 备注 |
---|---|---|---|
运行状态 | 栈顶 | 可见 | 系统不愿意回收的活动,因为会带来非常差的用户体验 |
暂停状态 | 不在栈顶 | 可见 | 栈顶的活动可能没有占满整个屏幕,比如对话框 |
停止状态 | 不在栈顶 | 不可见 | 系统仍然会为活动保持状态和变量,但是一旦需要内存,就可能被系统回收 |
销毁状态 | 不在栈顶 | 不可见 | 最倾向于回收的活动 |
- 活动的生存期
顺序 | 方法名 | 作用 |
---|---|---|
1 | onCreate() | 创建活动时调用,加载布局,绑定事件等。 |
2 | onStart() | 活动由不可见变为可见时调用 |
3 | onResume() | 此时活动一定处在栈顶,并且处于运行状态。 |
4 | onPause() | 准备启动或恢复另一个活动时调用,通常会将一些耗CPU的资源释放掉,以及保持一些关键数据,但执行速度要快,否则会影响新的栈顶活动的使用。 |
5 | onStop() | 如果新活动时对话框时,那么将不会调用onStop()。 |
6 | onDestory() | 销毁之前调用,之后活动状态变为销毁状态 |
7 | onRestart | 这个方法只在不占全屏的活动返回上一个活动时调用。比如对话框。 |
- 防止活动被回收而丢数据
Intent还可以结合Bundle一起用于传递数据的,首先可以把需要传递的数据都保存在Bundle对象中,然后再将Bundle对象存放在Intent里。到了目标活动之后先从Intent中取出Bundle,再从Bundle中取出数据。
启动模式
-
standard
每次启动活动都创建活动的新实例。
-
singleTop
启动的活动已经在栈顶时,不创建新的实例,不再栈顶则新建活动实例。
- singleTask
返回栈中存在启动的活动时,会将该活动之前的活动都出栈,直到启动的活动到达栈顶。
- singleInstance
为该活动新建一个返回栈,解决应用程序之间共享活动的使用场景。
最佳实践
一些使用技巧
- 获知当前的活动名称
所有的活动都继承下面的BaseActivity,这个类通过日志输出当前的类名。
publicclassBaseActivityextendsActivity{
@Override
protectedvoid onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.d("BaseActivity", getClass().getSimpleName());
}
}
- 随时退出应用程序
如果活动很多,你会发现必须一个一个活动返回,按home键只是将程序挂起,并没有退出程序。解决方案很简单——使用一个集合类来管理所有活动。
publicclassActivityCollector{
publicstaticList<Activity> activities =newArrayList<Activity>();
publicstaticvoid addActivity(Activity activity){
activities.add(activity);
}
publicstaticvoid removeActivity(Activity activity){
activities.remove(activity);
}
publicstaticvoid finishAll(){
for(Activity activity : activities){
if(!activity.isFinishing()){
activity.finish();
}
}
}
}
- 启动活动的最佳写法
活动之间的耦合性很高,如果是协作开发的话,会遇到对接问题。换一种写法可以解决:
添加一个actionStart()方法,在方法中完成Intent的创建,另外将所有活动需要的数据都通过参数传递过来。如此一来活动所需的数据可以从参数列表中体现出来,而无需阅读要启动的活动的源码或者询问相关同事了。