Intent
Intent分为两种,显式Intent和隐式Intent。
显式Intent的构造函数需要两个参数,第一个参数是上下文,第二个参数是class,指定要启动的活动,创建好的Intent通过startActivity方法启动。
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
}
按下back键可以销毁当前的活动,回到上一个活动。
隐式Intent并不明确指定启动的活动,而是用更抽象的action和category等信息来由系统分析启动哪一个程序。
首先需要给第二个活动配置intent-filter来接收action和category, 如下图:
<intent-filter>
<action android:name="com.example.activtydemo.ACTION_START"></action>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
这样第二个活动就能响应来自category下的"com.example.activtydemo.ACTION_START"的Intent了。一个隐式Intent能够响应一个action和多个category。
隐式Intent还能跨程序访问,Intent.ACTION_VIEW是android内置的,声明了一个字符串常量"android.intent.action.VIEW",这样配置了"android.intent.action.VIEW"的intent-filter的action就能被访问了,setData方法将uri解析的结果放在intent对象中,这样点击按钮就能访问百度了。
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
我们还能在<intent-filter>
标签中添加<data>
标签,可以对协议,主机名,端口号等进行指定。
使用Intent来传递数据
我们可以通过putExtra, getStringExtra方法来在活动间传递数据
public void onClick(View v) {
String data = "Hello SecondActivity";
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("extra_data",data);
startActivity(intent);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);
}
返回数据给上一个活动
首先我们需要一个startActivityForResult方法,第一个参数是intent,第二个参数是一个唯一状态码。
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivityForResult(intent,1);
}
然后在第二个活动处理返回逻辑,新建一个Intent,然后使用setResult方法,第一个参数是状态码,一般使用RESULT_OK和RESULT_CANCELED,第二个参数是Intent。
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("return_data","Hello FirstActivity");
setResult(RESULT_OK,intent);
finish();
}
由于使用了startActivityForResult方法,在第二个活动销毁的时候,会调用第一个活动的onActivityResult方法,因此我们需要重写onActivityResult方法,得到Intent返回的数据。
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode){
case 1:
if (resultCode == RESULT_OK){
String returnData = data.getStringExtra("return_data");
Log.d("FirstActivity", returnData);
}
break;
default:
}
}
如果使用back键返回,那么重写onBackPressed方法就行。
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("return_data","Hello FirstActivity");
setResult(RESULT_OK,intent);
finish();
}
活动的生命周期
活动是以栈的形式堆叠在一起的,这个栈叫做返回栈。
活动的状态
- 运行状态
- 暂停状态
- 停止状态
- 销毁状态
活动位于栈顶的时候,就处于运行状态,系统不愿意回收这种状态。
活动不位于栈顶的时候,但是可见的,这时处在暂停状态,系统也不愿意回收。
活动不位于栈顶,并且不可见的时候,就处于停止状态,有可能会被系统回收。
活动从返回栈中移除的时候,就处于销毁状态,系统最倾向于销毁这种活动。
七个回调方法
- onCreate
- onStart
- onResume
- onPause
- onStop
- onDestory
- onRestart
除了onRestart,其他的回调方法都是两两对应的,形成3个生存期。
三个生存期
- 完整生存周期
- 可见生存期
- 前台生存期
完整生存周期从onCreate到onDestory,一般在onCreate中做初始化,在onDestory时释放内存。
可见生存期从onStart到onStop,期间用户是可见的,onStart加载资源,onStop释放资源。
前台生存周期在onResume,onPause,此时活动是运行状态的。
四种启动模式
通过在AndroidManifest.xml中指定<activity>
标签中的android:launchMode来选择启动模式。
standard
不会关心返回栈中是否有相同实例存在,这样连续点击会产生多个实例,需要多次点击back建销毁活动。
singleTop
这种模式会检查栈新建的活动是否和返回栈栈顶相同,这样连续点击不会产生新的实例,但是来回切换的时候还是会创建相同的实例。
singleTask
这种模式会在整个返回栈中检查实例是否存在,这样整个返回栈不会有相同实例,如果有相同实例,使用原有的实例,并将原有实例之上的活动全部出栈
singleInstance
每个程序都有一个自己的返回栈,singleInstance会有一个单独的返回栈,所有程序都会共享这个返回栈的实例。
活动的最佳实践
要实现进入一个活动界面就显示该活动的名称,我们建立一个新的baseActivity类,其他的activity继承基类,在基类中打印日志显示当前实例就能做到了。
要同时销毁所有的活动,使用back会不方便,因此我们可以新建一个收集器类,在基类的创建方法onCreate中用收集器收集实例,并在销毁方法onDestory中调用收集器的方法销毁所有实例即可。
启动活动时,自己写一个静态的启动类,声明参数,这样别人就能知道需要向这个活动传递的参数了,同时也能简化活动的启动,如图:
private static void actionStart(Context context,String data1,String data2){
Intent intent = new Intent(context,SecondActivity.class);
intent.putExtra("param1",data1);
intent.putExtra("param2",data2);
actionStart(context, data1, data2);
}