BindService 的生命周期分析【我读源码你不读,我吃螃蟹你吃土 (1)
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.
shortName, e);serviceProcessGoneLocked(s);}}mPendingServices.remove(s);
if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
评论