Android进阶笔记:bindService的流程--源码解析
Android进阶笔记:bindService的流程–源码解析
第⼀次写博客,⽬的也是为了记录⾃⼰在Android学习过程中⾃⼰发现的⼀些值得学习反复琢磨的东西也希望能和⼤家⼀起分享,如果写的有什么不对的地⽅
还请⼤家多多指点。
⾸先想要知道bindService这⼀过程是怎么样实现的,得先找到个路⼝,这个路⼝也很明显,就是Activity中的bindService⽅法。代码如下:
参数很简单都很简单,⽤过的应该都了解。第⼀个参数就是⼀个启动rvice的Intent⽽第⼆个参数是⼀个ServiceConnection的对象。这
个对象的实现⼀般需要实现两个接⼝,如下所⽰:
实现的⽅法中会返回两个参数⼀个是ComponentName另外⼀个是IBinder类型的实例。这个ComponentName其实就是记录⼀个应⽤的
包名已经相关的组件名(例如:包名”ice”,组件名”ice”),⽽这个IBinder类型的对象就
是Service中OnBind⽅法中返回的Binder对象,如下:
具体这中间到底怎么实现的我们还是来看看源码吧。Ctrl按住点击bindService⽅法看到的代码如下:
这⾥很清楚直接就就调⽤了Context的bindService那就直接点进去呗。然后你会看到如下:
反正我⾃⼰⼀开看的时候就蒙了,这是⼀个abstract的⽅法,意思就是真正实现其实在他的⼦类。这这这。。这你让我去哪⾥看怎么实现
bindService过程,还能不能看代码了?
其实,看到这⾥你应该就要往回想想,这个⽅法是刚刚的mBa对象调⽤的,那这个mBa对象⼀定就是已经实现了这个⽅法的⼦类对
象,那我们只要知道这个mBa到底是啥就可以看到这个bindService⽅法真正实现的过程了。这⾥直接给出答案这个mBa其实就是
ContextImpl类的对象,你要问我咋知道的。很简单这个mBa既然是Activity对象的内部成员,那只要了解Activity创建的过程肯定就知
道这是什么了。(具体想知道可以查查Activity创建启动这块的资料,当然我以后也可能会写的哈哈)。
bindService(rviceIntent,rviceConnection,_AUTO_CREATE);
ServiceConnectionrviceInatent=newServiceConnection(){
@Override
publicvoidonServiceConnected(ComponentNamename,IBinderrvice){
}
@Override
publicvoidonServiceDisconnected(ComponentNamename){
}
};
publicIBinderonBind(Intentintent){
returnnull;
}
publicclassContextWrapperextendsContext{
...
ContextmBa;
@Override
publicbooleanbindService(Intentrvice,ServiceConnectionconn,
intflags){
rvice(rvice,conn,flags);
}
...
}
publicabstractbooleanbindService(Intentrvice,@NonNullServiceConnectionconn,
@BindServiceFlagsintflags);
上⾯写了这么多其实也是为了提供了⼀个看源码的思路,当然我也是可以直接就告诉你这个⽅法在哪实现。但是这样就失去了⼀种过程感,
感觉就是在灌输东西死记硬背。有⼀些东西你“知其所以然”以后印象肯定就⾮常的深了(这个也是写给我⾃⼰的“知其然并且知其所以
然”,这也是我开始看源码的⽬的。我⼜忍不住废话多了,骚瑞。。。)。
好了继续上⾯的过程,既然我们知道这个bindService⽅法具体在哪个类⾥⾯实现的我就直接去找到它点进去看看就是了
位置:
这⾥已经把⼀些不太重要的代码省略了,⾸先进⼊bindService⽅法,然后直接进⼊了bindServiceCommon⽅法当中。⽽这个
bindServiceCommon主要是实现了两个步骤,第⼀个是实现了⼀个叫做IServiceConnection的对象,如果有看过⼀些源码的应该知道就
这尿性这命名多半是⼀个IBinder类的⼦类。这⾥我们先“存档”⼀下,记住等下要回来的千万别绕着绕着就忘记刚刚是从哪绕进来
的了(这应该也算是这个⽅法吧,源码毕竟很多,很容易就看到后⾯忘记前⾯了)。
这⾥⾸先我们要去看viceDispatcher这个⽅法,mPackageInfo这个很简单(看⼀下声明就知道了)是⼀个
LoadedApk类的实现对象,那么我们就去找到这个对象咯。
位置:
//bindService
@Override
publicbooleanbindService(Intentrvice,ServiceConnectionconn,intflags){
warnIfCallingFromSystemProcess();
returnbindServiceCommon(rvice,conn,flags,Handle());
}
//bindServiceCommon
privatebooleanbindServiceCommon(Intentrvice,ServiceConnectionconn,intflags,UrHandleur){
IServiceConnectionsd;
...
sd=viceDispatcher(conn,getOuterContext(),
dler(),flags);
...
intres=ault().bindService(
licationThread(),getActivityToken(),rvice,
eTypeIfNeeded(getContentResolver()),
sd,flags,getOpPackageName(),ntifier());
...
}
找到getServiceDispatcher⽅法可以看到其实上⾯⼀坨都是判断⼀下是不是空啊,是不是要创建⼀下啊,是不是要保存⼀下啦,都是浮
云。重要的是最后sd(eDispatcher)对象调⽤了getIServiceConnection()这个⽅法。那我们继续跟踪⼀下看看这个
⽅法的实现。
这个⽅法是属于LoadedApk的⼀个内部类ServiceDispatcher的⼀个⽅法,主要就是返回⼀个IServiceConnection类型的对象,那这个
IServiceConnection类型的对象到底是什么呢,我们就接下来看看ServiceDispatcher这个类到底是怎么样的。
publicfinalIServiceConnectiongetServiceDispatcher(ServiceConnectionc,Contextcontext,Handlerhandler,intflags){
synchronized(mServices){
eDispatchersd=null;
ArrayMap
if(map!=null){
sd=(c);
}
if(sd==null){
sd=newServiceDispatcher(c,context,handler,flags);
if(map==null){
map=newArrayMap
(context,map);
}
(c,sd);
}el{
te(context,handler);
}
rviceConnection();
}
}
IServiceConnectiongetIServiceConnection(){
returnmIServiceConnection;
}
这⾥是⼀个很有有意思的地⽅,这个ServiceDispatcher是LoadedApk的内部类,他内部还有⼀个叫做InnerConnection的内部类。看⼀
下声明:
看声明你就能发现很明显⼀开始的getIServiceConnection()⽅法返回的就是这货!这⼜是⼀个onnection类型
的实例,那我们要的是IServiceConnection类型的实例,那稍微想想就知道onnection肯定直接或者间接的继
承了IServiceConnection。那我们就接着看看InnerConnection这个内部类咯。
InnerConnection类他继承的是⼀个.stub类型的类(类其实⼜extend了IServiceConnection这个类),了解
过aidl的同学应该明⽩这是什么(不懂的可以去学习⼀下AIDL的相关知识),这⾥说⽩了他就是⼀个IBinder类的⼦类主要是⽤来⽀持
IPC(跨进程通信),说⼈话。。。就是⽤来跨进程调⽤⼀些⽅法。这个类总共只有两个⽅法。
⾸先看这个类的第⼀个⽅法————构造⽅法。
staticfinalclassServiceDispatcher{
onnectionmIServiceConnection;
privatefinalServiceConnectionmConnection;
privatefinalContextmContext;
privatefinalHandlermActivityThread;
privatefinalServiceConnectionLeakedmLocation;
privatefinalintmFlags;
ServiceDispatcher(ServiceConnectionconn,Contextcontext,HandleractivityThread,intflags){
mIServiceConnection=newInnerConnection(this);
mConnection=conn;
mContext=context;
mActivityThread=activityThread;
mLocation=newServiceConnectionLeaked(null);
StackTrace();
mFlags=flags;
}
{
finalWeakReference
InnerConnection(eDispatchersd){
mDispatcher=newWeakReference
}
publicvoidconnected(ComponentNamename,IBinderrvice)throwsRemoteException{
eDispatchersd=();
if(sd!=null){
ted(name,rvice);
}
}
}
IServiceConnectiongetIServiceConnection(){
returnmIServiceConnection;
}
...
}
onnectionmIServiceConnection;
...
IServiceConnectiongetIServiceConnection(){
returnmIServiceConnection;
}
他引⽤(弱引⽤)了⼀个他的上级类(ServiceDispatcher)的实例并且保存下来了。这⾥注意,InnerConnection内部类他引⽤了他的
上级类的实例,也就是说InnerConnection可以通过ServiceDispatcher实例来调⽤ServiceDispatcher类中的公有⽅
法,InnerConnection⼜是⼀个⽀持跨进程的类,也就是说InnerConnection可以实现跨进程来调⽤ServiceDispatcher和
InnerConnection这两个类中的所有公有⽅法,形象的说就是⼀个桥梁来连接两个进程之间⽅法的调⽤,这⾥也是我觉得他很有意思的原
因。
说完了构造⽅法,那我们再去看看另外⼀个⽅法connected(ComponentNamename,IBinderrvice)
瞅瞅⽅法名,再瞅瞅参数,怎么就那么眼熟呢?没错,这个⽅法其实就是对我们之前ServiceConnection类中onServiceConnected⽅法的
封装,最后还是会调⽤到iceConnected这个⽅法的,不信再跟踪⼀下源码看看:
很明显吧这个mConnection其实就是⼀开始ServiceDispatcher的构造函数中传进来的ServiceConnection实例,看⼀下他的声明就明⽩
了。最后就是调⽤了iceConnected(name,rvice)这个⽅法。这个地⽅要有⼀点印象,因为后⾯会通过
InnerConnection实例来远程回调这个⽅法。
分析完ServiceDispatcher这个类以及他的内部类InnerConnection,也可以稍微的总结⼀下。
我们⼀开始时为了获得⼀个IServiceConnection类的实例,⽽这个类的实例是通过rviceConnection()⽅法获得
的,这个⽅法⼜调⽤了他的内部类eDispatcher的InnerConnection实例,这个实例通过⼀系列的继承最后⽗类就是
IServiceConnection;是不是有点晕。。。。稍微画⼀下这三个类的关系结构
InnerConnection(eDispatchersd){
mDispatcher=newWeakReference
}
publicvoidconnected(ComponentNamename,IBinderrvice)throwsRemoteException{
eDispatchersd=();
if(sd!=null){
ted(name,rvice);
}
}
//ted
publicvoidconnected(ComponentNamename,IBinderrvice){
if(mActivityThread!=null){
(newRunConnection(name,rvice,0));
}el{
doConnected(name,rvice);
}
}
//ected
publicvoiddoConnected(ComponentNamename,IBinderrvice){
...
//Ifthereisanewrvice,itisnowconnected.
if(rvice!=null){
iceConnected(name,rvice);
}
}
这下这三个类的关系应该很明确了吧。最后拿到的其实就是InnerConnection这东西。
好了休息⼀下,还记得前⾯我有说存档⼀下吗?现在我们也该回到前⾯说的“存档”点了,可别绕晕了啊。
上⾯我们分析了这个sd到底是什么东西(有远程调⽤功能的⼀个东西),有什么⽤(保存数据,实现连接⽅⾯的⽅法,远程调⽤)。那么我
们就继续来分析接下来的⼀块:
其实就调⽤了⼀个⽅法ault().bindService()剩下的那⼀坨都是参数,要知道⼀下的是第⼀个参数其实是⼀
个ApplicationThread类型的实例,他是AtivityThread的内部类,⽽ApplicationThread继承了IApplicationThread也是⼀个IBinder类
型实例,也就是说我们可以运⽤它来远程的调⽤ApplicationThread类中的⽅法。还有别忘记刚刚我们拿到的sd也跟着传进去了,⾄于那个
rvice其实是⼀个intent。
那问题来了ault()到底是⼀个什么东西呢?其实这是⼀个ActivityManagerService的Binder驱动,也是⼀
个IBinder类型的对象。主要是通过这个Binder驱动来跨进程调⽤ActivityManagerService中的⽅法,这⾥就是调⽤了
rvice⽅法。
这⾥我还是给出了ActivityManagerNative类的位置吧。
位置:
那我们就继续去看看rvice这个⽅法。
位置:platformframewo
很简单没什么好说的就是调⽤了ActiveServices中的bindServiceLocked这个⽅法。
位置:platfor
publicfinalclassLoadedApk{
staticfinalclassServiceDispatcher{
{
//tendIServiceConnection
finalWeakReference
}
}
}
sd=viceDispatcher(conn,getOuterContext(),
dler(),flags);
intres=ault().bindService(
licationThread(),getActivityToken(),rvice,
eTypeIfNeeded(getContentResolver()),
sd,flags,getOpPackageName(),ntifier());
publicintbindService(IApplicationThreadcaller,IBindertoken,Intentrvice,StringresolvedType,IServiceConnectionconnection,intflags,Strin
inturId)throwsTransactionTooLargeException{
...
synchronized(this){
rviceLocked(caller,token,rvice,
resolvedType,connection,flags,callingPackage,urId);
}
}
这⾥我做了删减,这个代码其实耐⼼的看⼀下还是很清晰的就是s(ServiceRecord)、b(AppBindRecord)、
c(ConnectionRecord)、callerApp(ProcessRecord)这四个类型的⼀些保存啊之类的操作,⽅便以后调⽤。可以观察⼀下这三个
类的命名,都很有规则都是有⼀个Record后缀,其实就⼀个对应的描述类保存了后⾯要⽤到的信息(如:ServiceRecord,这⾥⾯就存放
了将来要创建Service时所需要的所有信息)
这⾥还是要说明⼀下ServiceRecord是对Service(需要绑定的Service)信息存放,c是对⼀开始我们传进来的IServiceConnection封
装,各种地⽅都保存了这个c⽅便调⽤。
intbindServiceLocked(IApplicationThreadcaller,IBindertoken,Intentrvice,
StringresolvedType,IServiceConnectionconnection,intflags,
StringcallingPackage,inturId)throwsTransactionTooLargeException{
finalProcessRecordcallerApp=ordForAppLocked(caller);
ActivityRecordactivity=null;
if(token!=null){
activity=ackLocked(token);
}
ServiceLookupResultres=
retrieveServiceLocked(rvice,resolvedType,callingPackage,
lingPid(),lingUid(),urId,true,callerFg);
ServiceRecords=;
try{
AppBindRecordb=veAppBindingLocked(rvice,callerApp);
ConnectionRecordc=newConnectionRecord(b,activity,
connection,flags,clientLabel,clientIntent);
IBinderbinder=er();
ArrayList
if(clist==null){
clist=newArrayList
(binder,clist);
}
(c);
(c);
if(activity!=null){
...
(c);
}
(c);
if((flags&_AUTO_CREATE)!=0){
tivity=Millis();
if(bringUpServiceLocked(s,gs(),callerFg,fal)!=null){
return0;
}
}
...
return1;
}
IBinderbinder=er();
⽽这个binder其实可以简单的看做成IServiceConnection,后⾯可以通过它asInterface⽅法获取binder驱动来远程调⽤
IServiceConnection(其实就是IServiceConnection–>InnerConnection–>ServiceDispatcher)⾥⾯的⽅法。然后把这个binder放
到了s(ServiceRecord)的connections的集合中,clist就是⼀个connectionRecord的集合,应为可能不⽌⼀个activity或者组件需要绑
定这个rvice。
接下来我们根据设置的flag(⼀般都是设置成这个)会进⼊到if语句块,然后调⽤bringUpServiceLocked这个⽅法
这⾥很明确既然调⽤了那我们继续动⼿点进去看看呗。
这块代码源码那边其实稍微有点多,但是⼤多是都是进⾏⼀些空值或者变量的判断,⼀些重要的变量如果异常则直接返回不再执⾏。如果正
常则会执⾏到如上所⽰的⽅法。
r就是ServiceRecord刚刚bindServiceLocked⽅法中封装了的对rvice的描述实例(⽤来创建rvice可以简单的理解就是⼀个不成
型的rvice)。
app就是刚刚提到的processRecord变量,刚刚也提到过是⽤来存储⼀些数据(其实也就是当前应⽤相关的数据)。
mAm就是ActivityManagerService的实例
然后最后会执⾏到realStartServiceLocked,看名字real,说明这⾥是真正的开始启动⼀个Service的地⽅,那就继续点进去看看咯。
(binder,clist);
if((flags&_AUTO_CREATE)!=0){
tivity=Millis();
if(bringUpServiceLocked(s,gs(),callerFg,fal)!=null){
return0;
}
}
privatefinalStringbringUpServiceLocked(ServiceRecordr,intintentFlags,booleanexecInFg,booleanwhileRestarting)throwsTransactionTooL
...
if(!isolated){
app=cessRecordLocked(procName,,fal);
if(DEBUG_MU)Slog.v(TAG_MU,"bringUpServiceLocked:="+
+"app="+app);
if(app!=null&&!=null){
try{
kage(eName,nCode,ssStats);
realStartServiceLocked(r,app,execInFg);
returnnull;
}catch(TransactionTooLargeExceptione){
throwe;
}catch(RemoteExceptione){
Slog.w(TAG,"Exceptionwhenstartingrvice"+ame,e);
}
//Ifadeadobjectexceptionwasthrown--fallthroughto
//restarttheapplication.
}
}
...
returnnull;
}
上⾯app就是之前传过来的,⽽这个到底是什么呢,我们去ProcessRecord类⾥⾯去看看。
其实就是之前说到的ApplicationThread的远程接⼝IApplicationThread,就是说可以跨进程的通过它来调⽤ApplicationThread⾥⾯的
⽅法。
既然这样IApplicationThread调⽤了scheduleCreateService这个⽅法,看名字就知道是打算真正的来创建这个Service了。那很简单我
们只要直接去ActivityThread类(ApplicationThread是ActivityThread的内部类所以别找错地⽅哦)⾥⾯去找就⾏了。
这个⽅法全部也只有这⼏⾏很⼩,主要做的⼯作就是发送⼀个消息并且通过token和info来创建了⼀个新的ServiceRecord(真正的东西其
实都在toke和info⾥⾯,这⾥之所以他们能被跨进程传过来其实是因为toke是Ibinder类型⽽info实现了parcelable接⼝)传递给
H(ActivityThread内部的⼀个Handler)处理来创建⼀个Service。那我们就继续去找这个Handler他收到消息具体去⼲什么了。
privatefinalvoidrealStartServiceLocked(ServiceRecordr,
ProcessRecordapp,booleanexecInFg)throwsRemoteException{
...
=app;
...
leCreateService(r,eInfo,
ibilityInfoForPackageLocked(ationInfo),
cState);
tification();
...
requestServiceBindingsLocked(r,execInFg);
updateServiceClientActivitiesLocked(app,null,true);
...
}
finalclassProcessRecord{
...
IApplicationThreadthread;//theactualproc...maybenullonlyif
//'persistent'istrue(inwhichcawe
//areintheprocessoflaunchingtheapp)
...
}
publicfinalvoidscheduleCreateService(IBindertoken,
ServiceInfoinfo,CompatibilityInfocompatInfo,intprocessState){
updateProcessState(processState,fal);
CreateServiceDatas=newCreateServiceData();
=token;
=info;
Info=compatInfo;
ndMessage(_SERVICE,s);
}
这⾥也很简单发送消息给Handler,让handerMessage⽅法来处理消息,然后回调了handleCreateService这个⽅法。这个⽅法⾥⾯就开
始真正的创建了⼀个Service实例。data其实就是ServiceRecord。到这⼀步⼀个rvice的创建算是完成了。但是我们要做的事情还没完
啊!我们讨论的是bindService。回过去看看,我们之前是从leCreateService⽅法⼀路⾛到rvice的创建,那么下⾯
其实还有⼀个⽅法没有完成,就是requestServiceBindingsLocked。
//Handler的回调函数handleMessage
publicvoidhandleMessage(Messagemsg){
switch(){
...
caCREATE_SERVICE:
egin(_TAG_ACTIVITY_MANAGER,"rviceCreate");
handleCreateService((CreateServiceData));
nd(_TAG_ACTIVITY_MANAGER);
...
}
}
//Hander通过handlerMessage回调的⽅法
privatevoidhandleCreateService(CreateServiceDatadata){
LoadedApkpackageInfo=getPackageInfoNoCheck(
ationInfo,Info);
Servicervice=null;
...
oadercl=ssLoader();
rvice=(Service)ass().newInstance();
Applicationapp=plication(fal,mInstrumentation);
(context,this,,,app,
ault());
//te真正回调的地⽅
te();
(,rvice);
...
}
privatefinalvoidrealStartServiceLocked(ServiceRecordr,
ProcessRecordapp,booleanexecInFg)throwsRemoteException{
...
=app;
...
leCreateService(r,eInfo,
ibilityInfoForPackageLocked(ationInfo),
cState);
tification();
...
//就是这个⽅法
requestServiceBindingsLocked(r,execInFg);
updateServiceClientActivitiesLocked(app,null,true);
...
}
看名字就知道是请求绑定rvice,那就继续呗。离胜利不远了!
这⾥就很简单了,就是调⽤了⼀下requestServiceBindingLocked。这⾥为什么弄个循环去做这件事情呢,我想也是应为⼀个Service可能
会被多个Activity去绑定所以需要⼀个循环来处理(具体还没研究过)。
看看⽅法⾥⾯怎么实现的。其实还是那个尿性,就是把需要的东西全部都通过binder驱动来远程传给
ActivtyThread(ApplicationThread)的scheduleBindService⽅法去实现那么⽼样⼦这⾥直接去找⼀下这个⽅法是怎么实现的就好了。
没错!⽼套路,还是发消息,这⾥我就不具体贴代码了最后通过handlerMessage⽅法来调⽤handleBindService⽅法,参数也仍然是
ServiceRecord对象,这⾥我们就直接看看这个⽅法吧。
这⾥因为之前Service已经创建过了并且保存在了mServices这个集合⾥⾯了
privatefinalvoidrequestServiceBindingsLocked(ServiceRecordr,booleanexecInFg)
throwsTransactionTooLargeException{
for(inti=()-1;i>=0;i--){
IntentBindRecordibr=t(i);
if(!requestServiceBindingLocked(r,ibr,execInFg,fal)){
break;
}
}
}
privatefinalbooleanrequestServiceBindingLocked(ServiceRecordr,IntentBindRecordi,
booleanexecInFg,booleanrebind)throwsTransactionTooLargeException{
...
leBindService(r,ent(),rebind,
cState);
...
returntrue;
}
publicfinalvoidscheduleBindService(IBindertoken,Intentintent,
booleanrebind,intprocessState){
updateProcessState(processState,fal);
BindServiceDatas=newBindServiceData();
=token;
=intent;
=rebind;
if(DEBUG_SERVICE)
Slog.v(TAG,"scheduleBindServicetoken="+token+"intent="+intent+"uid="
+lingUid()+"pid="+lingPid());
ndMessage(_SERVICE,s);
}
privatevoidhandleBindService(BindServiceDatadata){
Services=();
...
if(!){
IBinderbinder=();
ault().publishService(
,,binder);
}
...
}
所以直接取出来了就可以了。好了,回过头然后⽅法⾥⾯通过调⽤Service的onBind⽅法来获得⼀个binder对象,这个⽅法只要继承了
Service并且要实现绑定的话是肯定要重写的,这⾥⾯返回的Binder对象是⾃⼰传⼊的可以是null。最后⼜是通过
ault()(之前也解释过,这个其实就是⼀个ActivityManagerService的远程驱动)来调⽤publishService
这个⽅法,那我们就再回去,在去ActivityManagerService⾥⾯找这个⽅法;
没什么营养,反正就是各种异常判断⼀下最后调⽤了mServices(ActiveServices类的实例)的publishServiceLocked⽅法。
这⾥就是从ServiceRecord⾥⾯取出了ConnectionRecord然后调⽤了ted(,rvice);这么⼀个⽅法。⾄于细⼼的
同学应该想起来之前bindServiceLocked⾥⾯创建完ServiceRecord的时候有这么⼀段代码
没错,这个ConnectionRecord就是那时候存进去的。
privatevoidhandleCreateService(CreateServiceDatadata){
...
(,rvice);
...
}
publicvoidpublishService(IBindertoken,Intentintent,IBinderrvice){
//Refupossibleleakedfiledescriptors
if(intent!=null&&eDescriptors()==true){
thrownewIllegalArgumentException("FiledescriptorspasdinIntent");
}
synchronized(this){
if(!(tokeninstanceofServiceRecord)){
thrownewIllegalArgumentException("Invalidrvicetoken");
}
hServiceLocked((ServiceRecord)token,intent,rvice);
}
}
voidpublishServiceLocked(ServiceRecordr,Intentintent,IBinderrvice){
...
for(intconni=()-1;conni>=0;conni--){
ArrayList
for(inti=0;i<();i++){
ConnectionRecordc=(i);
...
try{
ted(,rvice);
}catch(Exceptione){
Slog.w(TAG,"Failurendingrvice"++
"toconnection"+er()+
"(in"+sName+")",e);
}
}
}
...
}
if(clist==null){
clist=newArrayList
(binder,clist);
}
ted(,rvice)这个⽅法⾥⾯的rvice就是刚刚创建的(我们⾃⼰从来的⽅法)返回回来的binder
对象,⽽这个其实是⼀个ComponentName的对象。怎么样,是不是感觉这个⽅法的参数有⼀点熟悉啊!这不就是
ServiceConnection对象⾥⾯的onServiceConnected(ComponentNamename,IBinderrvice)⽅法要的参数嘛。那这个⽅法百分之
⼋⼗就是辗转调⽤到了这个⽅法咯。那我们就去看看这个到底是什么
看吧,这就是我之前说的那个Inn什么的记起来了嘛(InnerConnection),我之前也提到过“最后就是调⽤了
iceConnected(name,rvice)这个⽅法。这个地⽅要有⼀点印象,因为后⾯会通过InnerConnection实例来远程
回调这个⽅法。”忘记在哪个步骤的可以ctrl+f搜⼀下这句话回过去再看看。
到上⾯的步骤其实bindService的流程已经分析的差不多了,可能有⼀些多,凡是思路还是很清晰的。
总结⼀下其实就是把⼀些真正需要创建Service要⽤的东西全部都给ActivityManagerService来做(跨进程)然后做完了在丢给
ActivityThread(ApplicationThread)去真正的创建。
从上⾯的源码其实也可以看出iceConnected这个回调是通过跨进程来调⽤的,⽽最后通过
IServiceConnection来调⽤connected⽅法(这个⽅法真正回调了onServiceConnected⽅法)
⽽connected⽅法所在的类的实例是创建在UI线程的
finalclassConnectionRecord{
...
finalIServiceConnectionconn;//Theclientconnection.
...
}
因此onServiceConnected这个⽅法其实是运⾏在主线程中的,如果Server端的⽅法是耗时操作最好起⼀个线程来调⽤,因为在调⽤
IBinder的transact⽅法时当前线程是会挂起的!
第⼀次写博客可能有点乱,这之中也花了好多时间,不管怎么样写出来了也⽅便以后⾃⼰查看。省的我那天脑⼦⼀抽⼜忘记了。
//
sd=viceDispatcher(conn,getOuterContext(),
dler(),flags);
publicfinalIServiceConnectiongetServiceDispatcher(ServiceConnectionc,
Contextcontext,Handlerhandler,intflags){
...
sd=newServiceDispatcher(c,context,handler,flags);
...
}
ServiceDispatcher(ServiceConnectionconn,Contextcontext,HandleractivityThread,intflags){
mIServiceConnection=newInnerConnection(this);
...
}
{
...
publicvoidconnected(ComponentNamename,IBinderrvice)throwsRemoteException{
eDispatchersd=();
if(sd!=null){
ted(name,rvice);
}
}
}
publicvoidconnected(ComponentNamename,IBinderrvice){
if(mActivityThread!=null){
(newRunConnection(name,rvice,0));
}el{
doConnected(name,rvice);
}
}
publicvoiddoConnected(ComponentNamename,IBinderrvice){
...
//Ifthereisanewrvice,itisnowconnected.
if(rvice!=null){
iceConnected(name,rvice);
}
}
本文发布于:2023-03-12 05:02:51,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/zhishi/a/1678568572138087.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:尿性是什么意思.doc
本文 PDF 下载地址:尿性是什么意思.pdf
留言与评论(共有 0 条评论) |