Android进阶笔记:bindService的流程--源码解析
Android进阶笔记:bindService的流程–源码解析
第⼀次写博客,⽬的也是为了记录⾃⼰在Android学习过程中⾃⼰发现的⼀些值得学习反复琢磨的东西也希望能和⼤家⼀起分享,如果写的有什么不对的地⽅还请⼤家多多指点。
⾸先想要知道bindService这⼀过程是怎么样实现的,得先到个路⼝,这个路⼝也很明显,就是Activity中的bindService⽅法。代码如下:bindService(serviceIntent,serviceConnection, Service.BIND_AUTO_CREATE);
参数很简单都很简单,⽤过的应该都了解。第⼀个参数就是⼀个启动service的Intent⽽第⼆个参数是⼀个ServiceConnection的对象。这个对象的实现⼀般需要实现两个接⼝,如下所⽰:
ServiceConnection serviceInatent = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
实现的⽅法中会返回两个参数⼀个是ComponentName 另外⼀个是IBinder类型的实例。这个ComponentName其实就是记录⼀个应⽤的包名已经相关的组件名(例如:包名”service”,组件名”service”),⽽这个IBinder类型的对象就是Service中OnBind⽅法中返回的Binder对象,如下:
public IBinder onBind(Intent intent) {
return null;
}
具体这中间到底怎么实现的我们还是来看看源码吧。Ctrl按住点击bindService⽅法看到的代码如下:
public class ContextWrapper extends Context {
...
Context mBase;
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
...
}
这⾥很清楚直接就就调⽤了Context的bindService那就直接点进去呗。然后你会看到如下:
制作android软件流程
public abstract boolean bindService(Intent service, @NonNull ServiceConnection conn,
@BindServiceFlags int flags);
反正我⾃⼰⼀开看的时候就蒙了,这是⼀个abstract的⽅法,意思就是真正实现其实在他的⼦类。这这这。。这你让我去哪⾥看怎么实现bindService过程,还能不能看代码了?
其实,看到这⾥你应该就要往回想想,这个⽅法是刚刚的mBase对象调⽤的,那这个mBase对象⼀定就是已经实现了这个⽅法的⼦类对象,那我们只要知道这个mBase到底是啥就可以看到这个bindService⽅法真正实现的过程了。这⾥直接给出答案这个mBase其实就是ContextImpl类的对象,你要问我咋知道的。很简单这个mBase既然是Activity对象的内部成员,那只要了解Activity创建的过程肯定就知道这是什么了。(具体想知道可以查查Activity创建启动这块的资料,当然我以后也可能会写的哈哈)。
上⾯写了这么多其实也是为了提供了⼀个看源码的思路,当然我也是可以直接就告诉你这个⽅法在哪实现。但是这样就失去了⼀种过程感,感觉就是在灌输东西死记硬背。有⼀些东西你“知其所以然”以后印象肯定就⾮常的深了(这个也是写给我⾃⼰的“知其然并且知其所以然”,这也是我开始看源码的⽬的。我⼜忍不住废话多了,骚瑞。。。)。
好了继续上⾯的过程,既然我们知道这个bindService⽅法具体在哪个类⾥⾯实现的我就直接去到它点进去看看就是了
位置:platform\frameworks\base\core\java\android\app\ContextImpl.java
// bindService
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, UserHandle());
}
// bindServiceCommon
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, UserHandle user) {
IServiceConnection sd;
...
sd = ServiceDispatcher(conn, getOuterContext(),
...
int res = Default().bindService(
sd, flags, getOpPackageName(), Identifier());
...
}
这⾥已经把⼀些不太重要的代码省略了,⾸先进⼊bindService⽅法,然后直接进⼊了bindServiceCommon⽅法当中。⽽这个bindServiceCommon主要是实现了两个步骤,第⼀个是实现了⼀个叫做IServiceConnection的对象,如果有看过⼀些源码的应该知道就这尿性这命名多半是⼀个IBinder类的⼦类。这⾥我们先“存档”⼀下,记住等下要回来的千万别绕着绕着就忘记刚刚是从哪绕进来的了(这应该也算是这个⽅法吧,源码毕竟很多,很容易就看到后⾯忘记前⾯了)。
这⾥⾸先我们要去看ServiceDispatcher这个⽅法,mPackageInfo这个很简单(看⼀下声明就知道了)是⼀个LoadedApk类的实现对象,那么我们就去到这个对象咯。
位置:platform\frameworks\base\core\java\android\app\LoadedApk.java
public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = (context);
if (map != null) {
sd = (c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
IServiceConnection();
}
}
到getServiceDispatcher⽅法可以看到其实上⾯⼀坨都是判断⼀下是不是空啊,是不是要创建⼀下啊,是不是要保存⼀下啦,都是浮云。重要的是最后sd(LoadedApk.ServiceDispatcher)对象调⽤了getIServiceConnection()这个⽅法。那我们继续跟踪⼀下看看这个⽅法的实现。
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
这个⽅法是属于LoadedApk的⼀个内部类ServiceDispatcher 的⼀个⽅法,主要就是返回⼀个IServiceConnection 类型的对象,那这个IServiceConnection 类型的对象到底是什么呢,我们就接下来看看ServiceDispatcher这个类到底是怎么样的。
static final class ServiceDispatcher {
private final ServiceDispatcher.InnerConnection mIServiceConnection;
private final ServiceConnection mConnection;
private final Context mContext;
private final Handler mActivityThread;
private final ServiceConnectionLeaked mLocation;
private final int mFlags;
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;
}
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) throws RemoteException {
LoadedApk.ServiceDispatcher sd = ();
if (sd != null) {
}
}
}
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
...
}
这⾥是⼀个很有有意思的地⽅,这个ServiceDispatcher 是LoadedApk的内部类,他内部还有⼀个叫做InnerConnection 的内部类。看⼀下声明:
private final ServiceDispatcher.InnerConnection mIServiceConnection;
...
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
看声明你就能发现很明显⼀开始的getIServiceConnection()⽅法返回的就是这货!这⼜是⼀个ServiceDispatcher.InnerConnection类型的实例,那我们要的是IServiceConnection 类型的实例,那稍微想想就知道ServiceDispatcher.InnerConnection肯定直接或者间接的继承了IServiceConnection 。那我们就接着看看InnerConnection这个内部类咯。
InnerConnection类他继承的是⼀个.stub类型的类(IServiceConnection.Stub类其实⼜extend了IServiceConnection这个类),了解过aidl的同学应该明⽩这是什么(不懂的可以去学习⼀下AIDL的相关知识),这⾥说⽩了他就是⼀个IBinder类的⼦类主要是⽤来⽀持
IPC(跨进程通信),说⼈话。。。就是⽤来跨进程调⽤⼀些⽅法。这个类总共只有两个⽅法。
⾸先看这个类的第⼀个⽅法————构造⽅法。
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
他引⽤(弱引⽤)了⼀个他的上级类(ServiceDispatcher )的实例并且保存下来了。这⾥注意,InnerConnection内部类他引⽤了他的上级类的实例,也就是说InnerConnection可以通过ServiceDispatcher 实例来调⽤ServiceDispatcher 类中的公有⽅
法,InnerConnection⼜是⼀个⽀持跨进程的类,也就是说InnerConnection可以实现跨进程来调⽤ServiceDispatcher 和InnerConnection这两个类中的所有公有⽅法,形象的说就是⼀个桥梁来连接两个进程之间⽅法的调⽤,这⾥也是我觉得他很有意思的原因。
说完了构造⽅法,那我们再去看看另外⼀个⽅法connected(ComponentName name, IBinder service)
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = ();
if (sd != null) {
}
}
瞅瞅⽅法名,再瞅瞅参数,怎么就那么眼熟呢?没错,这个⽅法其实就是对我们之前ServiceConnection类中onServiceConnected⽅法的封装,最后还是会调⽤到ServiceConnected这个⽅法的,不信再跟踪⼀下源码看看:
//ted
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, service);
}
}
//ServiceDispatcher.doConnected
public void doConnected(ComponentName name, IBinder service) {
...
// If there is a new service, it is now connected.
if (service != null) {
}
}
很明显吧这个mConnection其实就是⼀开始ServiceDispatcher 的构造函数中传进来的ServiceConnection实例,看⼀下他的声明就明⽩了。最后就是调⽤了 ServiceConnected(name, service)这个⽅法。这个地⽅要有⼀点印象,因为后⾯会通过InnerConnection实例来远程回调这个⽅法。
分析完ServiceDispatcher 这个类以及他的内部类 InnerConnection,也可以稍微的总结⼀下。
我们⼀开始时为了获得⼀个IServiceConnection类的实例,⽽这个类的实例是通过IServiceConnection()⽅法获得的,这个⽅法⼜调⽤了他的内部类LoadedApk.ServiceDispatcher 的 InnerConnection实例,这个实例通过⼀系列的继承最后⽗类就是IServiceConnection;是不是有点晕。。。。稍微画⼀下这三个类的关系结构
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论