1.1 源代码路径
apk生成的路径 /system/app/Launcher2.apk
源代码路径 /packages/apps/Launcher2是Launcher2.ap的源代码
Launcher2.apk是android系统启动后的第一个android应用 ,这个应用就是android系统的home程序,也就是进入
android系统后首先看到的UI,如果只是定制android rom的ui,主要修改的就是launcher2的源代码
1.2 课程学习内容
桌面图标如何加载
如何处理app widget
如何显示程序列表
如何在桌面上放置快捷方式
1.3 分析 AndroidManifest.xml
<application
android:name="com.android.launcher2.LauncherApplication"
android:label="@string/application_name"
android:icon="@mipmap/ic_launcher_home"
android:hardwareAccelerated="true"
android:largeHeap="@bool/config_largeHeap"
android:supportsRtl="true">
<activity
android:name="com.android.launcher2.Launcher"
android:launchMode="singleTask" --> Launcher窗口的创建模式为singleTask,所以launcher窗口不会创建多个实例,而且就算在launcher窗口显示后,在同一个回退栈中再放入多个窗口,当再次
显示launcher窗口后,这些窗口都会被释放
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:resumeWhilePausing="true"
android:theme="@style/Theme"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="nosensor">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" /> --> android系统会自动寻找指定android.intent.category.HOME的窗口,并在android系统成功后第一次运行时显示该窗口(运行包含该 窗口的android应用)
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY"/>
</intent-filter>
</activity>
1.4 初始化launcherHomeUi
oncreate方法中完成初始化: Launcher.onCrete方法和主布局文件launcher.xml
Launcher2的主布局文件launcher.xml
横屏和竖屏分别在res/lanyout-land/launcher.xml和res/lanyout-port/launcher.xml
初始化android桌面
@Override
protected void onCreate(Bundle savedInstanceState) {
if (DEBUG_STRICT_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
}
super.onCreate(savedInstanceState);
LauncherApplication app = ((LauncherApplication)getApplication()); //创建一些launcher2要用到的管理对象,获取LauncherApplication对象
mSharedPrefs = getSharedPreferences(LauncherApplication.getSharedPreferencesKey(),
Context.MODE_PRIVATE);
mModel = app.setLauncher(this);
mIconCache = app.getIconCache();
mDragController = new DragController(this);
mInflater = getLayoutInflater();
mAppWidgetManager = AppWidgetManager.getInstance(this);
mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
mAppWidgetHost.startListening();
// If we are getting an onCreate, we can actually preempt onResume and unset mPaused here,
// this also ensures that any synchronous binding below doesn't re-trigger another
// LauncherModel load.
mPaused = false; //使用bool值设置一个判断,防止重新装载android桌面
if (PROFILE_STARTUP) {
android.os.Debug.startMethodTracing(
Environment.getExternalStorageDirectory() + "/launcher");
}
checkForLocaleChange();
setContentView(R.layout.launcher);
setupViews(); //装载视图
showFirstRunWorkspaceCling();
registerContentObservers();
lockAllApps();
mSavedState = savedInstanceState;
restoreState(mSavedState);
// Update customization drawer _after_ restoring the states
if (mAppsCustomizeContent != null) {
mAppsCustomizeContent.onPackagesUpdated(
LauncherModel.getSortedWidgetsAndShortcuts(this));
}
if (PROFILE_STARTUP) {
android.os.Debug.stopMethodTracing();
}
if (!mRestoring) {
if (sPausedFromUserAction) {
// If the user leaves launcher, then we should just load items asynchronously when
// they return.
mModel.startLoader(true, -1); //如果用户离开android桌面,再回到桌面时,使用异步方式重新装载桌面
} else {
// We only load the page synchronously if the user rotates (or triggers a
// configuration change) while launcher is in the foreground
mModel.startLoader(true, mWorkspace.getCurrentPage()); //如果用户旋转android设备造成了配置的变化,应该同步加载当前页面
}
}
if (!mModel.isAllAppsLoaded()) {
ViewGroup appsCustomizeContentParent = (ViewGroup) mAppsCustomizeContent.getParent();
mInflater.inflate(R.layout.apps_customize_progressbar, appsCustomizeContentParent);
}
// For handling default keys
//其他初始化工作
mDefaultKeySsb = new SpannableStringBuilder();
Selection.setSelection(mDefaultKeySsb, 0);
IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
registerReceiver(mCloseSystemDialogsReceiver, filter); //注册可以拦截关闭系统对话框的广播接收器
updateGlobalIcons(); //更新桌面上的图标
// On large interfaces, we want the screen to auto-rotate based on the current orientation
unlockScreenOrientation(true); //解锁屏幕旋转状态
}
这样就完成了初始化的一个操作,下面简单总结一下整个过程
第1步:创建管理对象
oncreate方法一开始会获取或者创建launcher2要用到的管理对象
LauncherApplication app = ((LauncherApplication)getApplication());
维护launcher2在内存中状态的launcherModel对象,处理桌面图标的iconcache对象
处理拖动操作的DragController对象等
mIconCache = new IconCache(this);
mModel = new LauncherModel(this, mIconCache);
第2步:获取状态标志
mSharedPrefs = getSharedPreferences(LauncherApplication.getSharedPreferencesKey(),
Context.MODE_PRIVATE);
第3步:装载视图
setupViews()方法从launcher.xml布局文件中创建各种视图对象
第4步:装载所有的android应用
所有指的是包含指定下面的intent filter的窗口的android应用
使用的方法mModel.startLoader,该方法可以同步或异步装载所有的应用程序,也就是
我们在应用列表中看到的那些图标
第5步:其他初始化工作
主要完成一些收尾工作,如注册广播接收器
registerReceiver(mCloseSystemDialogsReceiver, filter);
调用updateGlobalIcons();方法更新桌面图标
到这里onCreate方法就执行完毕,后面我会分析LauncherApplication这个对象
注:本文的创作是根据李宁的书籍android深度探索进行分解的