Android Launcher2源码分析
Android源码程序程序中有一个应用程序入口,官方给出的中文翻译为“启动器”。我们一下统称Launcher.
Launcher源码分析,我们还是从AndroidManifest.xml开始:
<applicationandroid:name="com.android.launcher2.LauncherApplication"android:label="@string/application_name"android:icon="@drawable/ic_launcher_home"android:hardwareAccelerated="@bool/config_hardwareAccelerated"android:largeHeap="@bool/config_largeHeap"><activityandroid:name="com.android.launcher2.Launcher"…><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>…</application>其他,我们姑且也不管,有三点我们必须说一下:
一、android:hardwareAccelerated="@bool/config_hardwareAccelerated"
指定了整个应用程序是启用硬件加速的,这样整个应用程序的运行速度会更快。
二、
android:largeHeap="@bool/config_largeHeap"指定了应用程序使用了大的堆内存,,能在一定程度上避免,对内存out of memory错误的出现。
三、
<category android:name="android.intent.category.HOME" />这个申明,相当于告诉系统这是桌面Activity。如果你希望开发自己的桌面应用。这个申明是必须的
通过这三点的设置,我们大概知道了桌面的核心。
那么,接下来我们从LauncherApplication(com/android/launcher2/LauncherApplication.java)应用程序开始分析
public void onCreate() {super.onCreate();// 在创建icon cache之前,我们需要判断屏幕的大小和屏幕的像素密度,以便创建合适大小的iconfinal int screenSize = getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;sIsScreenLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE ||screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE;sScreenDensity = getResources().getDisplayMetrics().density;mIconCache = new IconCache(this); //用来<span style="color: rgb(51, 51, 51); font-family: 宋体; font-size: 14px; line-height: 28px; text-indent: 28px; background-color: rgb(248, 248, 248);">设置了应用程序的图标的cache</span>mModel = new LauncherModel(this, mIconCache); //<span style="color: rgb(51, 51, 51); font-family: 宋体; font-size: 14px; line-height: 28px; text-indent: 28px; background-color: rgb(248, 248, 248);">LauncherModel主要用于加载桌面的图标、插件和文件夹,同时LaucherModel是一个广播接收器,在程序包发生改变、区域、或者配置文件发生改变时,都会发送广播给LaucherModel,LaucherModel会根据不同的广播来做相应加载操作</span>// 注册广播接收器IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);……registerReceiver(mModel, filter);//注册ContentObserver,监听LauncherSettings.Favorites.CONTENT_URI数据的变化ContentResolver resolver = getContentResolver();resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,mFavoritesObserver);}查看IconCache(com.android.launcher2.IconCache.java)我们很容易发现,这是一个应用程序图标(icon)缓冲生成器。正如我们刚才所说的,我们知道LauncherModel主要用于加载桌面的图标(icon)、插件(AppWidge)和文件夹(Floder) 和Shortcut。
在LauncherModel(com.android.launcher2.LauncherModel.java)中
public class LauncherModel extends BroadcastReceiver {public interface Callbacks {public boolean setLoadOnResume();public int getCurrentWorkspaceScreen();public void startBinding();public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end);public void bindFolders(HashMap<Long,FolderInfo> folders);public void finishBindingItems();public void bindAppWidget(LauncherAppWidgetInfo info);public void bindAllApplications(ArrayList<ApplicationInfo> apps);public void bindAppsAdded(ArrayList<ApplicationInfo> apps);public void bindAppsUpdated(ArrayList<ApplicationInfo> apps);public void bindAppsRemoved(ArrayList<ApplicationInfo> apps, boolean permanent);public void bindPackagesUpdated();public boolean isAllAppsVisible();public void bindSearchablesChanged();} }很明显
LauncherModel.startLoader(),开始加载的工作。launcherModel中加载好的内容会通过
LauncherModel.Callbacks接口的回调函数将数据传给需要的组件
setLoadOnResume() 由于Launcher继承自Activity,因此Launcher可能会处于paused状态(onPause()被调用),
则有可能在这段时间内资源可能发生了改变,如应用被删除或新应用安装,因此需要在onResume()中调用此方法进行重新加载。
getCurrentWorkspace() 获取当前屏幕的序号
startBinding() 通知Launcher加载开始,并更新Workspace上的shortcuts
bindItems(ArrayList<ItemInfo> shortcuts, int start, int end) 加载一批内容项到Workspace,加载的内容项包括,
Application、shortcut、folder。
bindFolders(HashMap<Long, FolderInfo> folders) 加载folder的内容
finishBindingItems()通知Launcher加载结束。
bindAppWidget(LauncherAppWidgetInfo item) 加载AppWidget到Workspace
bindAllApplications(final ArrayList<ApplicationInfo> apps)在All Apps页加载所有应用的Icon
bindAppsAdded(ArrayList<ApplicationInfo> apps)通知Launcher一个新的应用被安装,并加载这个应用
bindAppsUpdated(ArrayList<ApplicationInfo> apps)通知Launcher一个应用发生了更新
bindAppsRemoved(ArrayList<ApplicationInfo> apps, boolean permanent) 通知Launcher一个应用被删除了
bindPackagesUpdated() 通知Launcher多个应用发生了更新
isAllAppsVisible()用于在加载的过程中记录当前Launcher的状态,返回true则当前显示的All Apps
bindSearchablesChanged()当搜索/删除框状态发生改变时调用
了解了每个方法的作用之后,就可以开始进一步的分析了。
了解了大概过程,下一步。我们走到Launcher(com.android.launcher2.Launcher.java)
醒来第一眼看见的是他,然后倒头继续睡。这就是我想要的幸福。