Launcher加载流程分析
最近开始接手Launcher模块,为了更好的技术积累,也看到很多大神在优快云上发的博文,就有了在优快云写博客的想法,这篇博文是我在研究了一段时间Launcher3后写的,可能有不对的,望大家拍砖。首先我们可以先参考这篇http://blog.youkuaiyun.com/yanbober/article/details/50525559博文,这篇博文介绍了launcher的代码主流程框架,这里我直接贴代码分析。
Launcher首次启动是通过ActivityManagerService.systemReady方法启动的,在Android系统启动中会启动system_server进程,在SystemServer.java中可以找到调用ActivityManagerService.systemReady的地方,来看一下ActivityManagerService中的systemReady方法
public void systemReady(final Runnable goingCallback) {
...//省略
startHomeActivityLocked(currentUserId, "systemReady");
...
}
继续看startHomeActivityLocked()方法
boolean startHomeActivityLocked(int userId, String reason) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
// the factory test app, so just sit around displaying the
// error message and don't try to start anything.
return false;
}
Intent intent = getHomeIntent();//这里得到Launcher的Intent
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
//这里就会启动
mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
}
/// M: PerfService for recording the last pause activity information. @{
if (mStackSupervisor.mLastResumedActivity.packageName == null ||
mStackSupervisor.isUpdatedLastActivityWhenStartHome(aInfo.packageName,
aInfo.name)) {
mStackSupervisor.mLastResumedActivity.packageName = aInfo.packageName;
mStackSupervisor.mLastResumedActivity.activityName = aInfo.name;
mStackSupervisor.mLastResumedActivity.activityType =
ActivityRecord.HOME_ACTIVITY_TYPE;
}
/// @}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
来看下getHomeIntent()方法
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);//CATEGORY_HOME
}
return intent;
}
在Launcher3中的AndroidManifest.xml中有注册这个Category的activity
<activity
android:name="com.android.launcher3.Launcher"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:theme="@style/Theme"
android:configChanges="mcc|mnc"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="portrait"
android:resumeWhilePausing="true"
android:taskAffinity=""
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY"/>
</intent-filter>
</activity>
简单分析完了Launcher是怎么被启动的,现在就来看Launcher本身的启动和加载流程,现在来看Launcher.java的onCreate方法,我在一些地方加了注释
@Override
protected void onCreate(Bundle savedInstanceState) {
/*这两行初始化LauncherAppState,这个单例对象,会注册应用安装、卸载、更新,配置变化等广播,同时会
初始化LauncherModel,里面有一个内部类LoaderTask用来获取数据,初始化桌面*/
LauncherAppState.setApplicationContext(getApplicationContext());
LauncherAppState app = LauncherAppState.getInstance();
/*new InvariantDeviceProfile对象,从名字看意思是不变的设备相关参数存储类,里面会初始化管理横
竖屏的两个DeviceProfile对象*/
app.RenewInvariantDeviceProfile();
//获得横竖屏的DeviceProfile对象
mDeviceProfile = getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE ?
app.getInvariantDeviceProfile().landscapeProfile
: app.getInvariantDeviceProfile().portraitProfile;
mModel = app.setLauncher(this);//获取在LauncherAppState中new LauncherModel对象
mIconCache = app.getIconCache();//桌面图标缓存类
mDragController = new DragController(this);//拖拽控制类
mInflater = getLayoutInflater();
mStateTransitionAnimation = new LauncherStateTransitionAnimation(this);//动画管理类
mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);//widget管理类
mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
mAppWidgetHost.startListening();
setupViews();//初始化布局控件
mDeviceProfile.layout(this);//根据设备配置调整布局
//调用mModel.startLoader方法开始加载异步加载桌面的数据,如app,folder,widget等
if (!mRestoring) {
if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
// If the user leaves launcher, then we should just load items asynchronously when
// they return.
mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);
} else {
// We only load the page synchronously if the user rotates (or triggers a
// configuration change) while launcher is in the foreground
mModel.startLoader(mWorkspace.getRestorePage());
}
}
//是否启动向导界面
if (shouldShowIntroScreen()) {
showIntroScreen();
} else {
showFirstRunActivity();
showFirstRunClings();
}
以上就是Launcher.java中onCreate方法中的部分代码,以上很多地方都用到了LauncherAppState这个单例对象,现在主要看这个类的构造方法,这个构造方法会初始化很多关键对象
private LauncherAppState() {
if (sContext == null) {
throw new IllegalStateException("LauncherAppState inited before app context set");
}
Log.v(Launcher.TAG, "LauncherAppState inited");
if (sCon