android笔记-02 程序启动和Launcher
来源:互联网 发布:手机淘宝收藏店铺在哪 编辑:程序博客网 时间:2024/05/21 18:48
了解Activity的生命周期很久了,最近在网上学习了一下Activity的启动过程,和程序的启动过程,想知道当手机开机以后,手机进入到主页面,点击一个程序,这个程序是怎么启动的,在程序内部,Activity又是怎么跳转的,里面的东西太多,也只能了解个大概,然后写一下笔记:在Android系统中,Launcher程序就是我们平时看到的桌面程序,它也是一个android程序,只不过这个应用程序是默认系统的第一个启动的应用程序,这里简单分析一下Launcher应用的启动流程。不同的手机厂商定制android操作系统的时候都会更改Launcher的源代码,我们这里以android23的源码为例大致的分析一下Launcher的启动流程。![这里写图片描述](http://img.blog.csdn.net/20160721150934177)这张图很熟悉了吧,这不是就是eclipse中app项目的结构吗,里面点开AndroidManifest:
<application android:name="com.android.launcher2.LauncherApplication" ... > <activity android:name="com.android.launcher2.Launcher" android:launchMode="singleTask" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:theme="@style/Theme" android:windowSoftInputMode="adjustPan" android:screenOrientation="nosensor"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.MONKEY"/> </intent-filter> </activity>
此AndroidManifest正式android手机开机以后的启动程序配置文件,从中我们可以知道启动过程需要先后初始化LauncherApplication和Launcher的对象。更加简洁的说,启动过程可以分成两步,第一步在LauncherApplication.onCreate()方法中,第二部在Launcher.onCreate()方法中。先来看LauncherApplication的代码:
public class LauncherApplication extends Application {public void onCreate() { super.onCreate(); // 在创建icon cache之前,我们需要判断屏幕的大小和屏幕的像素密度,以便创建合适大小的icon 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; mIconCache = new IconCache(this); mModel = new LauncherModel(this, mIconCache); // 注册广播接收器 IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); ...... registerReceiver(mModel, filter); //注册ContentObserver,监听LauncherSettings.Favorites.CONTENT_URI数据的变化 ContentResolver resolver = getContentResolver(); resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true, mFavoritesObserver); } }
LauncherApplication是 Application的子类,是整个程序的入口,所以里面放置一些全局信息的初始化和保存工作就在这里执行,包括屏幕大小,像素密度等信息的获取,已经广播的注册, LauncherApplication工作结束之后,下面就开始初始化Launcher了,
public final class Launcher extends Activity implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,View.OnTouchListener { protected void onCreate(Bundle savedInstanceState) { ... mModel = app.setLauncher(this); mIconCache = app.getIconCache(); ... mAppWidgetManager = AppWidgetManager.getInstance(this); mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID); mAppWidgetHost.startListening(); ... //检查本地保存的配置是否需要更新 checkForLocaleChange(); setContentView(R.layout.launcher); //对UI控件进行初始化和配置 setupViews(); //向用户展示指导的页面 showFirstRunWorkspaceCling(); registerContentObservers(); ... if (!mRestoring) { //为Launcher加载数据 mModel.startLoader(this, true); } ... } }
Launcher是一个Activity,自然他就会有Activity的生命周期,基本初始化信息也是在onCreate中完成的。
可以将Launcher.onCreate()所执行的操作大概分为七步:
1、LauncherAppliaction.setLauncher()。
2、AppWidgetHost.startListening(),对widget事件进行监听
3、checkForLocaleChange(),检查更新本地保存的配置文件
4、setupViews(),配置UI控件
5、showFirstRunWorkspaceCling(),第一次启动时显示的指导画面
6、registerContentObservers(),设置内容监听器
7、LauncherModel.startLoader(),为Launcher加载Workspace和AllApps中的内容
这些紧做了解。
在Launcher中,用一个重要方法:
public void onClick(View v) { Object tag = v.getTag(); if (tag instanceof ShortcutInfo) { // Open shortcut final Intent intent = ((ShortcutInfo) tag).intent; int[] pos = new int[2]; v.getLocationOnScreen(pos); intent.setSourceBounds(new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight())); startActivitySafely(intent, tag); } else if (tag instanceof FolderInfo) { ...... } else if (v == mHandleView) { ...... } } void startActivitySafely(Intent intent, Object tag) { //启动Activity创建一个新的Activity栈 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { startActivity(intent); } catch (ActivityNotFoundException e) { ...... } catch (SecurityException e) { ...... } } ......
在Launcher的onClick方法中,此方法是用户点击桌面app程序图标进行的业务逻辑,在onclick的里面调用了startActivitySafely(intent, tag),启动应用程序的Activity,这样就完成了一次app程序的启动,下面来分析下Activity中startActivity的方法原理,先看Activity的源码:
public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2 { @Override public void startActivity(Intent intent) { startActivity(intent, null); } @Override public void startActivity(Intent intent, Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); } }}
首先直接调用startActivity时,如果没有传入Bundle参数,会调用startActivityForResult(intent, -1);这里- 1 表示 target Activity finish的时候不通知original Activity ,Bundle指要传递的信息,
public void startActivityForResult(Intent intent, int requestCode, Bundle options) { //一般的Activity其mParent为null,mParent常用在ActivityGroup中,ActivityGroup已废弃 if (mParent == null) { //这里会启动新的Activity,核心功能都在mMainThread.getApplicationThread()中完成 Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { //发送结果,即onActivityResult会被调用 mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } final View decor = mWindow != null ? mWindow.peekDecorView() : null; if (decor != null) { decor.cancelPendingInputEvents(); } // TODO Consider clearing/flushing other event sources and events for child windows. } else { //在ActivityGroup内部的Activity调用startActivity的时候会走到这里,内部处理逻辑和上面是类似的 if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } } }
Instrumentation是仪器化,使用仪器,一般在开发Android程序的时候,需要写一个manifest文件, 这样,在启动程序的时候就会先启动一个Application,然后在此Application运行过程中根据情况加载相应的Activity,而Activity是需要一个界面的。但是Instrumentation并不是这样的。你可以将Instrumentation理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。任何想成为Instrumentation的类必须继承android.app.Instrumentation。
这里的mMainThread也是Activity类的成员变量,它的类型是ActivityThread,它代表的是应用程序的主线程,这里通过mMainThread.getApplicationThread获得它里面的ApplicationThread成员变量,它是一个Binder对象,后面我们会看到,ActivityManagerService会使用它来和ActivityThread来进行进程间通信。这里我们需注意的是,这里的mMainThread代表的是Launcher应用程序运行的进程。这里的mToken也是Activity类的成员变量,它是一个Binder对象的远程接口。
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { //核心功能在这个whoThread中完成,其内部scheduleLaunchActivity方法用于完成activity的打开 IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { //先查找一遍看是否存在这个activity final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); if (am.match(who, null, intent)) { //如果找到了就跳出循环 am.mHits++; //如果目标activity无法打开,直接return if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; } break; } } } } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(); //这里才是真正打开activity的地方,核心功能在whoThread中完成。 int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, null, options); //这个方法是专门抛异常的,它会对结果进行检查,如果无法打开activity, //则抛出诸如ActivityNotFoundException类似的各种异常 checkStartActivityResult(result, intent); } catch (RemoteException e) { } return null; }
http://blog.csdn.net/abcdef314159/article/details/50962335
- android笔记-02 程序启动和Launcher
- Android笔记 - Android启动之Launcher启动
- android 开机启动桌面程序,launcher模式
- 《老罗的Android之旅》阅读笔记——Launcher和Zygote的启动过程
- Android 启动Launcher
- Android启动Launcher过程
- 【Android】launcher启动参数
- android 启动launcher流程
- 【Android】程序自启动,跳过主桌面(Launcher)
- Android launcher 开发笔记(三) 启动过程分析
- Android Launcher分析和修改3——Launcher启动和初始化
- Android Launcher分析和修改3——Launcher启动和初始化
- Android Launcher分析和修改3——Launcher启动和初始化
- Android Launcher分析和修改3——Launcher启动和初始化
- Android Launcher分析和修改3——Launcher启动和初始化
- Android Launcher分析和修改3——Launcher启动和初始化
- Android Launcher分析和修改3——Launcher启动和初始化
- Android Launcher分析和修改3——Launcher启动和初始化
- (转)Android之你不可不知道的小知识
- 10 JAVA 正则表达式
- 关于CSS需要知道的10件事
- 顺序查找
- Linux发展编年表
- android笔记-02 程序启动和Launcher
- 通过局域网安装centos6.4
- leetcode.374. Guess Number Higher or Lower
- 八 shader中数据传递
- cloudera-manager 5.4.10的安装
- 背景色#888888
- ACM暑期集训——专题一[优先队列]
- java基础:Map三两事
- js实现动态时间显示