|
第一步:我們先從LauncherApplication.java開始,先找到onCreate()方法:
- public void onCreate() {
- //設(shè)置最小堆內(nèi)存8M
- VMRuntime.getRuntime().setMinimumHeapSize(8 * 1024 * 1024); //llx modify the heapsize
- super.onCreate();
-
- //建立應(yīng)用圖標緩存器
- 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 事件監(jiān)聽器
- //LauncherModel作為廣播接收器對上面事件進行監(jiān)聽
- 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 數(shù)據(jù)變化監(jiān)聽器
- 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();
-
- //從加載本地設(shè)置
- checkForLocaleChange();setWallpaperDimension();
-
- //加載布局文件
- setContentView(R.layout.launcher);
- //初始化所有控件
- setupViews();
- registerContentObservers();
- lockAllApps();
- //從Bundle savedInstanceState獲取桌面持久化數(shù)據(jù)
- 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廣播監(jiān)聽
- 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");
- //從數(shù)據(jù)庫launcher.db中查詢中所有桌面項構(gòu)造對應(yīng)類型的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();
- }
- }
這里調(diào)用了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++) {
- //根據(jù)ItemInfo對象創(chuàng)建桌面圖標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;
- }
- }
- //.重新設(shè)置桌面圖標view 的layoutparam(類型為cellLayout.layoutparam)
- workspace.requestLayout();
- }
注意,這兩個方法都是異步調(diào)用。原因應(yīng)該很清楚:時間。
另外還要注意一下兩點:
1.桌面圖標view對象添加OnLongClickListener=laucher,由laucher負責(zé)監(jiān)聽桌面圖標view的longclick事件
2.如果桌面圖標是DropTarget對象,拖放控制器mDragController添加該view到拖放目的地列表
在Launcher.java的代碼中有bindFolders()和bindAppWidget()方法,都是回調(diào)方法。主要看下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;
- //根據(jù)appWidgetInfo創(chuàng)建桌面組件的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);
- //添加到對應(yīng)桌面的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>
當(dāng)都加載完成以后會執(zhí)行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;
- }
前面那三個都是都是回調(diào)方法,控制器當(dāng)然是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();
- }
想看仔細的,自己可以在代碼中找一下。
最后執(zhí)行
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);
- }
到這基本上就是整個的啟動過程了。
|