学习资料:
- Android开发艺术探索
- 罗升阳大神的Android应用程序的Activity启动过程简要介绍和学习计划
本篇是个挖坑之作,步子跨得太大扯着了。不知天高地厚地开始学习后,发现涉及到很多暂时无法理解的东西。遂,中道崩殂,哈哈:),估计明年这个时候才能补充了
Android——Activity学习(上)学习了Activity的生命周期,启动模式,任务栈,本篇进行学习工作过程
对于用户来说,一个APP能够感知的就是一个Activity,四大组件的其他三位,都是在后台运行的,用户是看不到的,不可感知的。根据上篇的学习,Activity有不同的启动模式,启动方式也可以分为显示Intent和隐式Intent,finish()方法可以结束一个组件的运行。
1. 工作过程 <p>
在一个现有Activity_A中,经常会使用一个Intent来开启一个Activity_B
Intent intent = new Intent(Activity_A.this,Activity_B.class);
startActivity(intent);
startActivity()方法可以作为学习的入口点
扫了一眼Activity源码的行数,加上注释7177行,相对于View的23000行来说,小巫见大巫。最近一段时间的学习,感觉最明显的变化便是看源码时的心态。然而也仅仅是心态有了点朝好的趋势发展,阅读代码的能力还是渣
1.1 startActivity() 开启Activity<p>
有两种重载重载方式,startActivity(Intent intent)内部调用了startActivity(Intent intent, @Nullable Bundle options)
@Override
public void startActivity(Intent intent, @Nullable 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()方法都会调用startActivityForResult()方法
Activity_A并不知道Activity_B的存在,但Activity_A通过使用Intent来启动Activity_B,显式是通过指定类对象,隐式则更加显得强大,通过在AndroidManifest.xml清单文件中使用的action指定的Activity_B的名字来启动。这个设计使Activity耦合性很松散,模块化程度更高,之后维护和升级也更加方便些。
1.2 startActivityForResult()带有返回结果的开启Activity <p>
方法源码:
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {
if (mParent == null) {//mParent是ActvityGroup,API13后废弃,推荐由Framgment代替
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {//当前Activity返回一个result,无论它发生了什么
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {//mParent不为null
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {兼容重载方法,以确保重载方法可以使用
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
上面的代码需要重点关注mParent==null部分内的的逻辑,mParent是一个ActivityGroup,只是在API13之后,被废弃,系统推荐另外一个坑,Frrgment来替代。
mInstrumentation是Activity类中的一个成员变量,Instrumentation可以看作是APP和系统之间的监控器,用来监控应用程序和系统间的交互
mMainThread类型是ActivityThread,这里代表的就是程序的主线程。mMainThread.getApplicationThread()获得是一个ActivityThread的内部类ApplicationThread对象。在Android应用程序中,每一个进程就用一个ActivityThread实例对象来表示
本篇博客学习挖的1号坑——
ActivityThread,暂时不理解它的工作过程
1.3 Instrumentation的execStartActivity()方法 <p>
源码:
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {...}
try {
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread,intent,intent.resolveTypeIfNeeded(who.getContentResolver()), null, 0, token, target != null ? target.mEmbeddedID : null, requestCode, false, false); //才真正开始开启Activity
checkStartActivityResult(result, intent);//检查异常
} catch (RemoteException e) {
}
return null;
}
整个方法内关键之处在于ActivityManagerNative.getDefault().startActivity(...),真正启动一个Activity便是这行代码。
ActivityManagerNative.getDefault()返回的结果是一个IActivityManager,是一个接口。ActivityManagerNative(AMN)是ActivityManagerService(AMS)的父类,AMN继承之Binder并实现了IActivityManager这个Binder接口,因此AMS也是一个Binder,它是IAcitityManager的具体实现。由于ActivityManagerNative.getDefault()结果其实是一个IActivityManager类型的Binder对象,最终的具体实现是AMS,所以Activity的启动也就转移到了AMS中的startActivity()方法。
checkStartActivityResult(result,intent)用于检查启动Activity的结果,当无法正常开启一个Activity时,就会抛出一个异常。例如,一个Activity没有在AnroidManifest.xml中注册时,便会抛出:
Unable to find explict activity class ;
have you declared this activity in your AndroidManifest.xml ?
2号大坑——Binder,任教主推荐了两篇,Android深入浅出之Binder机制和Android Bander设计与实现 - 设计篇 ,一脸懵逼,属于有生年看懂系列
接下来看AMS的startActivity()方法
1.4 AMS的startActivity()方法
源码:
卒...
感觉再看下去属于浪费时间,再储备点知识后,再来学习
2. 最后 <p>
尺度太大,学不动,先放弃,这次学习没把握好尺度
写博客以来,第一次中途放弃,实在没有啥效率
2016.10.14 16:28
共勉 :)