Android--launcher启动过程解析

第一步:我们先从LauncherApplication.java开始,先找到onCreate()方法:

[java]  view plain copy
  1. public void onCreate() {  
  2.         //设置最小堆内存8M  
  3.         VMRuntime.getRuntime().setMinimumHeapSize(8 * 1024 * 1024); //llx modify the heapsize  
  4.         super.onCreate();  
  5.   
  6.         //建立应用图标缓存器           
  7.         mIconCache = new IconCache(this);  
  8.         //建立LauncherModel  
  9.         mModel = new LauncherModel(this, mIconCache);  
  10.         // Register intent receivers          
  11.         //注册Intent.ACTION_PACKAGE_ADDED,Intent.ACTION_PACKAGE_REMOVED,  
  12.        //Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE,  
  13.        //Intent.ACTION_LOCALE_CHANGED 事件监听器  
  14.        //LauncherModel作为广播接收器对上面事件进行监听  
  15.       IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);  
  16.        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);  
  17.        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);  
  18.        filter.addDataScheme("package");  
  19.        registerReceiver(mModel, filter);  
  20.   
  21.        filter = new IntentFilter();  
  22.        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);  
  23.        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);  
  24.        registerReceiver(mModel, filter);  
  25.   
  26.        filter = new IntentFilter();  
  27.        filter.addAction(Intent.ACTION_LOCALE_CHANGED);  
  28.        registerReceiver(mModel, filter);  
  29.          
  30.      // Register for changes to the favorites  
  31.         //添加对桌面favorites content provider 数据变化监听器  
  32.        ContentResolver resolver = getContentResolver();  
  33.        resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,mFavoritesObserver);  
  34.  }  
第二步:看下Launcher.java中的onCreate()方法:
[java]  view plain copy
  1. protected void onCreate(Bundle savedInstanceState) {  
  2.         super.onCreate(savedInstanceState);  
  3.         //获取LauncherApplication LauncherModel mIconCache等LauncherApplication初始化的对象  
  4.         LauncherApplication app = ((LauncherApplication)getApplication());  
  5.         mModel = app.setLauncher(this);  
  6.         mIconCache = app.getIconCache();  
  7.         //新建拖放控制器new DragController(this)  
  8.         mDragController = new DragController(this);  
  9.         mInflater = getLayoutInflater();  
  10.   
  11.         //获取桌面组件管理器,启动桌面组件host  
  12.         mAppWidgetManager = AppWidgetManager.getInstance(this);  
  13.         mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);  
  14.         mAppWidgetHost.startListening();  
  15.         if (PROFILE_STARTUP) {  
  16.             android.os.Debug.startMethodTracing("/sdcard/launcher");  
  17.         }  
  18.         //从array.hotseats中加载所有的hotseats  
  19.         loadHotseats();  
  20.   
  21.         //从加载本地设置  
  22.         checkForLocaleChange();setWallpaperDimension();  
  23.   
  24.         //加载布局文件  
  25.         setContentView(R.layout.launcher);  
  26.         //初始化所有控件  
  27.         setupViews();  
  28.         registerContentObservers();  
  29.         lockAllApps();  
  30.         //从Bundle savedInstanceState获取桌面持久化数据  
  31.         mSavedState = savedInstanceState;  
  32.         restoreState(mSavedState);  
  33.   
  34.         if (PROFILE_STARTUP) {  
  35.            android.os.Debug.stopMethodTracing();  
  36.          }  
  37.   
  38.         if (!mRestoring) {  
  39.         //LauncherModel.Loader.startLoader() 代码同步处理  
  40.         mModel.startLoader(thistrue);  
  41.          }  
  42.   
  43.        // For handling default keys  
  44.         mDefaultKeySsb = new SpannableStringBuilder();  
  45.         Selection.setSelection(mDefaultKeySsb, 0);  
  46.   
  47.         //注册Intent.ACTION_CLOSE_SYSTEM_DIALOGS广播监听  
  48.         IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);  
  49.         registerReceiver(mCloseSystemDialogsReceiver, filter);  
  50.      }  
第三步:加载桌面项 : 在LauncherModel.java的Thread的run方法 , 是在主线程完成以后才开始加载

[java]  view plain copy
  1. public void run() {  
  2.             // Optimize for end-user experience: if the Launcher is up and // running with the  
  3.             // All Apps interface in the foreground, load All Apps first. Otherwise, load the  
  4.             // workspace first (default).  
  5.             final Callbacks cbk = mCallbacks.get();  
  6.             final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;  
  7.   
  8.             keep_running: {  
  9.                 // Elevate priority when Home launches for the first time to avoid  
  10.                 // starving at boot time. Staring at a blank home is not cool.  
  11.                 synchronized (mLock) {  
  12.                     android.os.Process.setThreadPriority(mIsLaunching  
  13.                             ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);  
  14.                 }  
  15.                 //判断是否先加载桌面  
  16.                 if (loadWorkspaceFirst) {  
  17.                     if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");  
  18.                     //从数据库launcher.db中查询中所有桌面项构造对应类型的ItemInfo对象存入  
  19.                     loadAndBindWorkspace();  
  20.                 } else {  
  21.                     if (DEBUG_LOADERS) Log.d(TAG, "step 1: special: loading all apps");  
  22.                     loadAndBindAllApps();  
  23.                 }  
  24.                 if (mStopped) {  
  25.                     break keep_running;  
  26.                 }  
  27.   
  28.                 // Whew! Hard work done.  Slow us down, and wait until the UI thread has  
  29.                 // settled down.  
  30.                 synchronized (mLock) {  
  31.                     if (mIsLaunching) {  
  32.                         android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);  
  33.                     }  
  34.                 }  
  35.                 waitForIdle();  
  36.   
  37.                 // second step  
  38.                 if (loadWorkspaceFirst) {  
  39.                     if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");  
  40.                     loadAndBindAllApps();  
  41.                 } else {  
  42.                     if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace");  
  43.                     loadAndBindWorkspace();  
  44.                 }  
  45.             }  

这里调用了Launcher.java中startBinding方法

[java]  view plain copy
  1. public void startBinding() {  
  2.         final Workspace workspace = mWorkspace;  
  3.         int count = workspace.getChildCount();  
  4.         for (int i = 0; i < count; i++) {  
  5.             // Use removeAllViewsInLayout() to avoid an extra requestLayout() and invalidate().  
  6.             ((ViewGroup) workspace.getChildAt(i)).removeAllViewsInLayout();  
  7.         }  
  8.   
  9.         if (DEBUG_USER_INTERFACE) {  
  10.             android.widget.Button finishButton = new android.widget.Button(this);  
  11.             finishButton.setText("Finish");  
  12.             workspace.addInScreen(finishButton, 10011);  
  13.   
  14.             finishButton.setOnClickListener(new android.widget.Button.OnClickListener() {  
  15.                 public void onClick(View v) {  
  16.                     finish();  
  17.                 }  
  18.             });  
  19.         }  
  20.     }  
还有Launcher.java的bindItem()方法:

[java]  view plain copy
  1. public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end) {  
  2.         setLoadOnResume();  
  3.         //获取桌面的celllayout对象,也就是workspace下5个用户桌面中的一个  
  4.         final Workspace workspace = mWorkspace;  
  5.         for (int i=start; i<end; i++) {  
  6.             //根据ItemInfo对象创建桌面图标view对象  
  7.             final ItemInfo item = shortcuts.get(i);  
  8.             mDesktopItems.add(item);  
  9.             switch (item.itemType) {  
  10.                 case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:  
  11.                 case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:  
  12.                     final View shortcut = createShortcut((ShortcutInfo)item);  
  13.                    //获取item.screen, item.cellX, item.cellY, spanX, spanY并添加到屏幕上。  
  14.                     workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 11,false);  
  15.                     break;  
  16.                 case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:  
  17.                     final FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,  
  18.                             (ViewGroup) workspace.getChildAt(workspace.getCurrentScreen()),  
  19.                             (UserFolderInfo) item);  
  20.                     workspace.addInScreen(newFolder, item.screen, item.cellX, item.cellY, 11,false);  
  21.                     break;  
  22.                 case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:  
  23.                     final FolderIcon newLiveFolder = LiveFolderIcon.fromXml(  
  24.                             R.layout.live_folder_icon, this,  
  25.                             (ViewGroup) workspace.getChildAt(workspace.getCurrentScreen()),  
  26.                             (LiveFolderInfo) item);  
  27.                     workspace.addInScreen(newLiveFolder, item.screen, item.cellX, item.cellY, 11,false);  
  28.                     break;  
  29.             }  
  30.         }  
  31.          //.重新设置桌面图标view 的layoutparam(类型为cellLayout.layoutparam)  
  32.           workspace.requestLayout();  
  33.     }  
注意,这两个方法都是异步调用。原因应该很清楚:时间。

另外还要注意一下两点:

         1.桌面图标view对象添加OnLongClickListener=laucher,由laucher负责监听桌面图标view的longclick事件

         2.如果桌面图标是DropTarget对象,拖放控制器mDragController添加该view到拖放目的地列表

Launcher.java的代码中有bindFolders()bindAppWidget()方法,都是回调方法。主要看下bindAppWidget()方法吧。

[java]  view plain copy
  1. /** 
  2.  
  3.      * Add the views for a widget to the workspace. 
  4.      * 
  5.      * Implementation of the method from LauncherModel.Callbacks. 
  6.      */  
  7.     public void bindAppWidget(LauncherAppWidgetInfo item) {  
  8.         setLoadOnResume();  
  9.   
  10.         final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0;  
  11.         if (DEBUG_WIDGETS) {  
  12.             Log.d(TAG, "bindAppWidget: " + item);  
  13.         }  
  14.         final Workspace workspace = mWorkspace;  
  15.         //获取LauncherAppWidgetInfo的appWidgetId  
  16.         final int appWidgetId = item.appWidgetId;  
  17.         //根据appWidgetInfo创建桌面组件的view AppWidgetHostView对象  
  18.         final AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);  
  19.         if (DEBUG_WIDGETS) {  
  20.             Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component " + appWidgetInfo.provider);  
  21.         }  
  22.   
  23.         item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);  
  24.   
  25.         item.hostView.setAppWidget(appWidgetId, appWidgetInfo);  
  26.         item.hostView.setTag(item);  
  27.         //添加到对应桌面的cell  
  28.         workspace.addInScreen(item.hostView, item.screen, item.cellX,  
  29.                 item.cellY, item.spanX, item.spanY, false);  
  30.   
  31.         workspace.requestLayout();  
  32.   
  33.         mDesktopItems.add(item);  
  34.   
  35.         if (DEBUG_WIDGETS) {  
  36.             Log.d(TAG, "bound widget id="+item.appWidgetId+" in "  
  37.                     + (SystemClock.uptimeMillis()-start) + "ms");  
  38.         }  
  39.     }  
  40. <span style="font-size:16px;">  
  41. </span>  

当都加载完成以后会执行finishBindingItems():

[java]  view plain copy
  1. /** 
  2.      * Callback saying that there aren't any more items to bind. 
  3.      * 
  4.      * Implementation of the method from LauncherModel.Callbacks. 
  5.      */  
  6.     public void finishBindingItems() {  
  7.         setLoadOnResume();  
  8.         if (mSavedState != null) {  
  9.             if (!mWorkspace.hasFocus()) {  
  10.                 mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();  
  11.             }  
  12.             final long[] userFolders = mSavedState.getLongArray(RUNTIME_STATE_USER_FOLDERS);  
  13.             if (userFolders != null) {  
  14.                 for (long folderId : userFolders) {  
  15.                     final FolderInfo info = sFolders.get(folderId);  
  16.                     if (info != null) {  
  17.                         openFolder(info);  
  18.                     }  
  19.                 }  
  20.                 final Folder openFolder = mWorkspace.getOpenFolder();  
  21.                 if (openFolder != null) {  
  22.                     openFolder.requestFocus();  
  23.                 }  
  24.             }  
  25.             mSavedState = null;  
  26.         }  
  27.         if (mSavedInstanceState != null) {  
  28.             super.onRestoreInstanceState(mSavedInstanceState);  
  29.             mSavedInstanceState = null;  
  30.         }  
  31.         mWorkspaceLoading = false;  
  32.     }  

前面那三个都是都是回调方法,控制器当然是LauncherModel.java了,让我们在代码里看一下:

其接口定义如下:

[java]  view plain copy
  1. public interface Callbacks {  
  2.         public boolean setLoadOnResume();  
  3.         public int getCurrentWorkspaceScreen();  
  4.         public void startBinding();  
  5.         public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end);  
  6.         public void bindFolders(HashMap<Long,FolderInfo> folders);  
  7.         public void finishBindingItems();  
  8.         public void bindAppWidget(LauncherAppWidgetInfo info);  
  9.         public void bindAllApplications(ArrayList<ApplicationInfo> apps);  
  10.         public void bindAppsAdded(ArrayList<ApplicationInfo> apps);  
  11.         public void bindAppsUpdated(ArrayList<ApplicationInfo> apps);  
  12.         public void bindAppsRemoved(ArrayList<ApplicationInfo> apps, boolean permanent);  
  13.         public boolean isAllAppsVisible();  
  14.     }  

想看仔细的,自己可以在代码中找一下。

最后执行 bindAllApplications() , bindAppsAdded()方法

[java]  view plain copy
  1. public void bindAllApplications(ArrayList<ApplicationInfo> apps) {  
  2.         mAllAppsGrid.setApps(apps);  
  3.     }  
  4.     /** 
  5.      * A package was installed. 
  6.      * 
  7.      * Implementation of the method from LauncherModel.Callbacks. 
  8.      */  
  9.     public void bindAppsAdded(ArrayList<ApplicationInfo> apps) {  
  10.         setLoadOnResume();  
  11.         removeDialog(DIALOG_CREATE_SHORTCUT);  
  12.         mAllAppsGrid.addApps(apps);  
  13.     }  

到这基本上就是整个的启动过程了。

转载自:http://blog.csdn.net/aomandeshangxiao/article/details/6988326


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值