Activity 是 Android 组件中最基本也是最为常见用的四大组件(Activity 活动,Service 服务,Broadcast Receiver 广播接收器,Content Provider 内容提供器)之一。Activity 是一种包含了用户界面的组件,所有操作都与用户密切相关,主要用于和用户进行交互。
在一个 Android 应用中,一个 Activity 通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。Activity 之间通过 Intent 进行通信。
所以我认为 Activity 还有一个作用就是传递数据。
自定义一个 FirstActivity 继承 Activity,通过 XML 文件的方式来编辑布局,然后在onCreate()
方法中调用setContentView(R.layout.first_layout)
方法来给当前的活动加载布局,并且所有的活动都要在 AndroidManifest.xml
中进行注册才能生效。
活动的注册声明要放在<application>
标签内,这里是通过<activity>
标签来对活动进行注册的。
Intent 是 Android 程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以再不同组件之间传递数据。Intent 的用法分为显式 Intent 和隐式 Intent 。
显式 Intent 直接用组件的名称定义目标组件,这种方式很直接。但是由于开发人员往往并不清楚别的应用程序的组件名称,因此,显式 Intent 更多用于在应用程序内部传递消息。代码如下:
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
Intent 的构造函数接受两个参数,第一个参数 Context 要求提供一个启动活动的上下文,第二个参数 Class 则是指定想要启动的目标活动。再将构建好的 Intent 传入 startActivity()
中来启动目标活动。
相比于显式 Intent,隐式 Intent 则含蓄了许多,由于没有明确的目标组件名称,所以必须由 Android 系统帮助应用程序寻找与 Intent 请求意图最匹配的组件。因此,它更广泛地用于在不同应用程序之间传递消息。
Android 系统寻找与 Intent 请求意图最匹配的组件具体的选择方法是:Android 将 Intent 的请求内容和一个叫做 Intent-Filter 的过滤器比较,Intent-Filter 中包含系统中所有可能的待选组件。在通过和 Intent-Filter 比较来解析隐式 Intent 请求时,Android 将以下三个因素作为选择的参考标准:Action、Data、Category。Extra 和 Flag 在解析收到 Intent 时是并不起作用的。
一个没有声明 Intent-Filter 的组件只能响应指明自己名字的显式 Intent 请求,而无法响应隐式 Intent 请求。而一个声明了 Intent-Filter 的组件既可以响应显式 Intent 请求,也可以响应隐式 Intent 请求。
Intent 中提供了一系列的putExtra()
方法的重载,可以把我们想要传递的数据暂存在 Intent 中,启动了另一个活动后,再从 Intent 中取出即可。
先把数据暂存在第一个活动的 Intent 中:
String data = "Hello World!";
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("extra_data",data);//第一个参数是键,第二个参数是键对应的值,即想要的数据。
startActivity(intent);
再在第二个活动将传递的数据取出并打印信息:
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");//对应头一个活动的键,以此取出值。
Log.d("SecondActivity",data);//打印信息。
这里由于传递的是字符串,所以使用getStringExtra()
方法,如果传递的是整型数据,则使用getIntExtra()
方法,以此类推。
在第一个活动中不用startActivity()
而是用startActivityForResult()
方法来启动第二个活动:
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivityForResult(intent,233);//这里的233是请求码,请求码只要是一个唯一值就可以了,用来判断数据来源。
接下来在第二个活动中给按钮注册点击事件,并在点击事件中添加可以返回数据的逻辑代码:
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new OnClickListener(){
@override
public void onClick(View v){
Intent intent = new Intent();//没有意图仅用于传递数据。
intent.putExtra("data_return","Hello FirstActivity");//把数据放入 Intent中。
setResult(RESULT_OK,intent);//一般只用RESULT_OK和RESULT_CANCELED两个值。
finish();//销毁活动。
}
});
因为使用的是startActivityForResult()
方法来启动第二个活动的,在第二个活动被销毁之后会回调第一个活动的onActivityResult()
方法:
@override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
switch(requestCode){ //requestCode请求码就是上面传入的233。
case 233:
if(resultCode == RESULT_OK){ //resultCode即在返回数据时传入的处理结果。
String returnedData = data.getStringExtra("data_return");
Log.d("FirstActivity",returnedData);
}
break;
default:
}
}
如果在第二个活动中,是按返回键返回的,那么就在第二个活动中重写onBackPressed()
方法返回数据,方法同上。
每个活动在其生命周期中拥有四种基本状态:
1. 运行状态 (Active/Running):活动位于返回栈的栈顶。
2. 暂停状态 (Paused):活动不在栈顶位置,但是仍然可见。在系统内存极端低下的时候将被强行终止掉。
3. 停止状态 (Stoped):活动不在栈顶位置,并且完全不可见。当系统内存需要被用在其他地方的时候,停止状态的活动将被强行终止掉。
4. 销毁状态 (Killed):活动从返回栈中移除。系统最倾向于回收处于这种状态的活动,从而保证手机的内存充足。
onCreate()
和onDestroy()
之前所经历的。onStart()
和onStop()
之前所经历的。onResume()
和onPause()
之前所经历的。 启动模式一共有四种,可以在<activity>
标签中 android:launchMode
定义。
1. standard:默认启动方式,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。
2. singleTop:在启动活动时检查栈顶是否已经存在该活动,存在的话系统就认为可以直接使用,不创建新的实例。不过当活动并未处于栈顶位置时,这时再启动改活动,还是会创建新的实例。
3. singleTask:启动活动时系统会检查整个返回栈是否存在该活动的实例,如果存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈。没有的话会新建。
4. singleInstance: 系统会启用一个新的返回栈(或 Task )来管理这个活动,该活动与其他活动不在同一个 Task 中,其他程序也可以调用这个活动的实例。
新建一个 BaseActivity 继承 Activity,然后在 BaseActivity 中重写onCreate()
方法:
@override
protected void onCreate(Bundle saveInstanceState){
super.onCreate(saveInstanceState);
Log.d("BaseActivity",getClass().getSimpleName()); //获得类名
}
然后,所有让所有的活动都继承 BaseActivity,查看 LogCat 中的打印信息。现在每当我们进入到一个活动的界面,该活动的类名就会被打印出来。
当打开很多活动之后,退出程序需要一直按 Back,很麻烦。这时候只需要用一个专门的 ActivityColletor 集合类对所有的活动进行管理,创建静态变量和静态方法来实现所有的活动的add()
、remove()
和finish()
。
比如我需要启动一个 SecondActivity,可是不知道该活动需要哪些参数,怎么办?在 SecondActivity 中添加一个启动自己的方法:
public class SecondActivity extends Activity{
...
public static void startActivity(Context contex, String data1, String data2){
Intent intent = new Intent(context, SecondActicity.class);
intent.putExtra("param1", data1);
intent.putExtra("param2", data2);
startActivity(intent);
}
...
}
在 SecondActivity 中添加了 startActivity()
方法之后,在任意的 activity 中启动 SecondActivity,都可以调用该方法,而且知道需要传入哪些参数。
比如在 MainActivity 中启动方法为:
SecondActivity.startActivity(MainActivity.this, "data1", "data2");
养成一个良好的习惯,给自己编写的每个活动都添加类似的启动方法。