Activiy生命周期
根据上图,现在有Activity A跳转到Activity B时,页面A,B的生命周期为:
onPause(A)—onCreate(B)—onStart(B)—onResume(B)—onStop(A)
点击返回键从Activity B返回 Activity A 时,页面A,B的生命周期为:
onPause(B)—onRestart(A)—onStart(A)—onResume(A)—onStop(B)—onDestory(B)
由于Activity生命周期都是在UI线程中执行,以上生命周期中不允许有耗时操作(如网络请求,数据库读写等等),通常都会在几十毫秒(onCreate由于要加载布局,测量绘制渲染页面,需要时间会长点)或者十几毫秒内完成。现在有没有可能在以上生命周期中没有明显耗时操作,但是有些生命周期却迟迟不能回调呢?请看下面例子
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("lvlin", TAG + "onCreate: ");
setContentView(R.layout.activity_main);
findViewById(R.id.tv_test).setOnClickListener(v -> startActivity(new Intent(MainActivity.this, SecondActivity.class)));
}
@Override
protected void onStart() {
super.onStart();
Log.i("lvlin", TAG + "onStart: ");
}
@Override
protected void onResume() {
super.onResume();
Log.i("lvlin", TAG + "onResume: ");
}
@Override
protected void onPause() {
super.onPause();
Log.i("lvlin", TAG + "onPause: ");
}
@Override
protected void onStop() {
super.onStop();
Log.i("lvlin", TAG + "onStop: ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i("lvlin", TAG + "onDestroy: ");
}
}
SecondActivity
public class SecondActivity extends AppCompatActivity {
private static final String TAG = SecondActivity.class.getSimpleName();
private ScheduledExecutorService service;
private Handler handler = new Handler(Looper.myLooper());
private TextView tvTest;
int num = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Log.i("lvlin", TAG + "onCreate: ");
tvTest = findViewById(R.id.tv_test_second);
// 初始化一个单线程的service
service = Executors.newSingleThreadScheduledExecutor();
// 开启定时任务,间隔5ms更新textView文字
service.scheduleAtFixedRate(() -> {
num++;
handler.post(() -> {
tvTest.setText(num+"");
});
}, 0, 5, TimeUnit.MILLISECONDS);
}
@Override
protected void onStart() {
super.onStart();
Log.i("lvlin", TAG + "onStart: ");
}
@Override
protected void onResume() {
super.onResume();
Log.i("lvlin", TAG + "onResume: ");
}
@Override
protected void onPause() {
super.onPause();
Log.i("lvlin", TAG + "onPause: ");
}
@Override
protected void onStop() {
super.onStop();
Log.i("lvlin", TAG + "onStop: ");
}
@Override
protected void onDestroy() {
super.onDestroy();
service.shutdownNow();
Log.i("lvlin", TAG + "onDestroy: ");
}
}
从MainActivity 跳转到SecondActivity,生命周期打印如下:
从SecondActivity 返回时,生命周期打印如下:
可以发现一个问题,从MainActivity跳转到SecondActivity 时 MainActivity的onStop延迟10秒左右才执行,同样,从SecondActivity返回到MainActivity时,SecondActivity的onStop和onDestory方法也是延迟了差不多10秒后才执行,为什么会这样呢?我们并没有在这两个Acivity的onStart和onResume里面做任何耗时操作,现在让我们跟着Android源码一起分析是啥情况。
以SecondActivity返回MainActivity为例,点击返回时,一定会调用activity.finish()方法,Activity.finsh()方法如下:
public void finish() {
finish(DONT_FINISH_TASK_WITH_ACTIVITY);
}
调用了finsh(int finishTask),传入的finishTask = DONT_FINISH_TASK_WITH_ACTIVITY, finsh(int finishTask大致代码如下:
private void finish(int finishTask) {
if (mParent == null) {
...
if (false) Log.v(TAG, "Finishing self: token=" + mToken);
try {
if (resultData != null) {
resultData.prepareToLeaveProcess(this);
}
if (ActivityTaskManager.getService()
.finishActivity(mToken, resultCode, resultData, finishTask)) {
mFinished = true;
}
} catch (RemoteException e) {
// Empty
}
} else {
mParent.finishFromChild(this);
}
...
}
实际上是调用了AMS的finishActivity(…)方法
public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,int finishTask) {
// 调用了ActivityTaskManagerService.finishActivity(…)方法
return mActivityTaskManager.finishActivity(token, resultCode, resultData, finishTask);
}
public final boolean finishActivity(IBinder token, int resultCode, Intent resultData, int finishTask) {
// Refuse possible leaked file descriptors
if (resultData != null && resultData.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized (mGlobalLock) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
return true;
}
...
// note down that the process has finished an activity and is in background activity
// starts grace period
if (r.app != null) {
r.app.setLastActivityFinishTimeIfNeeded(SystemClock.uptimeMillis());
}
final long origId = Binder.clearCallingIdentity();
try {
boolean res;
// finish()方法是传入的参数DONT_FINISH_TASK_WITH_ACTIVITY,所以finishWithRootActivity必定是false
final boolean finishWithRootActivity =
finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;
if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY
|| (finishWithRootActivity && r == rootR)) {
// If requested, remove the task that is associated to this activity only if it
// was the root activity in the task. The result code and data is ignored
// because we don't support returning them across task boundaries. Also, to
// keep backwards compatibility we remove the task from recents when finishing
// task with root activity.
res = mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
finishWithRootActivity, "finish-activity");
if (!res) {
Slog.i(TAG, "Removing task failed to finish activity");