深入分析Activity onStop()生命周期延时10s回调的原因

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");
        
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值