写点什么

BindService 的生命周期分析【我读源码你不读,我吃螃蟹你吃土 (1)

用户头像
Android架构
关注
发布于: 10 小时前

2.1、分析阶段 1

Android 系统是通过消息驱动机制进行工作的,在 Activity 被销毁时,ActivityThread 的 scheduleDestroyActivity 方法会被执行,如下所示:


public final void scheduleDestroyActivity(IBinder token, boolean finishing,int configChanges) {sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,configChanges);}


逻辑很清晰,直接调用了 sendMessage 方法,发送了一个类型为 H.DESTROY_ACTIVITY 的消息。最终 ActivityThread 的内部类 H 对该消息进行了处理,其处理逻辑如下所示:


public void handleMessage(Message msg) {


switch (msg.what) {case DESTROY_ACTIVITY:handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,msg.arg2, false);break;}}


handleMessage 方法中调用了 handleDestroyActivity 方法,如下所示:


private void handleDestroyActivity(IBinder token, boolean finishing,int configChanges, boolean getNonConfigInstance) {...省略 if (finishing) {try {ActivityManager.getService().activityDestroyed(token);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}mSomeActivitiesChanged = true;}


handleDestroyActivity 方法最终调用了 ActivityManagerService 的 activityDestroyed 方法。

2.2、分析阶段 2

承接上面的逻辑,我们跳转到 ActivityManagerService,并找到 activityDestroyed 方法,如下所示:


public final void activityDestroyed(IBinder token) {synchronized (this) {ActivityStack stack = ActivityRecord.getStackLocked(token);if (stack != null) {stack.activityDestroyedLocked(token, "activityDestroyed");}}}


在 activityDestroyed 方法中,通过 ActivityRecord.getStackLocked 方法获取一个 ActivityStack 对象,并调用 ActivityStack 的 activityDestroyedLocked 方法,如下所示:


final void activityDestroyedLocked(IBinder token, String reason) {final long origId = Binder.clearCallingIdentity();try {ActivityRecord r = ActivityRecord.forTokenLocked(token);if (r != null) {mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);}


if (isInStackLocked(r) != null) {if (r.state == ActivityState.DESTROYING) {cleanUpActivityLocked(r, true, false);removeActivityFromHistoryLocked(r, reason);}}mStackSupervisor.resumeFocusedStackTopActivityLocked();} finally {Binder.restoreCallingIdentity(origId);}}


当判断 ActivityRecord 对象的 state 为 ActivityState.DESTROYING 时,又调用了 cleanUpActivityLocked 方法,注意这里的第二个参数值为 true。如下所示:


private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {onActivityRemovedFromStack(r);


r.deferRelaunchUntilPaused = false;r.frozenBeforeDestroy = false;


...省略


if (cleanServices) {cleanUpActivityServicesLocked(r);}


removeTimeoutsForActivityLocked(r);mWindowManager.notifyAppRelaunchesCleared(r.appToken);}


从上一步骤可以看到,cleanServices 的参数值为 true,所以这里调用了 cleanUpActivityServicesLocked 方法,如下所示:


private void cleanUpActivityServicesLocked(ActivityRecord r) {if (r.connections != null) {Iterator<ConnectionRecord> it = r.connections.iterator();while (it.hasNext()) {ConnectionRecord c = it.next();mService.mServices.removeConnectionLocked(c, null, r);}r.connections = null;}}

2.3、分析阶段 3

承接上面的逻辑,在 cleanUpActivityServicesLocked 方法中,执行了一个判空操作 r.connection != null,而从[Service 的工作过程](


)这篇文章可知,当 Service 绑定在 Activity 时,在 ActiveService 类的 bindServiceLocked 方法中会将为 ActivityRecord 对象的 connections 赋值。因此得出以下结论:


当 Activity 没有绑定任何 Service 时,然后 cleanUpActivityServicesLocked 方法内的逻辑并不会执行


所以,当 Activity 绑定了 Service 时,会继续执行 ActiveServices 的 removeConnectionLocked 方法。如下所示:


void removeConnectionLocked(ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {IBinder binder = c.conn.asBinder();AppBindRecord b = c.binding;ServiceRecord s = b.service;ArrayList<ConnectionRecord> clist = s.connections.get(binder);if (clist != null) {clist.remove(c);if (clist.size() == 0) {s.connections.remove(binder);}}b.connections.remove(c);if (c.activity != null && c.activity != skipAct) {if (c.activity.connections != null) {//1、将 ConnectionRecord 对象从 ActivityRecord 对象的 connections 中去掉 c.activity.connections.remove(c);}}


...省略 if (!c.serviceDead) {if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0&& b.intent.hasBound) {try {bumpServiceExecutingLocked(s, false, "unbind");if (b.client != s.app && (c.flags&Context.BIND_WAIVE_PRIORITY) == 0&& s.app.setProcState <= ActivityManager.PROCESS_STATE_RECEIVER) {mAm.updateLruProcessLocked(s.app, false, null);}mAm.updateOomAdjLocked(s.app, true);b.intent.hasBound = false;b.intent.doRebind = false;s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());} catch (Exception e) {Slog.w(TAG, "Exception when unbinding service " + s.


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


shortName, e);serviceProcessGoneLocked(s);}}mPendingServices.remove(s);


if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
BindService的生命周期分析【我读源码你不读,我吃螃蟹你吃土(1)