第一步:我们先从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");        }    }

当都加载完成以后会执行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);    }

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


PS:这篇文章没有太多文字性的东西,关于代码的问题,请看代码注释,比较详细了。如果有疑问,欢迎留言探讨!

更多相关文章

  1. Android(安卓)-- 桌面悬浮,仿360
  2. android8.1 系统应用使用FileProvider时提示没有权限
  3. Android(安卓)BitmapFactory用法总结
  4. Android使用post方式上传图片到服务器的方法
  5. android 6.0 ConnectionService
  6. Android点击button触发Toast事件,弹出一个小小的消息框,几秒钟之
  7. 存储容量检测 注意构建StatFs对象的参数合法性
  8. INSTALL_FAILED_TEST_ONLY
  9. android phone application 通知missed call的过程

随机推荐

  1. Android(安卓)通知栏系列....
  2. android 零散笔记不定期更新 v16
  3. Android(安卓)中文 API (28) —— CheckedT
  4. Android事件分发机制源码分析
  5. Gradle(三)构建任务
  6. Mono for Android(安卓)(2)-- Android应用
  7. Android(安卓)DialogFragment(1)
  8. 为android-support-v4.jar打包源码
  9. 创建适配器时报:ERROR/AndroidRuntime(17
  10. Android(安卓)achartengine统计图