参考:
Activity:https://developer.android.com/guide/components/activities.html
任务和返回栈:https://developer.android.com/guide/components/tasks-and-back-stack.html
Activity
是 Android
系统中使用最频繁的组件,刚入门 Android
就需要使用它。Activity
包含了许多隐藏的知识,需要深入了解才能更好的使用它
Activity
浅析(Android Activity - 1
)- 生命周期
- 退出情况分析(
Android Activity - 2
) - 任务与返回栈
- 启动模式
BaseActivity.java
(Android Activity - 3
)- 清理返回栈
- 屏幕方向
Activity
浅析
Activity
浅析
Activity
是 Android
四个基本组件之一(Activity
/ Service
/ Broadcast Receiver
/ Content Provider
)
Activity
能够在屏幕上显示界面,同时能够和用户进行交互
声明
需要在 清单文件 上声明 Activity
,在元素 <application>
下增加子元素 <activity>
,示例如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zj.activitydemo">
<application
...
...
>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Main2Activity" />
</application>
</manifest>
元素 <activity>
必须设置的属性是 android:name
,用来指定 Activity
的类名
指定启动 Apk
后第一个 Activity
,通过子元素 <intent-filter>
进行设置,内容如下:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
显式启动
Activity
之间的跳转,需要使用函数 startActivity
:
void startActivity(Intent intent)
在 intent
中设定跳转的 Activity
,如果需要传递信息,可以设置键值对,示例如下:
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
intent.putExtra("String", "var1");
intent.putExtra("boolean", true);
intent.putExtra("Integer", 3);
startActivity(intent);
在目的 Activity
中调用函数 getIntent
获取 Intent
对象,解析键值对获取信息,示例如下:
Intent intent = getIntent();
if (intent != null) {
String var1 = intent.getStringExtra("String");
boolean var2 = intent.getBooleanExtra("Boolean", true);
int var3 = intent.getIntExtra("Integer", 0);
}
也可以设置 Bundle
对象:
Bundle bundle = new Bundle();
bundle.putString("key", "value");
intent.putExtra("bundle", bundle);
获取:
Bundle bundle = intent.getBundleExtra("bundle");
String str = bundle.getString("key");
如果需要目的 Activity
能够反馈信息给当前 Activity
,可以使用函数 startActivityForResult
:
void startActivityForResult (Intent intent, int requestCode)
除了设置 Intent
对象外,还需要设置参数 requestCode
(必须大于 0
),比如:
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
startActivityForResult(intent, 100);
然后在目的 Activity
结束之前,调用函数 setResult
:
void setResult (int resultCode)
void setResult (int resultCode, Intent data)
参数 resultCode
作为结果码(result code
)反馈给调用 Activity
,通常是 Activity.RESULT_OK
或者 Activity.RESULT_CANCELED
参数 data
用来返回数据(需要的话)
示例如下:
Intent intent = new Intent();
intent.putExtra("Hello", "World");
setResult(Activity.RESULT_CANCELED, intent);
finish();
当目的 Activity
结束,返回到调用 Activity
后,会调用函数 onActivityResult
:
void onActivityResult (int requestCode, int resultCode, Intent data)
参数 requestCode
和参数 resultCode
分别对应之前的参数设置,参数 data
用来保存目的 Activity
反馈给调用 Activity
的数据。示例如下:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 100:
if (resultCode == RESULT_CANCELED) {
if (data != null) {
String var = data.getStringExtra("Hello");
Log.e(TAG, "onActivityResult: " + var);
}
}
break;
default:
super.onActivityResult(requestCode, resultCode, data);
}
}
ActivityOptions
打开 startActivity
的源码,发现它调用了一个重载函数:
/**
* Same as {@link #startActivity(Intent, Bundle)} with no options
* specified.
*
* @param intent The intent to start.
*
* @throws android.content.ActivityNotFoundException
*
* @see #startActivity(Intent, Bundle)
* @see #startActivityForResult
*/
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
调用函数 startActivity(Intent, Bundle)
(支持最低版本是 Android 4.1(API 16)
)
void startActivity (Intent intent, Bundle options)
那么参数 options
有什么用呢,查看源码中对于 options
参数的解释:
...
...
* @param intent The intent to start.
* @param options Additional options for how the Activity should be started.
* See {@link android.content.Context#startActivity(Intent, Bundle)
* Context.startActivity(Intent, Bundle)} for more details.
...
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
Bundle options
参数是关于 Activity
如何启动的选项
继续查看 android.content.Context#startActivity(Intent, Bundle)
的解释:
Bundle: Additional options for how the Activity should be started.
May be null if there are no options.
See ActivityOptions for how to build the Bundle supplied here; there are no supported definitions for building it manually.
可以使用 ActivityOptions
来构建这个 Bundle
对象,设置 Activity
的启动画面
具体如何设置,等待以后学习
退出
点击屏幕 回退 键可以退出当前 Activity
,也可以使用函数 finish
手动退出:
/**
* Call this when your activity is done and should be closed. The
* ActivityResult is propagated back to whoever launched you via
* onActivityResult().
*/
public void finish() {
finish(DONT_FINISH_TASK_WITH_ACTIVITY);
}
还有一个函数 finishActivity
可用来结束上一个 Activity
,不过测试过后发现并没有效果,在网上查了很多资料也没有一个很好的解释,等待日后解决
生命周期
Android
系统将 Activity
从创建到销毁的整个生命周期分为多个阶段,每个阶段均有回调函数,根据不同的回调函数,执行相应的操作
基本状态
Android
基本状态包括:
- 创建:启动
Activity
- 运行:
Activity
位于前台并具有用户焦点 - 暂停:另一个
Activity
位于前台并具有用户焦点,当前Activity
仍可见 - 停止:
Activity
位于后台,对用户不可见,可能会被Android
系统终止 - 恢复:
Activity
从后台回到前台并获取用户焦点 - 终止:退出
Activity
基本生命周期回调函数
根据 Activity
的基本状态,其基本回调函数包括:
onCreate
onRestart
onStart
onResume
onPause
onStop
onDestroy
流程图如下所示:
两个 Activity
之间生命周期回调函数顺序
当前 Activity
启动新的 Activity
时,两个 Activity
对应的生命周期回调函数会有交叉现象,比如,Activity A
启动了 Activity B
,相应的回调函数顺序如下:
Activity A
执行暂停,调用onPause
(此时Activity A
仍处于可见状态)- 新建
Activity B
依次调用onCreate -> onStart -> onResume
(此时Activity B
位于前台并具有用户焦点) - 此时
Activity B
已不可见,然后调用onStop
然后从 Activity B
返回到 Activity A
,相应的回调函数顺序如下:
Activity B
执行暂停,调用onPause
Activity A
重新回到前台,依次调用onRestart -> onStart -> onResume
Activity B
停止并退出,依次调用onStop -> onDestroy
测试
下面进行测试说明生命周期回调顺序
新建 BaseActivity.java
,用于打印所有的回调函数运行过程:
public class BaseActivity extends AppCompatActivity {
private static final String TAG = "BaseActivity";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: " + getLocalClassName());
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart: " + getLocalClassName());
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart: " + getLocalClassName());
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume: " + getLocalClassName());
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause: " + getLocalClassName());
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop: " + getLocalClassName());
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: " + getLocalClassName());
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult: " + getLocalClassName());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d(TAG, "onNewIntent: ");
}
}
情况一:启动 MainActivity
,锁屏,然后将应用退到后台,最后退出
启动 MainActivity
,经过回调函数 onCreate -> onStart -> onResume
:
屏幕锁屏,经过回调函数 onPause -> onStop
:
屏幕解锁,重新回到应用,经过回调函数 onRestart -> onStart -> onResume
:
点击 主页 键,将应用退到后台,经过回调函数 onPause -> onStop
:
点击应用启动器,将应用重新回到前台,经过回调函数 onRestart -> onStart -> onResume
:
退出应用,经过回调函数 onPause -> onStop -> onDestroy
:
情况二:启动 MainActivity
,并跳转到 Main2Activity
,然后回退到 MainActivity
,最后退出应用
使用函数 startActivityForResult
进行跳转
启动 MainActivity
,经过回调函数 onCreate -> onStart -> onResume
:
点击按钮,跳转到 Main2Activity
首先经过 MainActivity
的 onPause
然后经过 Main2Activity
的 onCreate -> onStart -> onResume
最后经过 MainActivity
的 onStop
:
点击回退按钮,从 Main2Activity
返回到 MainActivity
首先经过 Main2Activity
的 onPause
然后经过 MainActivity
的 onActivityResult -> onRestart -> onStart -> onResume
最后经过 MainActivity
的 onStop -> onDestroy