Android Launcher分析和修改3——Launcher启动和初始化

来源:互联网 发布:淘宝卖家怎么导出订单 编辑:程序博客网 时间:2024/05/16 23:52

转载自:http://bbs.9ria.com/thread-224974-1-1.html

前面两篇文章都是写有关Launcher配置文件的修改,代码方面涉及不多,今天开始进入Launcher代码分析。

  我们开机启动Launcher,Launcher是由Activity Manager启动的,而Activity Manager是由system server启动。

  1、Launcher进程启动过程

  可以由下面图看到Launcher进程是如何被创建启动:

  

26203832-0a4cd35dbdad41a9a0a6c9f369038ca5.jpg




  Activity Manager通过发送Intend来启动Launcher。
  
  1.   Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);intent.setComponent(mTopComponent);
  2.   if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
  3.   intent.addCategory(Intent.CATEGORY_HOME);
  4.   }startActivityLocked(null, intent, null, null, 0, aInfo,
  5.   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]

  1.     android:name="com.android.launcher2.LauncherApplication"    android:label="@string/application_name"
  2.   android:icon="@drawable/ic_launcher_home"
  3.   android:hardwareAccelerated="@bool/config_hardwareAccelerated"
  4.   android:largeHeap="@bool/config_largeHeap"
  5.   android:configChanges="locale">
复制代码

  Android四大组件的声明都需要放到application标签里面,默认使用的是系统的Application类,如果你在项目

  里面重载了它。就需要在标签,name属性下写上你的新的Application类名。Launcher里面就是继承了Application

  为LauncherApplication。应用启动的时候首先会加载Application。

  我们可以看到Launcher主类Launcher.java的onCreate函数里面,第一个就是获取Application的实例。

  1.   LauncherApplication app = ((LauncherApplication)getApplication());
复制代码

  接下来我们看看LauncherApplication里面初始化,LauncherApplication大部分工作就是在初始化完成,剩下都是

  一些返回接口。
  1.   @Override
  2.   public void onCreate() {
  3.   super.onCreate();
复制代码

  //获取屏幕大小,主要用来区分手机还是平板

  1.   final int screenSize = getResources().getConfiguration().screenLayout 
  2. &
  3.   Configuration.SCREENLAYOUT_SIZE_MASK;
  4.   sIsScreenLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE ||
  5.   screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE; //屏幕密度
  6.   sScreenDensity = getResources().getDisplayMetrics().density;
  7.   //IconCahe里面保存了界面所有应用图标的绘画需要的数据,这个到时候具体分析再说。 //加入这东西的主要原因是为了提高绘画界面的效率
  8.   mIconCache = new IconCache(this);
  9.   //数据库加载类,LauncherModel是Launcher里面非常重要的一个类,相当于MVC模式里面的     
  10. //Model功能,管理数据和初始化数据
  11.   mModel = new LauncherModel(this, mIconCache);
  12.   //下面注册了一些监听器,主要包含APK文件更新删除等数据变化的时候接收的通知 
  13.   //接收通知后,主要是用来更新Launcher里面的数据库。因为桌面应用图标数据,只会加载一次
  14.   IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
  15.   filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
  16.   filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
  17.   filter.addDataScheme("package");
  18.   registerReceiver(mModel, filter);
  19.   filter = new IntentFilter();
  20.   filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
  21.   filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
  22.   filter.addAction(Intent.ACTION_LOCALE_CHANGED);
  23.   filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
  24.   registerReceiver(mModel, filter);
  25.   filter = new IntentFilter();
  26.   filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
  27.   registerReceiver(mModel, filter);
  28.   filter = new IntentFilter();
  29.   filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
  30.   registerReceiver(mModel, filter);
  31.   //contentresolver则是用于管理所有程序的contentprovider实例
  32.   ContentResolver resolver = getContentResolver();
  33.   //注册内容观察者,监听application数据库变化,回调
  34.   resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, 
  35. true, mFavoritesObserver);
  36.   }
复制代码

  上面是LauncherApplication最主要的工作,初始化整个Launcher的一些关键类,和注册一些监听器。主要都是用
  来监听应用的安装更新删除等导致Launcher数据库变化的操作。Launcher数据都是使用contentprovider来提供数据。

  其中注册的监听接口是

  1.   private final ContentObserver mFavoritesObserver = new ContentObserver(new 
  2. Handler())
  3.   {
  4.   @Override
  5.   public void onChange(boolean selfChange)
  6.   {       //重新加载界面数据
  7.   mModel.startLoader(LauncherApplication.this, false);
  8.   }
  9.   };
复制代码

  LauncherSettings.Favorites.CONTENT_URI里面数据发生变化的时候,都会调用mModel.startLoader()接口,重新加载Launcher的数据。startLoader的具体操作,我后面分析LauncherModel类的时候会分析。这一块涉及Launcher所有数据加载。剩下的接都是返回初始化时候创建的对象或者获取屏幕密度、获取是否大屏幕。后面很多处理都需要判断是否是大屏幕,4.0以后手机平板都共用一套系统,导致多了很多处理。

  3、Launcher.java初始化

  Launcher.java是Launcher里面最主要的类,是一个Activity。启动的第一个组件。既然是Activity,我们要分析它
  初始化,毫无疑问,需要找到onCreate()里面分析。把主要一些分析用注释方式写在代码里面,这样比较方便阅读。

  1.   @Override
  2.   protected void onCreate(Bundle savedInstanceState)   {
  3.   super.onCreate(savedInstanceState);
  4.   //获取Application 实例
  5.   LauncherApplication app = ((LauncherApplication)getApplication());     
  6. //LauncherModel类里面获取Launcher的对象引用
  7.   mModel = app.setLauncher(this); 
  8. //获取IconCache,IconCache在Application里面初始化
  9.   mIconCache = app.getIconCache();
  10.   mDragController = new DragController(this);
  11.   mInflater = getLayoutInflater();
  12.   mAppWidgetManager = AppWidgetManager.getInstance(this);
  13.   //监听widget改变,以后在Model里面回调处理的结果
  14.   mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
  15.   mAppWidgetHost.startListening();
  16.   //这个是设置Launcher的跟踪调试文件,下面很多信息会写到这个文件里面。
  17.   if (PROFILE_STARTUP)      {
  18.   android.os.Debug.startMethodTracing(
  19.   Environment.getExternalStorageDirectory() + "/launcher");
  20.   }
  21.   //读取本地配置,保存更新配置,清空IconCache
  22.   checkForLocaleChange();
  23.   setContentView(R.layout.launcher);
  24.   //对所有的UI控件进行加载和配置
  25.   setupViews();
  26.   //显示操作提示,第一次启动的时候才会显示
  27.   showFirstRunWorkspaceCling();
  28.   //注册监控Launcher数据库变化
  29.   registerContentObservers();
  30.   //锁住APP,初始化不能操作。
  31.   lockAllApps();
  32.   mSavedState = savedInstanceState;
  33.   restoreState(mSavedState);
  34.   // Update customization drawer _after_ restoring the states
  35.   if (mAppsCustomizeContent != null)      {
  36.   mAppsCustomizeContent.onPackagesUpdated();
  37.   }
  38.   if (PROFILE_STARTUP)      {
  39.   android.os.Debug.stopMethodTracing();
  40.   }
  41.   //加载启动数据,所有界面数据(快捷方式、folder、widget、allApp)等在loader里面加载,这部分后面我会详细分析。
  42.   if (!mRestoring) {
  43.   mModel.startLoader(this, true);
  44.   }
  45.   if (!mModel.isAllAppsLoaded())      {
  46.   ViewGroup appsCustomizeContentParent = (ViewGroup) 
  47. mAppsCustomizeContent.getParent();
  48.   mInflater.inflate(R.layout.apps_customize_progressbar, 
  49. appsCustomizeContentParent);
  50.   }
  51.   // For handling default keys
  52.   mDefaultKeySsb = new SpannableStringBuilder();
  53.   Selection.setSelection(mDefaultKeySsb, 0);
  54.   IntentFilter filter = new 
  55. IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
  56.   registerReceiver(mCloseSystemDialogsReceiver, filter);
  57.   //下面这几个就是Android原生界面上的Market、搜索、声音输入按钮的默认图标显示。
  58.   boolean searchVisible = false;
  59.   boolean voiceVisible = false;
  60.   // If we have a saved version of these external icons, we load them up 
  61. immediately
  62.   int coi = getCurrentOrientationIndexForGlobalIcons();
  63.   if (sGlobalSearchIcon[coi] == null || sVoiceSearchIcon[coi] == null ||
  64.   sAppMarketIcon[coi] == null) {
  65.   updateAppMarketIcon();
  66.   searchVisible = updateGlobalSearchIcon();
  67.   voiceVisible = updateVoiceSearchIcon(searchVisible);
  68.   }
  69.   if (sGlobalSearchIcon[coi] != null) {
  70.   updateGlobalSearchIcon(sGlobalSearchIcon[coi]);
  71.   searchVisible = true;
  72.   }
  73.   if (sVoiceSearchIcon[coi] != null)    {
  74.   updateVoiceSearchIcon(sVoiceSearchIcon[coi]);
  75.   voiceVisible = true;
  76.   }
  77.   if (sAppMarketIcon[coi] != null)     {
  78.   updateAppMarketIcon(sAppMarketIcon[coi]);
  79.   }
  80.   mSearchDropTargetBar.onSearchPackagesChanged(searchVisible, 
  81. voiceVisible);
  82.   // On large interfaces, we want the screen to auto-rotate based on the 
  83. current orientation
  84.   if (LauncherApplication.isScreenLarge() || Build.TYPE.contentEquals("eng")) 
  85.      {
  86.   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
  87.   }
  88.   Log.i(TAG,"------------------------>Launcher init over") ;
  89.   }
复制代码

  上面就是Launcher.java的初始化,大部分我都写了注释。其实这里最主要的工作是加载界面数据:

  mModel.startLoader(this, true); 这块实现是在LauncherModel里面实现的。下一篇文章,我会详细

  说明如何加载和获取管理系统里面的APP相关数据。

原文链接:http://www.cnblogs.com/mythou/p/3157452.html
0 0