Android面试题之四大组件+Fragment,包括Activity、Service、广播、ContentProvider和Fragment。
本文是我一点点归纳总结的干货,但是难免有疏忽和遗漏,希望不吝赐教。
转载请注明链接:https://blog.csdn.net/feather_wch/article/details/81136168
Android面试题-四大组件(73题)
版本:2018/8/3-1(2113)
1、四大组件的注册和调用方式
- Activity、Service、ContenProvider必须在
AndroidManifest
中注册BroadcastReceiver
可以在AndroidManifest
中注册,也可以代码
中注册- Activity、Service、ContenProvider的调用需要借助
Intent
BroadcastReceiver
不需要借助Intent
Activity
2、Activity是什么?
- 一种
展示型组件
,用于展示界面,并且与用户进行交互。- Activity的启动由
Intent
触发,Intent
可分为隐式Intent
和显式Intent
- 显式
Intent
需要明确指向一个Activity
- 隐式
Intent
可以指向一个或者多个Activity
组件,也可能没有任何Activity
处理该隐式Intent
Activity
具有特定的启动模式
,也可以通过finish
方法结束运行。
3、Activity启动流程中涉及的重要角色
Instrumentation:
监控应用与系统相关的交互行为。ActivityManagerService
:组件管理的调度中心,基本上什么都不干,但是什么都管。ActivityStarter
:Activity启动的管理器
。处理Intent和Flag
对Activity启动
的影响。ActivityStackSupervisor
:管理任务栈
。ActivityStack
:管理任务栈中的ActivityActivityThread
:主线程/UI线程,完成四大组件相关工作以及APP各种主要的任务。
ActivityStackSupervisor
是高版本才有的类,在系统支持多屏后
,需要去管理多个ActivityStack
4、App的启动流程
- 图标点击:
Lancher进程
会通过Binder机制通知ActivityManagerService
去进行ActivityC黄建等相关工作。AMS
会让ActivityStarter(启动管理器)处理Intent和Flag
,然后以Socket方式
去通知Zygote进程
- Zygote进程会进行孵化(虚拟机和资源的复制—以加快启动速度), 然后fork出新进程。
新进程
中会创建ActivityThread实例
,在RuntimeInit.zygoteInit()中会调用invokeStaticMain,其内部会执行ActivityThred的main()方法- ActivityThread中会创建Looper,开启消息循环
- 最后会进行Activity生命周期的回调-onCreate、onStart等方法
状态
5、Activity的状态
- 三种
常驻状态
和多个中间态
Resumed(运行状态)
:activity处于前台,用户可以进行交互。Paused(暂停状态)
: activity被部分遮挡,可见,不可交互。Stopped(停滞状态)
:activity不可见,不可交互。
6、Activity的通信方式有哪些?
- BroadcastReceiver和LocalBroadcastReceiver
- EventBus
- startActivityForResult
启动流程
7、Activity的启动方法
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
startActivity(intent);
8、Activity的启动流程流程图和要点
graph TD;
1(startActivity);
2(startActivityForResult);
3(mInstrumentation.execStartActivity);
4(ActivityManager.getService.startActivity);
5(checkStartActivityResult);
6(realStartActivityLocked);
7(app.thread.scheduleLaunchActivity);
8(sendMessage-H.LAUNCH_ACTIVITY);
9(handleMessage);
10(handleLaunchActivity);
11(WindowManagerGlobal.initialize);
12(performLaunchActivity);
13(handleResumeActivity);
1-->2;
2-->3;
3-->4;
3-->5;
4-->6;
6-->7;
7-->8;
8-->9;
9-->10;
10-->11;
10-->12;
10-->13;
graph TD;
12(performLaunchActivity);
14(getPackageInfo);
15(mInstrumentation.<br/>newActivity);
16(r.packageInfo.<br/>makeApplication);
17(activity.attach);
18(mInstrumentation.<br/>callActivityOnCreate);
19(attachBaseContext);
20(mUiThread/mApplication);
21(new PhoneWindow);
22(mWindow.<br/>setWindowManager);
23(mWindow.<br/>setContainer);
24(mWindow.<br/>getWindowManager);
12-->14;
12-->15;
12-->16;
12-->17;
12-->18;
17-->19;
17-->20;
17-->21;
17-->22;
17-->23;
17-->24;
graph TD;
13(handleResumeActivity);
25(performResumeActivity);
26(r.activity.getWindow);
27(r.window.getDecorView);
28(a.getWindowManager);
29(wm.addView);
13-->25;
13-->26;
13-->27;
13-->28;
13-->29;
- startActivity: 所有
startActivity()
方法最终会调用startActivityForResult()
方法- startActivityForResult: 内部执行
mInstrumentation.execStartActivity
.- mInstrumentation.execStartActivity:
Instrucmentation用于监控应用和系统的交互行为
, 执行4、5两步的方法
- ActivityManager.getService.startActivity(): 获取到
AMS
并且执行startActivity()
- checkStartActivityResult():检查启动Activity的结果,没有成功启动就会抛出异常,例如Activity没有注册
- realStartActivityLocked:AMS执行startActivity会经过
Activitystack
后执行到ActivityStackSupervisor
的该方法。会执行app.thread.scheduleLaunchActivity()
- app.thread.scheduleLaunchActivity: app.thread是IApplicationThread这个Binder类型接口, 发送消息
H.LAUNCH_ACTIVITY
给Handler H处理。- sendMessage-H.LAUNCH_ACTIVITY: 发送消息给Handler
- handleMessage: 会执行
handleLaunchActivity
- handleLaunchActivity: 启动工作,主要进行
11、12、13三步的功能
- WindowManagerGlobal.initialize() : 初始化
WM
- performLaunchActivity:会进行
14、15、16、17、18五步的工作
- handleResumeActivity:主要进行
25、26、27、28、29五步的功能
- getPackageInfo: 从
ActivityClientRecord
中获取到待启动的Activity的组件信息- mInstrumentation.newActivity: 使用类加载器创建Activity对象
- r.packageInfo.makeApplication: 通过
LoadedApk
的方法创建Applicayiton对象,该对象唯一,不会重复创建。- activity.attach: 调用该方法前会先创建
ContexnImpl
对象,然后调用该方法去完成Window的创建并且建立Activity和Window的关联。主要进行19、20、21、22、23、24 六步的工作
- mInstrumentation.callActivityOnCreate: 调用Activity的
onCreate()
- attachBaseContext(context): 建立Context和Activity的联系:本质就是将ContextImpl实例作为成员变量保存在Activity内部。
- mUiThread/mApplication: 将UI线程和application保存到Activity内部(
成员变量
)- new PhoneWindow(this): 创建Window(
PhoneWindow
), 并进行初始化工作- mWindow.setWindowManager: 给
Window
设置WindowManager
—通过context.getSystemService从WMS
中获取- mWindow.setContainer(mParent.getWindow()): 将当前Window所处的容器设置为父Activity的Window
- mWindowManager = mWindow.getWindowManager(): 将
WM
变量作为成员变量保存到Activity内部- performResumeActivity: 通过Instrucmentation调用onStart和onResume
- r.activity.getWindow(): 获取到Window(在Activity的attach方法中创建了PhoneWindow)
- r.window.getDecorView(): 创建DecorView,设置为不可见INVISIBLE, 并且Activity内部保存了DecorView
- a.getWindowManager(): 获取到WindowManager
- wm.addView(decor, l): WM的addView方法将DecorView添加到Window中
performLaunchActivity
9、Activitiy启动流程中performLaunchActivity的作用?(5种)
- 从ActivityClientRecord中获取到待启动的Activity的
组件信息
- 使用类加载器
创建Activity对象
- 通过LoadedApk的方法
创建Applicayiton对象
,该对象唯一,不会重复创建。- 会创建
ContextImpl
并且建立Context和Activity的联系,以及创建PhoneWindow
,建立Window和Activity的联系。- 调用Activity的
onCreate()
activity.attach
10、Activitiy启动流程中activity.attach的作用?(6种)
- 建立
Context
与Activity的联系。- 建立
UIThread/Application
与Activity的联系。- 创建
Window(PhoneWindow对象)
,建立与Activity的联系。- 给
Window
设置父容器
为父Activity的window
。- 给
Window
设置WindowManager
- 建立
WindowManager
与Activity的联系。
handleResumeActivity
11、Activity启动流程中handleResumeActivity的作用?(5种)
- 执行
onStart()、onResume()
—利用Instrucmentation
- 获取
Window
- 创建
DecorView
、设置为不可见INVISIBLE
、建立DecorView
和Activity的联系。- 获取Activity的
WindowManager
- 调用
WindowManager.addView(decorView, ...)
将DecorView添加到WM中,完成显示的工作。
关系建立
12、如何创建Activity对象?
ActivityThread.java
中performLaunchActivity()
方法内,通过Instrucmentation
的newActivity()
方法,通过类加载器进行创建。
13、如何创建Application对象?
ActivityThread.java
中performLaunchActivity()
方法内,通过LoadedApk
的makeApplication()
方法创建Application对象。
14、如何建立Context/UIThread/Application/Window/WindowManager与Activity的联系?
activity的attach
方法中attach()
在ActivityThread
的performLaunchActivity
中执行。
生命周期回调
15、onCreate在哪里被调用?
- performLaunchActivity通过
Instrumentation
调用
16、onStart、onCreate在哪里被调用?
handleResumeActvity
中
startActivity源码
17、Activity的startActivity源码流程详解
//Activity.java
//1. 所有`startActivity()`方法最终会调用`startActivityForResult()`方法:
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
//2. 父亲不为Null
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
//3. Instrumentation的execStartActivity去启动Activity
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(),//获取ApplicationThread
mToken, this,
intent, requestCode, options);
...
} else {
...
}
}
//Instrumentation.java
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
...省略...
try {
/**===============================================
* 1.开启Activity
* 1-获取到IActivityManager的Binder对象
* 2-通过IPC让ActivityManagerService执行startActivity方法
*===============================================*/
int result = ActivityManager.getService() //Binder对象
.startActivity(whoThread, ... ,options);
/**===============================================
*2. 检查启动Activity的结果
* 没有成功启动就会抛出异常,例如Activity没有注册:
* Unable to find explicit activity class...have you declared this activity in your AndroidManifest.xml?"
*===============================================*/
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
/**
* ActivityManagerService处理startActivity流程:
* startActivity() -> startActivityAsUser -> ...
* -> ActivityStack的resumeTopActivityUncheckedLocked() -> ...
* -> ActivityStackSupervisor的`realStartActivityLocked方法`
*/
//ActivityManagerService.java
public final int startActivity(IApplicationThread caller, ...,Bundle bOptions) {
return startActivityAsUser(caller, ...,UserHandle.getCallingUserId());
}
//ActivityStackSupervisor.java
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {
......
//app.thread的类型为IApplicationThread
/**============================================================
* app.thread的类型为IApplicationThread(继承IInterface接口-Binder类型接口)
* --内部包含大量Activity和Service启动/停止相关功能
* --具体实现:ActivityThread(继承了ApplicationThreadNative)
* * ApplicationThreadNative继承Binder并且实现了IApplicationThread接口
* (ApplicationThreadNative和系统为AIDL文件生成的类的作用是一样的)
*==============================================================*/
app.thread.scheduleLaunchActivity(new Intent(r.intent), ... ,profilerInfo);
......
}
//ActivityThread.java的内部类:ApplicationThread
public final void scheduleLaunchActivity(Intent intent, IBinder token, ...,ProfilerInfo profilerInfo) {
//1. 保存ActivityClientRecord需要的所有数据
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
...
r.overrideConfig = overrideConfig;
//2. 发送消息给Handler H处理
sendMessage(H.LAUNCH_ACTIVITY, r);
}
//ActivityThread.java
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
......
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
//1. 交给`ActivityThread`的`handleLaunchActivity`处理
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
}
break;
}
}
}
//ActivityThread.java
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
......
//0. 创建Activity前初始化WindowManagerGlobal
WindowManagerGlobal.initialize();
//1. 完成Activity对象的创建和启动过程
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
//2. 调用Activity的onResume这一生命周期
handleResumeActivity(r.token, ... ,reason);
} else {
//3. 如果出错,会finishActivity
ActivityManager.getService().finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
}
}
//ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//1. 从ActivityClientRecord中获取待启动的Activity的组件信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE);
}
...
//2. 通过Instrumentation的newActivity方法使用类加载器创建Activity对象
Activity activity = null;
java.lang.ClassLoader cl = appContext.getClassLoader();
// 实现简单,就是通过类加载器来创建Activity对象
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
...
/**============================================================
* 3. 通过LoadedApk的makeApplication方法创建Application对象
* 如果Application已经被创建,则不会重复创建-Application对象唯一
* 1-内部是通过Instruction来完成,也是通过类加载器来实现
* 2-Application创建好后,系统会通过Instruction的
* callApplicationOnCreate()来调用Application的onCreate()方法
*============================================================*/
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
/**===============================================================
*4. 创建ContextImpl对象并通过Activity的attach方法来完成一些重要的数据初始化
* -ContextImpl是Context的具体实现,ContextImpl通过Activity的attach方法和Activity建立关联
* -attach方法中Activity会完成Window的创建并且建立自己和Window的关联
*===============================================================*/
ContextImpl appContext = createBaseContextForActivity(r);
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
...
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
...
//5. 调用Activity的onCreate方法——Activity完成了整个启动过程
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
...
return activity;
}
//Activity.java
final void attach(Context context, ActivityThread aThread, ...) {
//1. 建立Context和Activity的关联
attachBaseContext(context);
//2. 数据初始化: UI线程为当前线程, application等等
mUiThread = Thread.currentThread();
mApplication = application;
...
//3. 创建Window(PhoneWindow)
mWindow = new PhoneWindow(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
...
//4. 给Window设置WindowManager(从WindowManagerService获取)
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE), ...);
//5. 当前Window的容器是父Activity的Window
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
//6. 将当前Window的WindowManager保存到Activity内部
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}
//ActivityThread.java
final void handleResumeActivity(IBinder token, ...) {
/**
* 1. 调用生命周期:onStart和onResume---通过Instrucmentation
*/
ActivityClientRecord r = performResumeActivity(token, clearHide);
//2. 获取到Window(在Activity的attach方法中创建了PhoneWindow)
r.window = r.activity.getWindow();
//3. 创建DecorView,设置为不可见INVISIBLE
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
a.mDecor = decor; //Activity内部保存了DecorView
//4. 获取到WindowManager
ViewManager wm = a.getWindowManager();
//5. WM的addView方法将DecorView添加到Window中
wm.addView(decor, l);
}
//ActivityThread.java
public final ActivityClientRecord performResumeActivity(IBinder token,boolean clearHide) {
//1. 执行onStart和onRsume
r.activity.performResume();
...
}
//Activity.java
final void performResume() {
// 1. 通过Instrucmentation执行onStart()
performRestart();
// 2. 执行onResume方法
mInstrumentation.callActivityOnResume(this);
}
Service
18、Service是什么?
- 一种
计算型组件
,用于在后台执行一系列计算任务(处理网络事务、播放音乐、文件读写、或者与ContentProvider交互)。Service
具有两种状态:启动状态
和绑定状态
- 启动状态: 进行后台任务,
Service
本身运行在主线程
,因此耗时操作需要在新线程
中处理- 绑定状态: 内部同样可以进行后台运算,但是此时
外界
可以很方便与Service
通信Service
的停止需要灵活采用stopService和unBindService
才能完全停止
分类
19、Service的分类
- 本地服务
- 远程服务
20、本地服务是什么?
- 该类服务依赖在主进程上而不是独立的进程,一定程度上节约资源。
- 本地服务因为在同一进程内,不需要IPC和AIDL进行交互。
bindService
也方便很多。- 缺点:限制性大,
主进程
被杀死后,服务便会终止
。- 应用场景:需要姨父某个进程的服务,比如音乐播放。
21、远程服务是什么?
- 该服务是
独立的进程
,进程名为所在包名 + android:process指定的字符串
。- 定义方式:用
android:process=".service"
- 特点: 主进程被杀死后,该服务依然存在,不受其他进城影响,能为多个进程提供服务,具有灵活性。
- 会消耗更多资源,并且使用AIDL进行IPC比较麻烦,一般用于系统Service。
- 从Android 5.0开始,APP结束后会关闭相关进程树,因此相关的服务也会被杀死。
生命周期
22、Service的生命周期
- 仅仅是
startService
:onCreate()->onStartCommand()->onDestory()- 仅仅是
bindService
:onCreate()->onBind()->onUnbind()->onDestory()- 同时使用
startService
开启服务与bindService
绑定服务:onCreate()->onStartCommand()->onBind()->onUnbind()->onDestory()
通信
23、Activity与Service间的通信方式
- Activity通过调用bindService,在ServiceConnection的onServiceConnected可以获取到Service的对象实例,然后就可以访问
Service
中的方法.(如果需要Service
去主动通知Activity
,可以通过回调
来实现—在Activity的ServicConnection的onServiceConnected中去给Service设置实现的接口,该接口会在Service中被调用。)- 通过
广播
- 通过
EventBus
启动模式
24、Service的启动方式有什么区别
startService
:Service与组件的生命周期无关,即使组件退出,Service依然存在。耗电,占内存。bindService
:调用者退出后,Service也会退出。
25、startService
- Service无论调用多少次
startService
,onCreate
只会调用一次,onStartCommand
会调用相应次数。- Service无论调用多少次
startService
,只存在一个Service实例
- 结束Service只需要调用一次
stopService或者stopSelf
- Activity的退出并不会导致Service的退出—除非在onDestoyr里面调用stopService,但是
退出APP会导致Service1的退出!
- 系统资源不足的时候,服务可能会被
Kill
26、bindService
- Service通过
bindService
启动,无论调用多少次,onCreate
只会调用一次,且onStartCommand
不会被调用。- 如果调用
Service
的组件退出,如Activity,Service就会被停止。bindService
开启的Service的通信比较方便,不需要AIDL和IPC
27、startService且同时bindService
onCreate
之调用一次。startService
调用几次,onStartCommand
会调用相同次数。bindService
不会调用onStartCommand
- 调用
unBindService
不会停止Service
,必须调用stopService
和Service自身的stopSelf
来停止。- 如果想停止这种Service,
unBindeService
和stopService
都需要调用,缺一不可。
28、同时开启和绑定有什么作用?
- 能让
Service
一直处于后台运行的状态,即使组件已经退出。- 同时通过
bindService
能方便地与Service
通信- 相比于
广播
的方式,性能更高。
29、Service的注意点
- 手机发生旋转时,Activity的重新创建,会导致之前
bindService
建立的连接断开,Service
会因为COntext的销毁而自动停止。
startService流程
30、Service的启动方法
Intent intent = new Intent(this, MyService.class);
startService(intent);
- Service有
启动状态
和绑定状态
两个状态可以共存
,Service可以既处于启动状态又处于绑定状态
31、Service的startService过程流程图和要点?
graph TD;
1(1.startService);
2(2.mBase.startService);
3(3.startServiceCommon);
4(4.ActivityManager.getService.startService);
5(5.mServices.startServiceLocked);
6(6.bringUpServiceLocked);
7(7.realStartServiceLocked);
8(8.app.thread.scheduleCreateService);
9(9.sendServiceArgsLocked);
10(10.handleMessage);
11(11.handleCreateService);
16(16.app.thread.scheduleServiceArgs);
17(17.handleMessage);
18(18.handleServiceArgs);
19(19.onStartCommand);
1-->2;
2-->3;
3-->4;
4-->5;
5-->6;
6-->7;
7-->8;
7-->9;
8-->10;
10-->11;
9-->16;
16-->17;
17-->18;
18-->19;
- startService(
ContextWrapper.java
):Activity层层继承自ContextWrapper
;内部交由ContextImpl
的startSertvice()
;典型的桥接模式- mBase.startService(
ContextImpl.java
): 交给ContextImpl执行。- startServiceCommon(
ContextImpl.java
): 通过ActivityManagerService
启动服务;IPC- startService(
ActivityManagerService.java
):通过ActiveServices
进行后续工作—调用mServices.startServiceLocked
。- startServiceLocked(
ActiveServices.java
): bringUpServiceLocked- bringUpServiceLocked(
ActiveServices.java
): realStartServiceLocked- realStartServiceLocked(
ActiveServices.java
): 1、app.thread.scheduleCreateService 2、sendServiceArgsLocked- app.thread.scheduleCreateService(
ActivityThread.java
):1. 创建Service 2. 发送消息CREATE_SERVICE
给Handler H- sendServiceArgsLocked(): 用Service的其他方法(如onStartCommand)-IPC通信
- handleMessage(
ActivityThread.java
): 处理消息- handleCreateService(
ActivityThread.java
): 处理第12、13、14、15 四步的工作
, 进行Service的创建工作- 16.app.thread.scheduleServiceArgs: IPC让ActivityThread只去执行其他的生命周期回调。发送消息给Handler H
- 17.handleMessage: 调用
handleServiceArgs
- 18.handleServiceArgs: 执行其他的生命周期,如
onStartCommand
- 19.onStartCommand: Service的回调方法
graph TD;
11(11.handleCreateService);
12(12.cl.loadClass);
13(13.makeApplication);
14(14.service.attach);
15(15.service.onCreate);
11-->12;
11-->13;
11-->14;
11-->15;
- handleCreateService(
ActivityThread.java
): 处理第12、13、14、15 四步的工作
- cl.loadClass().newInstance(): 类加载器创建Service实例。
- packageInfo.makeApplication: 用
LoadedApk
创建Application实例
- service.attach: 创建ContextImpling建立Context和Service的联系。
- service.onCreate(): Service的onCreate(), 并且将Service对象存储到ActivityThread中的一个列表中
32、ActiveServices是什么?
- 辅助ActivityManagerService进行Service管理
- 包括:启动、绑定、停止等
33、ServiceRecord是什么?
- 描述一个Service记录,官场整个启动过程
34、ContextWrapper是什么?
- ContextWrapper是Context实现类ContextImpl的包装类
- Activity、Service等都是直接或者间接继承自
ContextWrapper
35、ContextWrapper为什么是典型桥接模式?
36、桥接模式和代理模式的区别?
源码
37、Service的启动过程源码详细分析
/**
* ======================================
* 1. Activty层层继承自ContextWrapper
* 2. Activty的startService()方法来自于ContextWrapper
* 3. ContextWrapper最终由mBase(ContextImpl)完成-典型桥接
* ======================================
*/
//ContextWrapper.java
public ComponentName startService(Intent service) {
//1. mBase就是Context的实现ContextImpl对象(也就是Activity创建时关联的对象)
return mBase.startService(service);
}
//ContextImpl.java:直接调用startServiceCommon
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
//ContextImpl.java
private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) {
......
//1. 让`ActivityManagerService`启动一个Service服务
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, ...省略...);
......
}
//ActivityManagerService.java
public ComponentName startService(IApplicationThread caller, Intent service, ...) {
/**====================================
* 1. 通过mService(ActiveServices)完成后续过程
* 2. ActiveServices是辅助AMS进行Service管理的类
* -包括:启动、绑定、停止
* 3. `startServiceLocked`方法尾部会调用`startServiceInnerLocked`
*=====================================*/
res = mServices.startServiceLocked(caller, service, ...,userId);
}
//ActiveServices.java
ComponentName startServiceInnerLocked(...,ServiceRecord r) {
......
/**=========================================
* ServiceRecord描述的是一个Service记录(贯穿整个启动过程)
* 1. startServiceInnerLocked并没有完成具体启动工作,而是把后续任务交给了bringUpServiceLocked
* 2. bringUpServiceLocked内部调用`realStartServiceLocked`
* 3. realStartServiceLocked真正启动了Service
*==========================================*/
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
......
return r.name;
}
//ActiveServices.java
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) {
......
/**========================================================
* 创建了Service对象,并且调用了onCreate()方法-IPC通信
* 1. app.thread对象是IApplicationThread类型(Binder)
* 2. 具体实现是ActivityThread(继承了ApplicationThreadNative)
*========================================================*/
app.thread.scheduleCreateService(r, r.serviceInfo, ......);
......
//2. 用于调用Service的其他方法(如onStartCommand)-IPC通信
sendServiceArgsLocked(r, execInFg, true);
......
}
//ActivityThread.java的内部类:ApplicationThread
public final void scheduleCreateService(IBinder token, ...,int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
/**========================================
* 1. 发送消息给Handler H处理
* 2. H会接受消息,并且调用ActivityThread的handleCreateService
*========================================*/
sendMessage(H.CREATE_SERVICE, s);
}
/**====================================
* 完成Service最终启动工作
* //ActivityThread.java
*=====================================*/
private void handleCreateService(CreateServiceData data) {
//1. 通过类加载器创建Service实例
Service service = null;
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
//2. 创建Application对象并调用其onCreate方法(Application是唯一的不会重复创建)
Application app = packageInfo.makeApplication(false, mInstrumentation);
//3. 创建ContextImpl对象并通过Service的attach方法建立两者关系(类似Activity的过程)
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService());
//4. 调用service的onCreate方法,并且将Service对象存储到ActivityThread中的一个列表中
service.onCreate();
mServices.put(data.token, service);
......
}
/**=============================================================
* ActivityThread中还会通过handleServiceArgs方法调用Service的onStartCommand
*=============================================================*/
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
......
//1. Service的onStartCommand方法
res = s.onStartCommand(data.args, data.flags, data.startId);
......
}
bindService流程
38、Service绑定流程图分析
graph TD;
1(ContextWrapper.bindService);
2(ContextImpl.bindServiceCommon);
3(LoadedApk.getServiceDispatcher);
4(ActivityManager.getService.bindService);
5(mServices.bindServiceLocked);
6(r.app.thread.scheduleBindService);
7(Handler H);
8(handleBindService);
9(mServices.get);
10(service.onBind);
11(AMS.publishService);
12(c.conn.connected);
13(sd.connected);
14(mActivityThread.post);
15(doConnected);
16(onServiceConnected);
1-->2;
2-->3;
2-->4;
4-->5;
5-->6;
6-->7;
7-->8;
8-->9;
8-->10;
8-->11;
11-->12;
12-->13;
13-->14;
14-->15;
15-->16;
- bindService(): 调用了ContextWrapper的该方法。
- bindServiceCommon(): ContextImpl的该方法,执行了
第3,4两步的工作
- getServiceDispatcher(): 将客户端的ServiceConnection对象转换为
ServiceDispatcher内部类InnerConnection对象
,需要借助Binder才能让远程服务端调用自己的方法。- ActivityManager.getService().bindService: 通过
AMS
执行bindService方法。- mServices.bindServiceLocked(): 调用到
ActiveServices
的该方法。- r.app.thread.scheduleBindService: 通过IPC去调用
ActivityThread内部类Application
的该方法。- 本质都是通过Handler H的handleMessage()去进行处理
- handleBindService: 进行
第9、10、11 三步的任务
1.根据token取出Service 2.调用Service的onBind方法 3.通过IPC去告知客户端已经连接成功,并且执行onServiceConnected- Service s = mServices.get(data.token): 利用token取出Service
- IBinder binder = s.onBind(data.intent): 知性Service的onBind方法
- ActivityManager.getService().publishService: Service在执行
onBind
后已经处于绑定状态,但是此时客户端并不知道,需要通过Binder去执行ServiceConnection的onServiceConnected
方法。- c.conn.connected: 调用
ServiceDispatcher.InnerConnection
的connected()
【IPC】- sd.connected: 调用LoadedApk.java的内部类ServiceDispatcher的方法
- mActivityThread.post: mActivityThread就是Handler H
- doConnected: 最终调用ServiceConnection的onServiceConnected方法
39、如何让远程服务端调用客户端的ServiceConnection中的方法?
- 无法直接让远程服务端使用
- 需要借助Binder才能让远程服务端毁掉自己的方法
- ServiceDispatcher的内部类InnerConnection就起到了Binder的作用
- ServiceDispatcher起到连接ServiceConnection和InnerConnection的作用
40、getServiceDispatcher的原理
- 使用ArrayMap来:存储应用当前活动的ServiceConnection和ServiceDispatcher的映射关系
- key = ServiceConnection, value = ServiceDispatcher
- 根据ServiceConnection去查询是否有对应的ServiceDispatcher,存在就直接返回ServiceDispatcher的InnerConnection。
- 不存在,就新建ServiceDispatcher,并将映射关系存放到Map中。
41、何时Service处于绑定状态(何时执行的onBind方法)?
- 执行到
ActivityThread
的handlerBindService()
里,会获取到Service并且执行Service的onBind方法,此时就处于了绑定状态。
42、何时执行的ServiceConnection的onServiceConnected方法?
- AMS的publishService: 需要在Service进入绑定状态后,告知客户端已经完成连接。
- 【IPC】LoadedApk的ServiceDispatcher的connected方法
- 通过Handler H,最终在
ActivityThread
内部执行了onServiceConnected方法。
43、Service在ActivityThread中的存储?
- ActivityThread通过ArrayMap存储了IBinder和Service的映射关系。
- key = IBinder, value = Service
- 在handlerCreateService中创建好Service后,会将IBinder-Service的映射关系保存到Map中。
- AMS通过Binder去执行Service的任务比如执行Service的onBind方法,需要知道IBinder对应的是哪个Service,就利用到了ArrayMap存储的映射关系。
源码
44、Service的绑定过程源码
/**
* ==============================================
* 1. bindService最终也是调用的ContextWrapper的方法
* 2. 与启动过程类似, mBase是ContextImpl最终会调用自身的bindServiceCommon方法
* //ContextWrapper.java
* =============================================
*/
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
return mBase.bindService(service, conn, flags);
}
//ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
/**======================================================================
* 1. 将客户端的ServiceConnection对象转化为`ServiceDispatcher.InnerConnection`对象
* -ServiceConnection必须借助于Binder才能让远程服务端回调自己的方法
* -ServiceDispatcher的内部类InnerConnection就起到了Binder的作用
* -ServiceDispatcher起到连接ServiceConnection和InnerConnection的作用
*======================================================================*/
IServiceConnection sd;
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
//2. 通过ActivityManagerService完成Service的绑定过程
int res = ActivityManager.getService().bindService(... , service,...);
......
}
//LoadedApk.java
public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags) {
/**================================
* 1.mServices是ArrayMap:存储应用当前活动的ServiceConnection
* 和ServiceDispatcher的映射关系
*================================*/
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
//2. 获取`映射关系`的map
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
//3. 通过ServiceConnection去查询是否有ServiceDispatcher
sd = map.get(c);
}
//4. 不存在ServiceDispatcher,新建ServiceDispatcher对象,
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<>();
//6. 将该`映射关系`与Context放置到ArrayMap中
mServices.put(context, map);
}
//5. key=ServiceConnection,value=ServiceDispatcher,建立映射关系
map.put(c, sd);
}
//7. 返回ServiceDispatcher内部保存的InnerConnection
return sd.getIServiceConnection();
}
}
//ActivityManagerService.java
public int bindService(IApplicationThread caller, IBinder token, Intent service,...) {
......
/**=========================
* ActiveServices的方法:
* 1. bindServiceLocked
* 2. bringUpServiceLocked
* 3. realStartServiceLocked
* 4. 最后都是通过ActivityThread来完成Service实例的创建
* 并且执行Services的onCreate方法
* * Service绑定与启动的不同在于会调用app.thread的scheduleBindService方法
* (在ActiveServices的requestServiceBindingLocked中调用)
*============================*/
return mServices.bindServiceLocked(caller, token, service,...);
}
//ActiveServices.java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,...) {
......
//ActivityThread内部类:`ApplicationThread`——中一系列`schedule`方法之一,最终通过Handler H进行中转,最终交给handleBindServices
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState);
......
}
//ActivityThread
private void handleBindService(BindServiceData data) {
//1. 根据token取出Service
Service s = mServices.get(data.token);
if (s != null) {
if (!data.rebind) {
/**================================
* 2. 调用Service的onBind方法
* -此时Service就已经处于绑定状态,但此时客户端并不知道连接成功
* -因此必须调用客户端ServiceConnection中的onServiceConnected
*=================================*/
IBinder binder = s.onBind(data.intent);
/**=======================================
* 3. ActivityManagerService的publishService
* -1.会执行客户端ServiceConnection中的onServiceConnected
* -2.保证Service的onBind方法之调用一次(多次绑定同一个Service)
* -3.最终将具体任务交给ActiveServices的publishServiceLocked方法
*========================================*/
ActivityManager.getService().publishService(data.token, data.intent, binder);
}
}
......
}
//ActiveServices.java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
......
/**===================================
* 1. c是ConnectionRecord
* 2. c.conn是ServiceDispatcher.InnerConnection
* 3. service就是Service的onBind方法返回的Binder对象
*==================================*/
c.conn.connected(r.name, service, false);
......
}
//LoadedApk.java的内部类ServiceDispatcher的内部类InnerConnection
private static class InnerConnection extends IServiceConnection.Stub {
......
public void connected(ComponentName name, IBinder service, boolean dead) {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
//1. 调用ServiceDispatcher的方法
sd.connected(name, service, dead);
}
}
}
//LoadedApk.java的内部类: ServiceDispatcher
public void connected(ComponentName name, IBinder service, boolean dead) {
/**=========================================================
*1. mActivityThread是一个Handler,其实就是ActivityThread中的H
*2. 最终RunConnection通过H的post方法从而运行在主线程中
*3. 因此客户端ServiceConnection就是在主线程被回调
*========================================================*/
mActivityThread.post(new RunConnection(name, service, 0, dead));
}
//LoadedApk.java内部类ServiceDispatcher的内部类: RunConnection
private final class RunConnection implements Runnable {
......
/**
* =========================================================
* 1. 本质调用ServiceDispatcher的doConnected
* 2. ServiceDispatcher内部拥有客户端的ServiceConnection
* ========================================================
*/
public void run() {
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
}
//LoadedApk.java内部类: ServiceDispatcher
public void doConnected(ComponentName name, IBinder service, boolean dead) {
....
if (service != null) {
//1. 可以通过客户端的ServiceConnection调用onServiceConnected
mConnection.onServiceConnected(name, service);
}
}
Broadcast
45、BroadcastReceiver是什么?
- 一种
消息型组件
,用于在不同组件甚至不同应用间传递消息静态注册
: 在AndroidManifest中注册广播,会在应用安装时被系统解析
,不需要启动应用就可以接收到相应广播(从Android 3.1开始默认不给不在运行的应用发送广播)动态注册
:Context.registerReceiver()
进行注册,Context.unRegisterReceiver()
解除注册. 需要APP启动才能注册并且接收广播。- 广播发送通过
Context
的一系列send
方法完成发送和接收
过程的匹配通过广播接收者的intent-filter
来描述
分类
46、广播分为几种
- 普通广播
- 有序广播
47、普通广播是什么?
- 调用
sendBroadcast()
发送
48、有序广播是什么?
- 调用
sendOrderedBroadcast()
发送- 广播接收者会按照
priority优先级
从大到校进行排序优先级
相同的广播,动态注册
的广播优先处理- 广播接收者还能对
广播
进行截断和修改
49、广播的发送和接收原理
- 继承BroadcastReceiver,在
onReceive()
中实现接收到广播后应该进行的操作。- 通过
Binder机制
向ActivityManagerService
注册广播。- 通过
Binder机制
向ActivityManagerService
发送广播。ActivityManagerService
会查找符合广播
条件(IntentFilter/Permission
)的所有BroadcastReceiver
, 并将这些广播接受器存放到队列中。- 遍历队列中所有的
BroadcastReceiver
,并将广播
发送给该接收器【IPC】。- 最终通过Handler H回调其
onReceive()
方法。
50、BroadcasReceiver和LocalBroadcastReceiver
BroadcasReceiver
是跨应用广播,利用Binder机制
实现。LocalBroadcastReceiver
是应用内广播
,利用Handler
实现。利用IntentFilter
的match
功能,提供消息的发布与接收,实现应用内通信,效率较高。
51、本地广播的优点
- 效率更改。
- 发送的广播不会离开我们的应用,不会泄露关键数据。
- 其他程序无法将广播发送到我们程序内部,不会有安全漏洞。
注册方式
52、广播两种注册方式的区别
静态注册
:常驻系统,不受组件生命周期的影响,耗电,占内存动态注册
:非常驻系统,组件结束,广播就结束。但是在组件结束前,一定要释放广播,避免内存泄露和崩溃。
53、广播的静态注册过程:
- 安装应用时由系统自动完成注册
- 具体是由
PMS(Package Manager Service)
来完成注册过程- 本质其他
三大组件
的注册都是在安装时由PMS
解析并注册
动态注册
54、广播动态注册的流程图
graph TD;
1(registerReceiver-ContextWrapper);
2(registerReceiver-ContextImpl);
3(registerReceiverInternal-ContextImpl);
4(获取IIntentReceiver对象);
5(ActivityManager.getService.registerReceive);
6(mRegisteredReceivers.put);
7(mReceiverResolver.addFilter);
1-->2;
2-->3;
3-->4;
3-->5;
5-->6;
5-->7;
- registerReceiver: ContextWrapper.java, 层层调用
- registerReceiver: ContextImpl.java, 层层调用
- registerReceiverInternal: ContextImpl.java 进行下面
4、5的工作
- mPackageInfo.getReceiverDispatcher/LoadedApk.ReceiverDispatcher : 获取到IIntentReceiver对象
- ActivityManager.getService().registerReceiver(): 【IPC】调用AMS的registerReceiver方法,进行下面
6、7的工作
- mRegisteredReceivers.put(): 将InnerReceiver对象进行存储(该对象与BroadcastReceiver对象相对应)
- (mReceiverResolver.addFilter(): 存储IntentFilter
55、为什么需要将BroadcastReceiver转换为IIntentReceiver?
- BroadcastReceiver作为组件不能直接进行IPC,需要进行中转
- IIntentReceiver是Binder接口,具体实现是LoadedApk.ReceiverDispatcher.InnerReceiver
- ReceiverDispatcher中同时保存了 BroadcastReceiver和InnerReceiver,接收广播时ReceiverDispatcher可以很方便调用BroadcastReceiver的onReceive()方法
- Service也有ServiceDispatcher和内部类InnerConnection(Binder接口),原理相同
56、动态注册的本质是什么?
- 将BoradcastReceiver对应的Binder对象InnerReceiver存储到ActivityManagerService的Map中
- 将IntentFilter存储到AMS中
动态注册源码
57、广播的动态注册过程:
/**
* =================================
* 1. 动态注册是从ContextWrapper的registerReceiver方法开始
* 2. 之后直接交给ContextImpl完成
* //ContextWrapper.java
* =================================
*/
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
//1. mBase = ContextImpl
return mBase.registerReceiver(receiver, filter);
}
//ContextImpl.java
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,......) {
return registerReceiverInternal(receiver, ......);
}
//ContextImpl.java
private Intent registerReceiverInternal(BroadcastReceiver receiver, ......) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
//1. 从mPackageInfo获取IIntentReceiver对象
rd = mPackageInfo.getReceiverDispatcher(receiver, context, scheduler, ......);
} else {
/**==============================================================================
*2.从mPackageInfo获取IIntentReceiver对象
* 1-采用IIntentReceiver而不是BroadcastReceiver是因为这是IPC过程
* 2-BroadcastReceiver作为组件不能直接进行IPC,需要进行中转
* 3-IIntentReceiver是Binder接口,具体实现是LoadedApk.ReceiverDispatcher.InnerReceiver
* 4-ReceiverDispatcher中同时保存了 BroadcastReceiver和InnerReceiver,接收广播时ReceiverDispatcher
* 可以很方便调用BroadcastReceiver的onReceive()方法
* 5-可以发现Service也有ServiceDispatcher和内部类InnerConnection(Binder接口),原理相同
*===============================================================================*/
rd = new LoadedApk.ReceiverDispatcher(receiver, context, scheduler, null, true)
.getIIntentReceiver();
}
}
//3. 通过ActivityManagerService, 远程进行注册
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
......
}
//ActivityManagerService.java:广播完成注册
public Intent registerReceiver(IApplicationThread caller, ...,IIntentReceiver receiver, ...) {
......
//1. 存储远程的InnerReceiver对象(本地的BroadcastReceiver对应的对象)
mRegisteredReceivers.put(receiver.asBinder(), rl);
//2. 存储IntentFiler对象
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
rl.add(bf);
mReceiverResolver.addFilter(bf);
......
}
广播发送
58、广播发送/接收的流程图(普通广播)
graph TD;
1(sendBroadcast);
2(ActivityManager.getService.broadcastIntent);
3(broadcastIntentLocked);
4(intent.addFlags);
5(过滤出广播接受器);
6(enqueueOrderedBroadcastLocked);
7(scheduleBroadcastsLocked);
8(mHandler.sendMessage);
9(processNextBroadcast);
10(deliverToRegisteredReceiverLocked);
11(performReceiveLocked);
12(app.thread.scheduleRegisteredReceiver);
13(receiver.performReceive);
14(mActivityThread.post);
15(receiver.onReceive);
1-->2;
2-->3;
3-->4;
3-->5;
3-->6;
3-->7;
7-->8;
8-->9;
9-->10;
10-->11;
11-->12;
12-->13;
13-->14;
14-->15;
- sendBroadcast: 调用顺序-Activity->ContextWrapper->ContextImpl
- ActivityManager.getService().broadcastIntent(……): 直接向AMS发起一个异步请求用于发送广播
- broadcastIntentLocked: 进行
第4、5、6、7的工作
—添加标志位(不给已经停止的应用发送广播)、根据Intent-Fillter找到匹配的BroadcastReceiver、经过过滤后将- intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES): 从Android 3.1开始默认不会给已经停止的应用发送广播。
- 根据intent-filter查找出匹配的广播接收者, 过滤出所有符合条件的BroadcastReceiver
- queue.enqueueOrderedBroadcastLocked: 会将满足条件的广播接收者都加入到BroadcastQueue中
- queue.scheduleBroadcastsLocked:会将广播发送到BroadcastQueue中的所有广播接收者中。
- mHandler.sendMessage: 发送消息
- processNextBroadcast: 取出广播并且发送给所有接收者。
- deliverToRegisteredReceiverLocked: 发送广播
- performReceiveLocked: 通过IPC发送给ActivityThread
- app.thread.scheduleRegisteredReceiver: 通过InnerReceiver实现广播的接收
- receiver.performReceive: ReceiverDispatcherd的performReceive方法,通过Handler H去投递一个Runnable
- mActivityThread.post: 通过Handler H 的post方法投递Runnable
- receiver.onReceive: 执行BroadcastReceiver的onReceive方法
源码
59、广播的发送和接收过程源码(普通广播为例):
- 通过
sendBroadcast
发送广播时,AMS会查找出匹配的广播接收者并将广播发送给它们处理- 广播分为:普通广播、有序广播和粘性广播
/**
* ==================================================
* 1. 广播的发送开始于ContextWrapper的sendBroadcast方法
* 2. 最终会交给ContextImpl的sendBroadcast方法去处理
* // ContextImpl.java
* ==================================================
*/
public void sendBroadcast(Intent intent) {
//1. 直接向AMS发起一个异步请求用于发送广播
ActivityManager.getService().broadcastIntent(......);
......
}
//ActivityManagerService.java
public final int broadcastIntent(IApplicationThread caller, Intent intent, ......) {
....
int res = broadcastIntentLocked(callerApp, ......);
}
//ActivityManagerService.java
final int broadcastIntentLocked(ProcessRecord callerApp, ......) {
intent = new Intent(intent);
/**==============================================================
*1. 默认情况下广播不会发送给已经停止的应用(从Android 3.1开始)
* Intent中新增两个标记:
* FLAG_EXCLUDE_STOPPED_PACKAGES-不包含已经停止应用
* FLAG_INCLUDE_STOPPED_PACKAGES-包含已经停止应用
* -如果两个标记共存,则以FLAG_INCLUDE_STOPPED_PACKAGES为准
* -停止状态为:1-应用安装后未运行 2-应用被手动或者其他应用强制停止
*==============================================================*/
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
......
/**================================================
*2. 根据intent-filter查找出匹配的广播接收者
*3. 进过一系列过滤后,将满足条件的广播接收者添加到`BroadcastQueue`
*4. BroadcastQueue就会将广播发送给相应的广播接收者
*===============================================*/
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, ......);
......
queue.enqueueOrderedBroadcastLocked(r);
//4. BroadcastQueue就会将广播发送给相应的广播接收者
queue.scheduleBroadcastsLocked();
}
......
return ActivityManager.BROADCAST_SUCCESS;
}
//BroadcastQueue.java
public void scheduleBroadcastsLocked() {
//1. 发送消息,BroadcastQueue收到消息后会调用processNextBroadcast方法
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
}
//BroadcastQueue.java
final void processNextBroadcast(boolean fromMsg) {
synchronized (mService) {
BroadcastRecord r;
......
//1. 普通广播处理
while (mParallelBroadcasts.size() > 0) {
//2. 无序广播存储在mParallelBroadcasts中
r = mParallelBroadcasts.remove(0);
final int N = r.receivers.size();
//3. 取出广播并发送给他们所有的接受者
for (int i = 0; i < N; i++) {
Object target = r.receivers.get(i);
//4. 发送广播
deliverToRegisteredReceiverLocked(r, (BroadcastFilter) target, false, i);
}
addBroadcastToHistoryLocked(r);
}
......
}
}
//BroadcastQueue.java
private void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered, int index) {
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, ......);
}
//BroadcastQueue.java
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, ...) {
......
//1. app.thread为ActivityThread,会调用其中方法
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser, app.repProcState);
}
//ActivityThread.java
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, ......) {
updateProcessState(processState, false);
//1. 通过`InnerReceiver`实现广播的接收, 内部会调用ReceiverDispatcher的performReceive方法
receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser);
}
//LoadedApk.java内部类ReceiverDispatcher
public void performReceive(Intent intent, int resultCode, String data, ......) {
//1. 创建Args对象
final Args args = new Args(intent, resultCode, data, extras, ordered, sticky, sendingUser);
......
/**=========================================================
* 2. 通过mActivityThread的post方法来执行args中的逻辑
* -mActivityThread是Handler(也就是ActivityThread中的Handler H)
* -Args中实现了Runnable接口-在广播接受线程中执行了onReceive方法
*========================================================*/
if (intent == null || !mActivityThread.post(args.getRunnable())) {
......
}
}
//LoadedApk.java内部类ReceiverDispatcher.Args
final class Args extends BroadcastReceiver.PendingResult {
.......
public final Runnable getRunnable() {
return () -> {
//1. 执行了BroadcastReceiver的onReceive方法
final BroadcastReceiver receiver = mReceiver;
......
receiver.onReceive(mContext, intent);
......
};
}
}
ContentProvider
60、ContentProvider是什么?
- 一种
数据共享型组件
- 内部需要实现
增删改查
四种操作- 内部的
insert\delete\update\query
方法需要处理好线程同步,因为这些方法都在Binder线程池
中调用
61、ContentProvider要点
- ContentProvider所在进程启动时,就会同时启动并且发布到AMS中
- ContentProvider的onCreate要先于Application的onCreate执行
启动
62、ContentProvider的启动流程
ActivityThread
的main
方法为应用启动时的入口,main
是静态方法——会创建ActivityThread
的实例,并且创建主线程
的消息队列
- 然后会在
ActivityThread
的attach()
方法中远程调用AMS
的attachApplication
方法并将ApplicationThread
对象提供给AMS
ApplicationThread
是Binder对象,Binder接口是IApplicationThread
,主要用于ActivityThread
和AMS
之间的通信AMS
的attachApplication
中会调用ApplicationThread
的bindApplication
方法(IPC过程),bindApplication
的逻辑会通过ActivityThread
中的Handler H
切换到ActivityThread
中的handleBindApplication
去处理handleBindApplication
中会创建Application
对象并且加载ContentProvider
- 加载
ContentProvider
后,才会调用Application
的onCreate
方法
数据访问
63、ContentProvider的数据访问
- ContentProvider启动后,外界就可以通过提供的接口进行增删改查
- 外界无法直接访问
ContentProvider
,需要通过AMS
根据Uri
来获取对应的ContentProvider
的Binder接口IContentProvider
- 然后通过
IContentProvider
来访问其数据源
/**
* =============================================================================
* 1. 其他应用通过AMS来访问指定的ContentProvider
* 2. 通过AMS获得ContentProvider的Binder对象:IContentProvider
* 3. IContentProvider的具体实现ContentProvider.Transport(继承自ContentProviderNative)
* 以query为例: 最终会通过IPC调用到ContentProvider.Transport的query方法
* //ContentProvider.java内部类: Transport
* =============================================================================
*/
public Cursor query(String callingPkg, Uri uri, String[] projection, ......) {
......
//1. 调用了ContentProvider的query方法
Cursor cursor = ContentProvider.this.query(uri, projection, queryArgs, CancellationSignal.fromTransport(cancellationSignal));
......
}
数据解析
64、ContentProvider的数据访问解析
- 访问
ContentProvider
需要通过ContentResolver
,这是一个抽象类Context的getContentResolver()
本质获取的是ApplicationContentResolver
对象(ContextImpl的内部类)- 当
ContentProvider
所在进程未启动时,第一次访问会触发所在进程的启动和ContentProvider
的创建。- 例如
query
方法,首先会获取IContentProvider
对象,最终通过acquireProvider
来获取ContentProvider
65、ContentProvider访问和创建的流程图
graph TD;
1(1.acquireProvider);
2(2.mMainThread.acquireProvider);
3(3.acquireExistingProvider);
4(4.ActivityManager.getService.getContentProvider);
5(5.getContentProviderImpl);
6(6.startProcessLocked);
7(7.main)
8(8.new ActivityThread)
9(9.thread.attach)
10(10.Looper)
11(11.ActivityManager.getService.attachApplication);
12(12.thread.bindApplication);
13(13.sendMessage);
14(14.handleBindApplication);
15(15.创建ContextImpl对象);
16(16.makeApplication);
17(17.installContentProviders);
18(18.callApplicationOnCreate);
19(19.installProvider);
20(20.AMS.publishContentProviders);
21(21.创建ContentProvider);
22(22.localProvider.attachInfo);
1-->2;
2-->3;
2-->4;
4-->5;
5-->6;
6-->7;
7-->8;
7-->9;
7-->10;
9-->11;
11-->12;
12-->13;
13-->14;
14-->15;
14-->16;
14-->17;
14-->18;
17-->19;
17-->20;
19-->21;
19-->22;
- acquireProvider:;直接调用
ActivityThread
的方法; 位于ContextImpl.java的内部类:ApplicationContentResolver
- mMainThread.acquireProvider: 进行
3、4
- acquireExistingProvider(): 查询是否存在需要的ContentProvider,存在就直接返回
- ActivityManager.getService().getContentProvider: 发送请求让
AMS
启动需要的ContentProvider
- getContentProviderImpl: 调用
startProcessLocked
去启动ContentProvide所在进程,然后才会启动ContentProvider- startProcessLocked: 1. 会先启动ContentProvider所在的进程,然后才会启动ContentProvider 2. 主要是通过Process的start方法来完成新进程的启动 3. 新进程启动后入口方法在ActivityThread的main方法
- main: 进行
第8、9、10三个工作
1.创建ActivityThread实例 2.初始化工作 3.Looper相关- new ActivityThread(): 创建实例
- thread.attach: 一系列初始化工作
- Looper: Looper相关工作
- ActivityManager.getService().attachApplication(): 通过
AMS
进行处理—【IPC】- thread.bindApplication(): 通过【IPC】又交给ContentProvider进程进行bindApplication操作
- sendMessage(H.BIND_APPLICATION): 发送
BIND_APPLICATION
- handleBindApplication: 进行
15、16、17、18的工作
,主要是创建Application和COntentProvider- ContextImpl.createAppContext: 创建ContextImpl对象
- makeApplication: 创建Application对象
- installContentProviders: 进行
19、20
,启动当前进程的ContentProvider并调用其onCreate方法- callApplicationOnCreate: 调用Application的onCreate方法
- installProvider: 遍历当前进程的Provider列表,调用installProvider进行启动。进行
21、22
- AMS.publishContentProviders: 将已经启动的ContentProvider保存在AMS的ProviderMap中 外部调用者就可以直接从AMS中获取ContentProvider
- 类加载器创建ContentProvider
- localProvider.attachInfo: 通过ContextProvider的方法调用了onCreate方法
源码
66、ContentProvider源码解析
//ContextImpl.java的内部类:ApplicationContentResolver
protected IContentProvider acquireProvider(Context context, String auth) {
//1. 直接调用`ActivityThread`的方法
return mMainThread.acquireProvider(context, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), true);
}
//ActivityThread.java
public final IContentProvider acquireProvider(Context c, String auth, int userId, boolean stable) {
//1. 查找是否已经存在需要的ContenProvider
final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
if (provider != null) {
//2. 存在就直接返回——ActivityThread通过mProviderMap来存储已经启动的ContentProvider
return provider;
}
ContentProviderHolder holder = null;
//3. 不存在就发送请求让`AMS`启动需要的`ContentProvider`
holder = ActivityManager.getService().getContentProvider(getApplicationThread(), auth, userId, stable);
......
//4. 最后修改引用计数
holder = installProvider(c, holder, holder.info, true, holder.noReleaseNeeded, stable);
return holder.provider;
}
//ActivityManagerService.java
public final ContentProviderHolder getContentProvider(IApplicationThread caller, String name, int userId, boolean stable) {
...
return getContentProviderImpl(caller, name, null, stable, userId);
}
//ActivityManagerService.java
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, ...) {
ContentProviderRecord cpr;
ContentProviderConnection conn = null;
ProviderInfo cpi = null;
......
//1. 会先启动ContentProvider所在的进程,然后才会启动ContentProvider
/**==================================================================
* 1. 会先启动ContentProvider所在的进程,然后才会启动ContentProvider
* 2. startProcessLocked中主要是通过Process的start方法来完成新进程的启动
* 3. 新进程启动后入口方法在ActivityThread的main方法(个人认为这是ContentProvider的进程不是我们自己应用的)
*==================================================================*/
proc = startProcessLocked(cpi.processName,
cpr.appInfo, false, 0, "content provider",
new ComponentName(cpi.applicationInfo.packageName,
cpi.name), false, false, false);
......
return cpr != null ? cpr.newHolder(conn) : null;
}
//ActivityThread.java
public static void main(String[] args) {
...
//1. 首先会创建ActivityThread实例
ActivityThread thread = new ActivityThread();
//2. 然后调用attach-进行一系列初始化
thread.attach(false);
//3. 然后开始消息循环
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
...
}
//ActivityThread.java
private void attach(boolean system) {
......
//1. 将ApplicationThread对象传输给AMS(IPC)
final IActivityManager mgr = ActivityManager.getService();
mgr.attachApplication(mAppThread);
......
}
//ActivityManagerService.java
public void attachApplication(IApplicationThread thread) {
attachApplicationLocked(thread, callingPid);
}
//ActivityManagerService.java
private boolean attachApplicationLocked(IApplicationThread thread, int pid) {
......
thread.bindApplication(processName, appInfo, providers, ......);
......
}
//ActivityThread.java内部类:ApplicationThread
public final void bindApplication(String processName, ApplicationInfo appInfo,......) {
......
//1. 发送消息给Handler H(ActivityThread)
sendMessage(H.BIND_APPLICATION, data);
}
//ActivityThread.java
/**
* ==============================================
* -完成了Application的创建
* -以及ContentProvider的创建
* //ActivityThread.java
* ================================================
*/
private void handleBindApplication(AppBindData data) {
...
//1. 创建ContextImpl对象和Instrumentation
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
final ClassLoader cl = instrContext.getClassLoader();
//Instrumentation
mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance();
final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component, data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
//2. 创建Application对象
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
//3. 启动当前进程的ContentProvider并调用其onCreate方法
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers); //启动并且调用onCreate
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10 * 1000);
}
}
//4. 调用Application的onCreate方法
mInstrumentation.callApplicationOnCreate(app);
}
//ActivityThread.java
private void installContentProviders(Context context, List<ProviderInfo> providers) {
final ArrayList<ContentProviderHolder> results = new ArrayList<>();
//1. 遍历当前进程的Provider列表
for (ProviderInfo cpi : providers) {
//2. 调用installProvider进行启动
ContentProviderHolder cph = installProvider(context, null, cpi, ......);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
//2. 将已经启动的ContentProvider保存在AMS的ProviderMap中, 外部调用者就可以直接从AMS中获取ContentProvider
ActivityManager.getService().publishContentProviders(getApplicationThread(), results);
......
}
//ActivityThread.java
private ContentProviderHolder installProvider(Context context, ......) {
ContentProvider localProvider = null;
IContentProvider provider;
...
//1. 通过类加载器完成了ContentProvider对象的创建
final java.lang.ClassLoader cl = c.getClassLoader();
localProvider = (ContentProvider) cl.loadClass(info.name).newInstance();
provider = localProvider.getIContentProvider();
if (provider == null) {
return null;
}
//2. 通过ContextProvider方法调用了onCreate方法
localProvider.attachInfo(c, info);
...
}
Fragment
67、Fragment的常见问题,以及如何处理?
getActivity()空指针
:常见于进行异步操作的时候,此时如果Fragment已经onDetach()
,就会遇到。解决办法:在Fragment
里面使用一个全局变量mActivity
,可能会导致内存泄露。但是比崩溃
更好。视图重叠
:主要是因为Fragment
的onCreate()
中没有判断saveInstanceSate == null
,导致重复加载了同一个Fragment
序列图解析四大组件流程
68、Activity的启动
13.创建Activity前初始化WindowManagerGlobal
14.完成Activity对象的创建和启动过程
15.调用Activity的onResume这一生命周期
17.通过类加载器来创建Activity对象
18.通过LoadedApk的makeApplication方法创建Application对象(唯一),并会调用onCreate()
19.创建ContextImpl,并调用attach
20.关联了Context和Activity,并且创建Window加载WM等初始化工作
21.调用Activity的onCreate方法
69、Service的启动
AT: ActivityThread
11.Handler H接受并且处理消息,最终调用handleCreateService()
13.makeApplication(创建Application对象并调用onCreate()-若已经存在则不创建)
14.创建ContextImpl并调用attach方法-建立ContextImpl和Service的联系
15.service.onCreate(),并将Service添加到ActivityThread内部的Service列表中
16.sendServiceArgsLocked()-内部最终调用Service的其他方法(onStartCommand等)
70、Service的绑定
2 最终是会调用ContextImpl的bindServiceCommon方法
4.ServiceConnection需要借助binder才能让远程服务回调自己的方法(借助于ServiceDispatcher.InnerConnection)
10.scheduleBindService会发送消息,最终由handleBindService处理
12.调用Service的onBind方法-绑定成功
13.绑定成功后需要通知客户端:最终调用客户端ServiceConnection中的onServiceConnected
16.c.conn是ServiceDispatcher.InnerConnection(ServiceConnection的Binder中转对象),最终调用ServiceDispatcher的connected
17.mActivityThread就是ActivityThread的Hanlder H
18.通过post最终运行在主线程
19.调用客户端的onServiceConnected方法
71、广播的动态注册
1.动态注册从ContextWrapper开始,之后直接交给ContextImpl完成
3.已有,从mPackageInfo获取IIntentReceiver对象
4.没有则新建IIntentReceiver对象,本质是为了IPC通信需要进行中转,ReceiverDispatcher中同时保存了 BroadcastReceiver和InnerReceiver
7.存储远程的InnerReceiver对象(本地的BroadcastReceiver对应的对象)
72、广播的发送和接收
5.默认FLAG_EXCLUDE_STOPPED_PACKAGES-广播不会发送给已经停止的应用
4-4.BroadcastQueue就会将广播发送给相应的广播接收者
6.接收消息并且处理
6-1.取出无序广播列表中的广播
8.通过InnerReceiver
实现广播的接收, 内部会调用ReceiverDispatcher的performReceive方法
10.通过Hanlder H的post方法来执行args中的逻辑
11.LoadedApk.java内部类ReceiverDispatcher的内部类Args,主要是执行BroadcastReceiver的接收方法
73、ContentProvider的机制
1.获得ContextImpl的内部类:ApplicationContentResolver
5.不存在ContentProvider让MAS启动需要的ContentProvider
8.通过Process的start方法来完成新进程的启动
9-1.首先会创建ActivityThread实例
9-2.然后调用attach-进行一系列初始化
9-3.然后开始消息循环
12.将ApplicationThread
传输给AMS
15. 发送消息给Handler H
16. 完成了Application的创建以及ContentProvider的创建
16-3. makeApplication()创建Application对象
16-4. 启动ContentProvider并调用onCreate方法
16-5. 调用Application的onCreate方法
17-1. 遍历当前进程的Provider列表并调用installProvider()
18.创建ContentProvider对象,并调用onCreate方法
19.将已经启动的ContentProvider保存在AMS的ProviderMap中,外部调用者就可以直接从AMS中获取ContentProvider