第一步:我们先从LauncherApplication.java开始,先找到onCreate()方法:
- public void onCreate() {
- //设置最小堆内存8M
- VMRuntime.getRuntime().setMinimumHeapSize(8 * 1024 * 1024); //llx modify the heapsize
- super.onCreate();
-
- //建立应用图标缓存器
- mIconCache = new IconCache(this);
- //建立LauncherModel
- mModel = new LauncherModel(this, mIconCache);
- // Register intent receivers
- //注册Intent.ACTION_PACKAGE_ADDED,Intent.ACTION_PACKAGE_REMOVED,
- //Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE,
- //Intent.ACTION_LOCALE_CHANGED 事件监听器
- //LauncherModel作为广播接收器对上面事件进行监听
- IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addDataScheme("package");
- registerReceiver(mModel, filter);
-
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
- filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- registerReceiver(mModel, filter);
-
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_LOCALE_CHANGED);
- registerReceiver(mModel, filter);
-
- // Register for changes to the favorites
- //添加对桌面favorites content provider 数据变化监听器
- ContentResolver resolver = getContentResolver();
- resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,mFavoritesObserver);
- }
第二步:看下Launcher.java中的onCreate()方法:
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //获取LauncherApplication LauncherModel mIconCache等LauncherApplication初始化的对象
- LauncherApplication app = ((LauncherApplication)getApplication());
- mModel = app.setLauncher(this);
- mIconCache = app.getIconCache();
- //新建拖放控制器new DragController(this)
- mDragController = new DragController(this);
- mInflater = getLayoutInflater();
-
- //获取桌面组件管理器,启动桌面组件host
- mAppWidgetManager = AppWidgetManager.getInstance(this);
- mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
- mAppWidgetHost.startListening();
- if (PROFILE_STARTUP) {
- android.os.Debug.startMethodTracing("/sdcard/launcher");
- }
- //从array.hotseats中加载所有的hotseats
- loadHotseats();
-
- //从加载本地设置
- checkForLocaleChange();setWallpaperDimension();
-
- //加载布局文件
- setContentView(R.layout.launcher);
- //初始化所有控件
- setupViews();
- registerContentObservers();
- lockAllApps();
- //从Bundle savedInstanceState获取桌面持久化数据
- mSavedState = savedInstanceState;
- restoreState(mSavedState);
-
- if (PROFILE_STARTUP) {
- android.os.Debug.stopMethodTracing();
- }
-
- if (!mRestoring) {
- //LauncherModel.Loader.startLoader() 代码同步处理
- mModel.startLoader(this, true);
- }
-
- // For handling default keys
- mDefaultKeySsb = new SpannableStringBuilder();
- Selection.setSelection(mDefaultKeySsb, 0);
-
- //注册Intent.ACTION_CLOSE_SYSTEM_DIALOGS广播监听
- IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- registerReceiver(mCloseSystemDialogsReceiver, filter);
- }
第三步:加载桌面项:
在LauncherModel.java的Thread的run方法,
是在主线程完成以后才开始加载。
- public void run() {
- // Optimize for end-user experience: if the Launcher is up and // running with the
- // All Apps interface in the foreground, load All Apps first. Otherwise, load the
- // workspace first (default).
- final Callbacks cbk = mCallbacks.get();
- final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;
-
- keep_running: {
- // Elevate priority when Home launches for the first time to avoid
- // starving at boot time. Staring at a blank home is not cool.
- synchronized (mLock) {
- android.os.Process.setThreadPriority(mIsLaunching
- Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
- }
- //判断是否先加载桌面
- if (loadWorkspaceFirst) {
- if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
- //从数据库launcher.db中查询中所有桌面项构造对应类型的ItemInfo对象存入
- loadAndBindWorkspace();
- } else {
- if (DEBUG_LOADERS) Log.d(TAG, "step 1: special: loading all apps");
- loadAndBindAllApps();
- }
- if (mStopped) {
- break keep_running;
- }
-
- // Whew! Hard work done. Slow us down, and wait until the UI thread has
- // settled down.
- synchronized (mLock) {
- if (mIsLaunching) {
- android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- }
- }
- waitForIdle();
-
- // second step
- if (loadWorkspaceFirst) {
- if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
- loadAndBindAllApps();
- } else {
- if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace");
- loadAndBindWorkspace();
- }
- }
这里调用了Launcher.java中startBinding方法
- public void startBinding() {
- final Workspace workspace = mWorkspace;
- int count = workspace.getChildCount();
- for (int i = 0; i < count; i++) {
- // Use removeAllViewsInLayout() to avoid an extra requestLayout() and invalidate().
- ((ViewGroup) workspace.getChildAt(i)).removeAllViewsInLayout();
- }
-
- if (DEBUG_USER_INTERFACE) {
- android.widget.Button finishButton = new android.widget.Button(this);
- finishButton.setText("Finish");
- workspace.addInScreen(finishButton, 1, 0, 0, 1, 1);
-
- finishButton.setOnClickListener(new android.widget.Button.OnClickListener() {
- public void onClick(View v) {
- finish();
- }
- });
- }
- }
还有Launcher.java的bindItem()方法:
- public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end) {
- setLoadOnResume();
- //获取桌面的celllayout对象,也就是workspace下5个用户桌面中的一个
- final Workspace workspace = mWorkspace;
- for (int i=start; i<end; i++) {
- //根据ItemInfo对象创建桌面图标view对象
- final ItemInfo item = shortcuts.get(i);
- mDesktopItems.add(item);
- switch (item.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
- final View shortcut = createShortcut((ShortcutInfo)item);
- //获取item.screen, item.cellX, item.cellY, spanX, spanY并添加到屏幕上。
- workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1,false);
- break;
- case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
- final FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
- (ViewGroup) workspace.getChildAt(workspace.getCurrentScreen()),
- (UserFolderInfo) item);
- workspace.addInScreen(newFolder, item.screen, item.cellX, item.cellY, 1, 1,false);
- break;
- case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
- final FolderIcon newLiveFolder = LiveFolderIcon.fromXml(
- R.layout.live_folder_icon, this,
- (ViewGroup) workspace.getChildAt(workspace.getCurrentScreen()),
- (LiveFolderInfo) item);
- workspace.addInScreen(newLiveFolder, item.screen, item.cellX, item.cellY, 1, 1,false);
- break;
- }
- }
- //.重新设置桌面图标view 的layoutparam(类型为cellLayout.layoutparam)
- workspace.requestLayout();
- }
注意,这两个方法都是异步调用。原因应该很清楚:时间。
另外还要注意一下两点:
1.桌面图标view对象添加OnLongClickListener=laucher,由laucher负责监听桌面图标view的longclick事件
2.如果桌面图标是DropTarget对象,拖放控制器mDragController添加该view到拖放目的地列表
在Launcher.java的代码中有bindFolders()和bindAppWidget()方法,都是回调方法。主要看下bindAppWidget()方法吧。
- /**
-
- * Add the views for a widget to the workspace.
- *
- * Implementation of the method from LauncherModel.Callbacks.
- */
- public void bindAppWidget(LauncherAppWidgetInfo item) {
- setLoadOnResume();
-
- final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0;
- if (DEBUG_WIDGETS) {
- Log.d(TAG, "bindAppWidget: " + item);
- }
- final Workspace workspace = mWorkspace;
- //获取LauncherAppWidgetInfo的appWidgetId
- final int appWidgetId = item.appWidgetId;
- //根据appWidgetInfo创建桌面组件的view AppWidgetHostView对象
- final AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
- if (DEBUG_WIDGETS) {
- Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component " + appWidgetInfo.provider);
- }
-
- item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
-
- item.hostView.setAppWidget(appWidgetId, appWidgetInfo);
- item.hostView.setTag(item);
- //添加到对应桌面的cell
- workspace.addInScreen(item.hostView, item.screen, item.cellX,
- item.cellY, item.spanX, item.spanY, false);
-
- workspace.requestLayout();
-
- mDesktopItems.add(item);
-
- if (DEBUG_WIDGETS) {
- Log.d(TAG, "bound widget id="+item.appWidgetId+" in "
- + (SystemClock.uptimeMillis()-start) + "ms");
- }
- }
- <span style="font-size:16px;">
- </span>
当都加载完成以后会执行finishBindingItems():
- /**
- * Callback saying that there aren't any more items to bind.
- *
- * Implementation of the method from LauncherModel.Callbacks.
- */
- public void finishBindingItems() {
- setLoadOnResume();
- if (mSavedState != null) {
- if (!mWorkspace.hasFocus()) {
- mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();
- }
- final long[] userFolders = mSavedState.getLongArray(RUNTIME_STATE_USER_FOLDERS);
- if (userFolders != null) {
- for (long folderId : userFolders) {
- final FolderInfo info = sFolders.get(folderId);
- if (info != null) {
- openFolder(info);
- }
- }
- final Folder openFolder = mWorkspace.getOpenFolder();
- if (openFolder != null) {
- openFolder.requestFocus();
- }
- }
- mSavedState = null;
- }
- if (mSavedInstanceState != null) {
- super.onRestoreInstanceState(mSavedInstanceState);
- mSavedInstanceState = null;
- }
- mWorkspaceLoading = false;
- }
前面那三个都是都是回调方法,控制器当然是LauncherModel.java了,让我们在代码里看一下:
其接口定义如下:
- 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 boolean isAllAppsVisible();
- }
想看仔细的,自己可以在代码中找一下。
最后执行
bindAllApplications()
, bindAppsAdded()方法:
- public void bindAllApplications(ArrayList<ApplicationInfo> apps) {
- mAllAppsGrid.setApps(apps);
- }
- /**
- * A package was installed.
- *
- * Implementation of the method from LauncherModel.Callbacks.
- */
- public void bindAppsAdded(ArrayList<ApplicationInfo> apps) {
- setLoadOnResume();
- removeDialog(DIALOG_CREATE_SHORTCUT);
- mAllAppsGrid.addApps(apps);
- }
到这基本上就是整个的启动过程了。
|