简析Intent与活动Activity
微信公众号
本文亦可关注公众号阅读:
公众号:代码之火
一、Intent
1.1 Intent简介
Intent主要用于组件间的通信,它是一个消息,它可以包含数据,可以被传递到另一个组件。Intent一般用于启动活动、启动服务,以及发送广播等。
1.2 显示Intent
显示Intent即通过Intent的构造函数显示提供启动目标的上下文及启动目标本身,然后通过startActivity()
方法启动目标。
1
2
3
4
5
6
7
8
|
Button btn_testIntent = (Button) findViewById(R.id.btn_testIntent);
btn_testIntent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, TestIntentActivity.class);
startActivity(intent);
}
});
|
Intent构造函数有多个,其中最常用的是Intent(Context packageContext, Class<?> cls)
,其中context
是上下文,cls
是目标类。
1.3 隐式Intent
隐式Intent并不明确指出目标活动,而是通过action
和category
消息,让系统分析得到合适的
目标活动。
1
2
3
4
5
6
|
<activity android:name=".testIntentActivity">
<intent-filter>
<action android:name="com.cosyspark.testIntent.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
|
action
标签内容表示可以响应com.cosyspark.testIntent.ACTION_START
消息,category
标签内容表示附加内容,还必须可以响应 category
标签内容android.intent.category.DEFAULT
的消息。
如果某个活动注册了action
和category
标签,那么只有同时匹配这两个标签的Intent才能得到响应。
此时的按钮点击事件可以写成:
1
2
3
4
5
6
7
8
9
10
11
|
btn_testIntent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.cosyspark.testIntent.ACTION_START");
// 因为该activity的category标签为default,不写category标签时,系统会自动将default标签加入到intent中,故此写法能也能匹配到该活动。
// 如果addCategory()添加的category未在<intent-filter>标签中声明,那么启动程序会崩溃,因为该问题会导致无法找到响应该intent的活动。
//intent.addCategory("android.intent.category.DEFAULT");
startActivity(intent);
}
});
|
1.3.1 Intent.ACTION_VIEW
Intent.ACTION_VIEW
为Android系统内置动作,常量值为android.intent.action.VIEW
,具体传值方法如下:
使用浏览器打开链接
1
2
3
|
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://cosyspark.space));
startActivity(intent);
|
通过在<intent-filter>
标签中添加<data>
标签可以指定细化setData()
的解析的数据类型,如:
1
2
3
4
5
6
7
8
9
10
11
|
<activity android:name=".testIntentActivity">
<intent-filter>
<action android:name="com.cosyspark.testIntent.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="https" />
<!-- data android:host="cosyspark.space" /> 指定主机名 -->
<!-- data android:port="443" /> 指定端口号 -->
<!-- data android:path="/test" /> 指定域名后的路径- -->
</intent-filter>
</activity>
|
拨号
1
2
3
4
5
6
7
8
9
|
btn_testIntent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
// tel指定data的协议类型,10086表示拨号的号码,如果没有指定号码,那么系统会自动拨号到10086。
startActivity(intent);
}
});
|
1.4 Intent传递数据
通过Intent在活动间传输数据、参数等。
1
2
3
|
Intent intent = new Intent(MainActivity.this, TestIntentActivity.class);
intent.putExtra("key", "value"); // 将key为"key"的数据传递给TestIntentActivity
startActivity(intent);
|
获取Intent传输数据的值:
1
2
|
Intent intent = getIntent();
String value = intent.getStringExtra("key");
|
二、返回栈
返回栈
Android是通过任务(task)来管理活动的,一个任务是一组放在栈中的活动的集合,这个栈就叫返回栈
。启动新活动时会将新活动压栈,销毁活动时栈顶活动将被弹出(finish()
)。
2.1 活动的状态
2.2 活动的生存期
活动的回调方法:
- onCreate() 活动初始化:加载布局、绑定事件等
- onStart() 活动启动:使活动由不可见变为可见时调用
- onResume() 活动即将和用户交互时调用,活动处于栈顶
- onPause() 活动离开需启动另一个活动时调用
- onStop() 活动不可见时调用。若新活动是对话框式的活动,则旧活动会调用onPause()方法,因为旧活动仍可见
- onDestroy() 活动销毁前调用
- onRestart() 活动由停止状态变为运行状态时调用
活动的生存期:
- 完整生存期:onCreate() ~ onDestroy()
- 可见生存期:onStart() ~ onStop()
- 前台生存期:onResume() ~ onPause()
活动的生存期
2.3 活动被回收
如果活动被系统回收,那么之前该活动保存的数据将丢失(例如活动A
记录了用户输入的用户名和密码的表单,切换到另一个活动B
后又返回活动A
,之前未保存活动A
数据的话,活动A
的表单数据可能会被清空。因为一旦活动A
被回收,从活动B
返回至活动A
时将重新调用活动A
的onCreate()方法。)此时可以通过在活动A
中调用onSaveInstanceState()
方法保存活动A
数据,然后通过Bundle恢复活动A
数据。
活动A
调用onSaveInstanceState()
方法保存活动中某些数据:
1
2
3
4
5
6
7
8
|
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
String username = mUsernameEditText.getText().toString();
String password = mPasswordEditText.getText().toString();
outState.putString("username", mUsername);
outState.putString("password", mPassword);
}
|
活动A
修改onCreate()
方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUsernameEditText = (EditText) findViewById(R.id.username_edit_text);
mPasswordEditText = (EditText) findViewById(R.id.password_edit_text);
if (savedInstanceState != null) {
mUsername = savedInstanceState.getString("username");
mPassword = savedInstanceState.getString("password");
mUsernameEditText.setText(mUsername);
mPasswordEditText.setText(mPassword);
}
}
|
三、活动的启动模式
AndroidManifest.xml中的启动模式:
1
2
3
4
5
6
7
8
9
10
11
12
|
<activity android:name="com.example.myapplication.MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
<!-- android:launchMode="singleInstance" -->
<!-- android:launchMode="singleTop" -->
<!-- android:launchMode="singleTask" -->
android:theme="@style/AppTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
|
3.1 standard(默认)
每当启动一个活动,该活动都会被压入返回栈,不论占中存在该活动与否
默认模式
3.4 singleTop
当启动的活动本身在栈顶时,将不会压入返回栈,而是直接使用栈顶活动。
singleTop模式
3.2 singleTask
首先检查返回栈中是否存在该活动,若不存在则将新活动压栈;否则将存在的活动上面的其他活动全部弹出,使已经存在的活动处于栈顶。
singleTask模式
3.3 singleInstance
有且仅有该活动拥有一个独立的返回栈,与之前的活动不共用同一个返回栈。
singleInstance模式
四、判断当前活动类名
使某些活动
继承于一个自定义的类,而该类继承于某些活动
原来的父类,从而不改变某些活动
原来的类特征;在自定义类中重写onCreate()方法,添加调用getClass().getSimpleName()方法,以便判断当前活动的类名。
1
2
3
4
5
6
7
8
9
10
11
12
|
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
// ...
// ...
*/
Log.i("MyActivity", getClass().getSimpleName());
}
}
|
五、自定义活动管理器
随时随地结束当前活动,结束程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class ActivityCollector{
public static List<Activity> activities = new ArrayList<>();
public static void addActivity(Activity activity){
activities.add(activity);
}
public static void removeActivity(Activity activity){
activities.remove(activity);
}
public static void finishAll(){
for (Activity activity : activities) {
if (!activity.isFinishing()) {
activity.finish();
}
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
// ...
// ...
*/
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
}
|
调用活动管理器结束程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public class MyActivity extends Activity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
// ...
// ...
*/
ActivityCollector.addActivity(this);
}
Button button = findViewById(R.id.btn_exit);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityCollector.finishAll();
// 结束当前程序进程,当且仅限结束当前程序的pid,无法结束其他程序的进程
// android.os.Process.killProcess(android.os.Process.myPid());
}
});
}
|