本篇文章主要讲解bindService()绑定Service的过程。(android的版本依旧是26)
通过bindService()绑定一个Service时,最终都是调用的ContextWrapper的bindService()方法,我们来看下这个方法
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
return mBase.bindService(service, conn, flags);
}
上述方法中调用了mBase对象的bindService()方法,mBase的类型是Context,Context的实现类是ContextImpl,我们来看下ContextImpl的bindService()方法
@Override
public boolean bindService(Intent service, ServiceConnection conn,int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) {
// Keep this in sync with
DevicePolicyManager.bindDeviceAdminServiceAsUser.
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
/*
* sd其实指向的是一个ServiceDispatch.InnerConnection的对象
* 最终调用ServiceConnection的onServiceConnected()方法也是通过这个对象
*/
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
//检查合法性
validateServiceIntent(service);
try {
......
//调用ActivityManagerService的bindService()方法
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
......
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
由上述代码可知,相比较startService()的过程,在调用ActivityManagerService的bindService()方法之前,在bindServiceCommon()方法中多一个获取sd对象,即ServiceDispatch.InnerConnection类的对象的过程,mPackageInfo是LoadedApk类的一个引用,我们来看下mPackageInfo.getServiceDispatcher()中到底做了什么
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
//尝试获取缓存
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
sd = map.get(c);
}
if (sd == null) {
/*创建ServiceDispatcher对象
*而在本方法中最终return的sd.getIServiceConnection()的值也是在ServiceDispatcher
*的构造方法中初始化的,稍后的文章中会讲到这一点。
*/
sd = new ServiceDispatcher(c, context, handler, flags);
if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
//其实最终return的是ServiceDispatcher的内部类InnerConnection对象
return sd.getIServiceConnection();
}
}
上述代码中提到,getServiceDispatcher()方法最终返回的sd.getIServiceConnection()是ServiceDispatcher中的内部类InnerConnection对象,我们先来看一下上述方法最终return的sd.getIServiceConnection()到底是什么
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
可以看到该方法最终return的是一个IServiceConnection对象,看样子像是一个跨进程通信要用的东西,那么这个对象是在哪里创建的呢
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
mLocation = new ServiceConnectionLeaked(null);
mLocation.fillInStackTrace();
mFlags = flags;
}
由上述代码可知,mIServiceConnection是在ServiceDispatcher的构造方法中创建的,最终mIServiceConnection引用指向的是以ServiceDispatcher为参数构造的InnerConnection这个内部类的对象。我们来一下InnerConnection这个内部类
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
InnerConnection继承了IServiceConnection.Stub,看样子应该可以进行跨进程间的通信,内部持有了外部类ServiceDispatcher类的弱引用,代码量比较少,除了构造方法之外,只有一个connected()方法,在这个connected()方法中,获取了外部传递过来的ServiceDispatcher对象,并调用了ServiceDispatcher的connected()方法,我们来看下这个方法
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
可以看到connected()方法中会执行RunConnection的run()方法或者doConnected()方法,下面我们来看下RunCon