转载自:http://bbs.9ria.com/thread-224974-1-1.html
前面两篇文章都是写有关Launcher配置文件的修改,代码方面涉及不多,今天开始进入Launcher代码分析。
我们开机启动Launcher,Launcher是由Activity Manager启动的,而Activity Manager是由system server启动。
1、Launcher进程启动过程
可以由下面图看到Launcher进程是如何被创建启动:
Activity Manager通过发送Intend来启动Launcher。
- Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);intent.setComponent(mTopComponent);
- if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
- intent.addCategory(Intent.CATEGORY_HOME);
- }startActivityLocked(null, intent, null, null, 0, aInfo,
- null, null, 0, 0, 0, false, false);
复制代码
因此,如果你要开机启动一个替换Launcher的程序,只要在程序里面加入action.MAIN 、
category.HOME、category.DEFAULT就可以。如果出现多个程序都加入这种intent,系统会弹出让你选择
哪个作为启动器。
2、Launcher初始化——LauncherApplication。
Application类,我想大部分做Android应用的朋友都用过,每个Android应用默认都有一个Application类,
你也可以继承Application类,然后加入自己代码。Application是一个全局的应用类,在AndroidManifest.xml
我们也可以找到Application标签。
<application <="" application[="" size][="" font]
- 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"
- android:configChanges="locale">
复制代码
Android四大组件的声明都需要放到application标签里面,默认使用的是系统的Application类,如果你在项目
里面重载了它。就需要在标签,name属性下写上你的新的Application类名。Launcher里面就是继承了Application
为LauncherApplication。应用启动的时候首先会加载Application。
我们可以看到Launcher主类Launcher.java的onCreate函数里面,第一个就是获取Application的实例。
- LauncherApplication app = ((LauncherApplication)getApplication());
复制代码
接下来我们看看LauncherApplication里面初始化,LauncherApplication大部分工作就是在初始化完成,剩下都是
一些返回接口。
- @Override
- public void onCreate() {
- super.onCreate();
复制代码
//获取屏幕大小,主要用来区分手机还是平板
- 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;
- //IconCahe里面保存了界面所有应用图标的绘画需要的数据,这个到时候具体分析再说。 //加入这东西的主要原因是为了提高绘画界面的效率
- mIconCache = new IconCache(this);
- //数据库加载类,LauncherModel是Launcher里面非常重要的一个类,相当于MVC模式里面的
- //Model功能,管理数据和初始化数据
- mModel = new LauncherModel(this, mIconCache);
- //下面注册了一些监听器,主要包含APK文件更新删除等数据变化的时候接收的通知
- //接收通知后,主要是用来更新Launcher里面的数据库。因为桌面应用图标数据,只会加载一次
- 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);
- filter.addAction(Intent.ACTION_LOCALE_CHANGED);
- filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
- registerReceiver(mModel, filter);
- filter = new IntentFilter();
- filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
- registerReceiver(mModel, filter);
- filter = new IntentFilter();
- filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
- registerReceiver(mModel, filter);
- //contentresolver则是用于管理所有程序的contentprovider实例
- ContentResolver resolver = getContentResolver();
- //注册内容观察者,监听application数据库变化,回调
- resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI,
- true, mFavoritesObserver);
- }
复制代码
上面是LauncherApplication最主要的工作,初始化整个Launcher的一些关键类,和注册一些监听器。主要都是用
来监听应用的安装更新删除等导致Launcher数据库变化的操作。Launcher数据都是使用contentprovider来提供数据。
其中注册的监听接口是
- private final ContentObserver mFavoritesObserver = new ContentObserver(new
- Handler())
- {
- @Override
- public void onChange(boolean selfChange)
- { //重新加载界面数据
- mModel.startLoader(LauncherApplication.this, false);
- }
- };
复制代码
LauncherSettings.Favorites.CONTENT_URI里面数据发生变化的时候,都会调用mModel.startLoader()接口,重新加载Launcher的数据。startLoader的具体操作,我后面分析LauncherModel类的时候会分析。这一块涉及Launcher所有数据加载。剩下的接都是返回初始化时候创建的对象或者获取屏幕密度、获取是否大屏幕。后面很多处理都需要判断是否是大屏幕,4.0以后手机平板都共用一套系统,导致多了很多处理。
3、Launcher.java初始化
Launcher.java是Launcher里面最主要的类,是一个Activity。启动的第一个组件。既然是Activity,我们要分析它
初始化,毫无疑问,需要找到onCreate()里面分析。把主要一些分析用注释方式写在代码里面,这样比较方便阅读。
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //获取Application 实例
- LauncherApplication app = ((LauncherApplication)getApplication());
- //LauncherModel类里面获取Launcher的对象引用
- mModel = app.setLauncher(this);
- //获取IconCache,IconCache在Application里面初始化
- mIconCache = app.getIconCache();
- mDragController = new DragController(this);
- mInflater = getLayoutInflater();
- mAppWidgetManager = AppWidgetManager.getInstance(this);
- //监听widget改变,以后在Model里面回调处理的结果
- mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
- mAppWidgetHost.startListening();
- //这个是设置Launcher的跟踪调试文件,下面很多信息会写到这个文件里面。
- if (PROFILE_STARTUP) {
- android.os.Debug.startMethodTracing(
- Environment.getExternalStorageDirectory() + "/launcher");
- }
- //读取本地配置,保存更新配置,清空IconCache
- checkForLocaleChange();
- setContentView(R.layout.launcher);
- //对所有的UI控件进行加载和配置
- setupViews();
- //显示操作提示,第一次启动的时候才会显示
- showFirstRunWorkspaceCling();
- //注册监控Launcher数据库变化
- registerContentObservers();
- //锁住APP,初始化不能操作。
- lockAllApps();
- mSavedState = savedInstanceState;
- restoreState(mSavedState);
- // Update customization drawer _after_ restoring the states
- if (mAppsCustomizeContent != null) {
- mAppsCustomizeContent.onPackagesUpdated();
- }
- if (PROFILE_STARTUP) {
- android.os.Debug.stopMethodTracing();
- }
- //加载启动数据,所有界面数据(快捷方式、folder、widget、allApp)等在loader里面加载,这部分后面我会详细分析。
- if (!mRestoring) {
- mModel.startLoader(this, true);
- }
- if (!mModel.isAllAppsLoaded()) {
- ViewGroup appsCustomizeContentParent = (ViewGroup)
- mAppsCustomizeContent.getParent();
- mInflater.inflate(R.layout.apps_customize_progressbar,
- appsCustomizeContentParent);
- }
- // For handling default keys
- mDefaultKeySsb = new SpannableStringBuilder();
- Selection.setSelection(mDefaultKeySsb, 0);
- IntentFilter filter = new
- IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- registerReceiver(mCloseSystemDialogsReceiver, filter);
- //下面这几个就是Android原生界面上的Market、搜索、声音输入按钮的默认图标显示。
- boolean searchVisible = false;
- boolean voiceVisible = false;
- // If we have a saved version of these external icons, we load them up
- immediately
- int coi = getCurrentOrientationIndexForGlobalIcons();
- if (sGlobalSearchIcon[coi] == null || sVoiceSearchIcon[coi] == null ||
- sAppMarketIcon[coi] == null) {
- updateAppMarketIcon();
- searchVisible = updateGlobalSearchIcon();
- voiceVisible = updateVoiceSearchIcon(searchVisible);
- }
- if (sGlobalSearchIcon[coi] != null) {
- updateGlobalSearchIcon(sGlobalSearchIcon[coi]);
- searchVisible = true;
- }
- if (sVoiceSearchIcon[coi] != null) {
- updateVoiceSearchIcon(sVoiceSearchIcon[coi]);
- voiceVisible = true;
- }
- if (sAppMarketIcon[coi] != null) {
- updateAppMarketIcon(sAppMarketIcon[coi]);
- }
- mSearchDropTargetBar.onSearchPackagesChanged(searchVisible,
- voiceVisible);
- // On large interfaces, we want the screen to auto-rotate based on the
- current orientation
- if (LauncherApplication.isScreenLarge() || Build.TYPE.contentEquals("eng"))
- {
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
- }
- Log.i(TAG,"------------------------>Launcher init over") ;
- }
复制代码
上面就是Launcher.java的初始化,大部分我都写了注释。其实这里最主要的工作是加载界面数据:
mModel.startLoader(this, true); 这块实现是在LauncherModel里面实现的。下一篇文章,我会详细
说明如何加载和获取管理系统里面的APP相关数据。
原文链接:http://www.cnblogs.com/mythou/p/3157452.html