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

0 0
原创粉丝点击