<application android: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"> <activity android: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。如果你希望开发自己的桌面应用。这个申明是必须的
public void onCreate() { super.onCreate(); // 在创建icon cache之前,我们需要判断屏幕的大小和屏幕的像素密度,以便创建合适大小的icon final 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)缓冲生成器。
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()当搜索/删除框状态发生改变时调用
了解了每个方法的作用之后,就可以开始进一步的分析了。
public final class Launcher extends Activity implements View.OnClickListener,LauncherModel.Callbacks{ @Override protected void onCreate(Bundle savedInstanceState) { ... mModel = app.setLauncher(this); mIconCache = app.getIconCache(); ... mAppWidgetManager = AppWidgetManager.getInstance(this); mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID); mAppWidgetHost.startListening(); ... //检查本地保存的配置是否需要更新 checkForLocaleChange(); setContentView(R.layout.launcher); //对UI控件进行初始化和配置 setupViews(); //向用户展示指导的页面 showFirstRunWorkspaceCling(); registerContentObservers(); ... if (!mRestoring) { //为Launcher加载数据 mModel.startLoader(this, true); } ... }别的,我们先不管。
implements LauncherModel.Callbacks{
mModel = app.setLauncher(this);我们再来看看LauncherApplication.java中的
LauncherModel setLauncher(Launcher launcher) { mModel.initialize(launcher); return mModel; }从mModel.startLoader(true, mWorkspace.getCurrentPage());我们大概知道加载流程。但那时具体加载过程我们稍后分析
launcher.xml <com.android.launcher2.DragLayer xmlns:android="http://schemas.android.com/apk/res/android" xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher" android:id="@+id/drag_layer" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- Keep these behind the workspace so that they are not visible when we go into AllApps --> <include android:id="@+id/dock_divider" layout="@layout/workspace_divider" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/button_bar_height" android:layout_gravity="bottom" /> <include android:id="@+id/paged_view_indicator" layout="@layout/scroll_indicator" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="@dimen/button_bar_height" /> <!-- The workspace contains 5 screens of cells --> <com.android.launcher2.Workspace android:id="@+id/workspace" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="@dimen/qsb_bar_height_inset" android:paddingBottom="@dimen/button_bar_height" launcher:defaultScreen="2" launcher:cellCountX="4" launcher:cellCountY="4" launcher:pageSpacing="@dimen/workspace_page_spacing" launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left" launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right"> <include android:id="@+id/cell1" layout="@layout/workspace_screen" /> <include android:id="@+id/cell2" layout="@layout/workspace_screen" /> <include android:id="@+id/cell3" layout="@layout/workspace_screen" /> <include android:id="@+id/cell4" layout="@layout/workspace_screen" /> <include android:id="@+id/cell5" layout="@layout/workspace_screen" /> </com.android.launcher2.Workspace> <include layout="@layout/hotseat" android:id="@+id/hotseat" android:layout_width="match_parent" android:layout_height="@dimen/button_bar_height_plus_padding" android:layout_gravity="bottom" /> <include android:id="@+id/qsb_bar" layout="@layout/qsb_bar" /> <include layout="@layout/apps_customize_pane" android:id="@+id/apps_customize_pane" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="invisible" /> <include layout="@layout/workspace_cling" android:id="@+id/workspace_cling" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> <include layout="@layout/folder_cling" android:id="@+id/folder_cling" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> </com.android.launcher2.DragLayer>
首先让我们回顾一下整个加载过程的流程是怎样的
原文:http://blog.csdn.net/jaysong2012/article/details/44410385