接篇一进行扩展
1,MVC/MVP/MVVM区别
1)MVC
记得早年,画的MVC表是这样的
特么的Thunderbird的表格难用死了。。。。
当年面试是多么的简单啊。。。。
2)MVP
MVP与MVC对比,最大区别就是 使用P拆分了VC
View不再直接与Model交互,而是与Presenter相互持有接口,进行接口相互调用。
3)MVVM
示例
但是Model与View之间的通信是单向传输,View发起请求,调用P,与Model通信,反之亦然,这么做比较繁琐;
MVVM,通过 ViewModel隔离了Model与View;
绑定之后,对ViewModel的任何变更,都会直接展示在View上,这样就不用showData()了。
天下文章一大抄
有图,Blogspot又得更新不成功。。。。
2,View绘制流程
这里引出自定义View
3,常用算法
又是一个大坑
4,常用数据结构
数据结构定义:相互之间存在一种或多种特定关系的数据元素的集合;
1)数组Array
内存中连续存储多个元素的结构;
2)栈Stack
一种特殊的线性表,仅能在栈顶操作。
先进后出,先入栈后出栈。
集装箱。
3)队列Queue
也是一种线性表,先进先出,先入队先出队。
4)链表Linked List
非连续,非顺序的存储结构;
每个元素至少两个节点,一个存元素内容,一个存下一个节点地址;
5)树Tree
由n(n>=1)个有限节点组成一个具有层次关系的集合。
6)散列表Hash table
键值对
7)堆Heap
堆有以下特性:
8)图Graph
由顶点的有穷非空集合和顶点之间边的集合组成, 通常表示为: G(V,E), 其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
5,常用设计模式
1)设计模式六大原则
六大基本原则都是基于抽象(抽象类和接口)
总原则:开闭原则
OCP:Open Close Principle
对扩展开放,对修改关闭;
①单一职责原则
SRP:Single Responsibility Principle
一个类中应该是一组相关性很高的函数或函数封装;
②里氏替换原则
LSP:Liskov Substitution Principle
任何一个父类可以出现的地方,子类一定可以出现,并且不会产生错误;
③依赖倒置原则
DIP:Dependence inversion Principle
高层次模块不依赖于低层次模块实现细节,即依赖于抽象,不依赖于实现;
④接口隔离原则
ISP:Interface Segregation Principle
客户端不应依赖它不需要的接口,类的依赖应建立在最小接口上;
⑤迪米特法则/最少知识原则
LKP:Law of Demeter(Least Knowledge Principle)
一个对象应该对其他对象有最小的了解;
⑥合成复用原则
CARP:Composite/Aggregate Reuse Principle
在一个新的对象里面使用一些已有的对象,使其成为新对象的一部分。
新对象通过委派达到复用已有功能的效果。
2)分类
①创建型模式
②结构型模式
③行为型模式
④扩展模式
6,Activity启动流程
两种方式,一种是从Launcher2启动,一种是应用内startActivity(Intent)方式启动。
第一种,终归流向第二种。。。。
1)从startActivity(Intent)开始
2)startActivityForResult中调用Instrumentation执行启动
作为一个编辑器,为什么不能换行,回车键被开发团队吃了吗,屮。。。。
3)Instrumentation里调用了IActivityManager
但是 google有啊。。。。
Stub看起来是进行了IPC通信,然后到了AMS。。。。
幸好ActivityManagerService是有的。。。。
ActivityManagerService,一个从19行开始导包,到515行才结束导包的类。。。。
4)AMS启动activity
AMS也有startActivity(...)
5)ActivityStarter启动Activity
ActivityStarter的初始化
然后去执行
然后
其中,加锁的是那个变量是
然后,又一个巨长的方法,看起来是对参数的救赎
6)ActivityStackSupervisor与ActivityStack
7)ActivityManagerService创建进程
在启动前,还做了异步跟同步的判断,异步加锁synchronized (ActivityManagerService.this),最后调用的是同一个启动进程方法
8)进程存在时直接创建Activity
然后,回到17,调用realStartActivityLocked方法,原来也变了呀。。。。
9)LaunchActivityItem到ActivityThread
7,DNS劫持
HttpDnsService;
8,插件化动态加载方案
从页面A,调到页面B,B承载第三方入口;
B,壳,或ProxyActivity,对他的生命周期注入三方实现;
IPlugin,提供标准,此标准根据页面B所需定制,第三方页面C实现此标准,这样在B页面进行调用时,实际调用的是C,实现了Proxy。
有必要填一下坑啊。。。。
2019年05月15日22:57:38
1,MVC/MVP/MVVM区别
1)MVC
记得早年,画的MVC表是这样的
L\L |
Servlet |
Android |
Model |
Domain | Domain |
View |
JSP | Xml |
Controller |
SERVLET | Activity |
当年面试是多么的简单啊。。。。
2)MVP
MVP与MVC对比,最大区别就是 使用P拆分了VC
View不再直接与Model交互,而是与Presenter相互持有接口,进行接口相互调用。
3)MVVM
示例
MVP通过Presenter隔离了Model与View;package dc.test.lv;
但是Model与View之间的通信是单向传输,View发起请求,调用P,与Model通信,反之亦然,这么做比较繁琐;
MVVM,通过 ViewModel隔离了Model与View;
绑定之后,对ViewModel的任何变更,都会直接展示在View上,这样就不用showData()了。
天下文章一大抄
有图,Blogspot又得更新不成功。。。。
2,View绘制流程
这里引出自定义View
package dc.test.surname.shi;绘制流程就是个大坑。。。。
3,常用算法
又是一个大坑
package dc.test.surname.zhang;
4,常用数据结构
数据结构定义:相互之间存在一种或多种特定关系的数据元素的集合;
1)数组Array
内存中连续存储多个元素的结构;
2)栈Stack
一种特殊的线性表,仅能在栈顶操作。
先进后出,先入栈后出栈。
集装箱。
3)队列Queue
也是一种线性表,先进先出,先入队先出队。
4)链表Linked List
非连续,非顺序的存储结构;
每个元素至少两个节点,一个存元素内容,一个存下一个节点地址;
5)树Tree
由n(n>=1)个有限节点组成一个具有层次关系的集合。
6)散列表Hash table
键值对
7)堆Heap
堆有以下特性:
- 堆中某个节点的值总是不大于/不小于其父节点的值;
- 堆总是一颗完全二叉树;
8)图Graph
由顶点的有穷非空集合和顶点之间边的集合组成, 通常表示为: G(V,E), 其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
5,常用设计模式
1)设计模式六大原则
六大基本原则都是基于抽象(抽象类和接口)
总原则:开闭原则
OCP:Open Close Principle
对扩展开放,对修改关闭;
①单一职责原则
SRP:Single Responsibility Principle
一个类中应该是一组相关性很高的函数或函数封装;
②里氏替换原则
LSP:Liskov Substitution Principle
任何一个父类可以出现的地方,子类一定可以出现,并且不会产生错误;
③依赖倒置原则
DIP:Dependence inversion Principle
高层次模块不依赖于低层次模块实现细节,即依赖于抽象,不依赖于实现;
④接口隔离原则
ISP:Interface Segregation Principle
客户端不应依赖它不需要的接口,类的依赖应建立在最小接口上;
⑤迪米特法则/最少知识原则
LKP:Law of Demeter(Least Knowledge Principle)
一个对象应该对其他对象有最小的了解;
⑥合成复用原则
CARP:Composite/Aggregate Reuse Principle
在一个新的对象里面使用一些已有的对象,使其成为新对象的一部分。
新对象通过委派达到复用已有功能的效果。
2)分类
①创建型模式
- 单例模式;
- 工厂方法模式;
- 抽象工厂模式;
- 建造者模式;
- 原型模式;
②结构型模式
- 适配器模式;
- 装饰者模式;
- 代理模式;
- 门面/外观模式;
- 桥梁模式;
- 组合模式;
- 享元模式;
③行为型模式
- 策略模式;
- 模板方法模式;
- 观察者模式;
- 迭代器模式;
- 责任链模式;
- 命令模式;
- 备忘录模式;
- 状态模式;
- 访问者模式;
- 中介者模式;
- 解释器模式;
④扩展模式
- 规则模式;
- 对象池模式;
- 雇工模式;
- 黑板模式;
- 空对象模式;
6,Activity启动流程
两种方式,一种是从Launcher2启动,一种是应用内startActivity(Intent)方式启动。
第一种,终归流向第二种。。。。
1)从startActivity(Intent)开始
@Override public void startActivity(Intent intent) { this.startActivity(intent, null); }
调用了 startActivityForResult(intent, -1);
2)startActivityForResult中调用Instrumentation执行启动
特么的Mac上的软件一个比一个难用。。。。public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { ... Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); //3,execStartActivity(...); ... }
作为一个编辑器,为什么不能换行,回车键被开发团队吃了吗,屮。。。。
3)Instrumentation里调用了IActivityManager
其中这个getService()是个IBinder的单例public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { 。。。 if (mActivityMonitors != null) { synchronized (mSync) { } } try { 。。。 int result = ActivityManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);//5,IActivityManagerSingleton启动 。。。 } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }
到了这里,SDK AS里就找不到IActivityManager这个类了。。。。public static IActivityManager getService() { return IActivityManagerSingleton.get(); } private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() { @Override protected IActivityManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } };
但是 google有啊。。。。
Stub看起来是进行了IPC通信,然后到了AMS。。。。
幸好ActivityManagerService是有的。。。。
ActivityManagerService,一个从19行开始导包,到515行才结束导包的类。。。。
从这里开始,就跟网上搜到的80%的教程不一样了。。。。public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {}
4)AMS启动activity
AMS也有startActivity(...)
然后startActivity调用startActivityAsUser//6,AMS启动Activity @Override public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId()); }
这是个建造者模式吧。。。。public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) { ... // TODO: Switch to user app stacks here. return mActivityStartController.obtainStarter(intent, "startActivityAsUser") .setCaller(caller) .setCallingPackage(callingPackage) .setResolvedType(resolvedType) .setResultTo(resultTo) .setResultWho(resultWho) .setRequestCode(requestCode) .setStartFlags(startFlags) .setProfilerInfo(profilerInfo) .setActivityOptions(bOptions) .setMayWait(userId) .execute();//8,新晋控制中心吗 }
5)ActivityStarter启动Activity
ActivityStarter的初始化
神翻译/** 9,看起来是工厂里绑了一个ActivityStarter出来 * @return A starter to configure and execute starting an activity. It is valid until after 配置和执行启动活动的启动器。 它有效期至之后 * {@link ActivityStarter#execute} is invoked. At that point, the starter should be {@link ActivityStarter #cute}被调用。 那时,首发应该是 * considered invalid and no longer modified or used. 被视为无效,不再修改或使用。 */ ActivityStarter obtainStarter(Intent intent, String reason) { return mFactory.obtain().setIntent(intent).setReason(reason); }
然后去执行
前面建造者模式的时候,调用了setMayWait(userId),所以应该走第一个。。。。/** 10,又是执行启动 * Starts an activity based on the request parameters provided earlier.根据前面提供的请求参数启动Activity。 * @return The starter result. */ int execute() { try { // TODO(b/64750076): Look into passing request directly to these methods to allow查看直接向这些方法传递请求以允许 // for transactional diffs and preprocessing.用于事务差异和预处理。 if (mRequest.mayWait) {//ActivityStarter#setMayWait(int)表示等待启动请求的结果 return startActivityMayWait(mRequest.caller, mRequest.callingUid, mRequest.callingPackage, mRequest.intent, mRequest.resolvedType, mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo, mRequest.resultWho, mRequest.requestCode, mRequest.startFlags, mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig, mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId, mRequest.inTask, mRequest.reason, mRequest.allowPendingRemoteAnimationRegistryLookup); } else { return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent, mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo, mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo, mRequest.resultWho, mRequest.requestCode, mRequest.callingPid, mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.componentSpecified, mRequest.outActivity, mRequest.inTask, mRequest.reason, mRequest.allowPendingRemoteAnimationRegistryLookup); } } finally { onExecutionComplete(); } }
然后
这个类是真长啊。。。。//11,要等待返回值回来 private int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, WaitResult outResult, Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity, int userId, TaskRecord inTask, String reason, boolean allowPendingRemoteAnimationRegistryLookup) { 。。。 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0 /* matchFlags */, computeResolveFilterUid( callingUid, realCallingUid, mRequest.filterCallingUid)); if (rInfo == null) { 。。。 } // Collect information about the target of the Intent. ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo); synchronized (mService) { final ActivityStack stack = mSupervisor.mFocusedStack; 。。。 final ActivityRecord[] outRecord = new ActivityRecord[1]; int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason, allowPendingRemoteAnimationRegistryLookup); Binder.restoreCallingIdentity(origId); 。。。 if (outResult != null) { outResult.result = res; final ActivityRecord r = outRecord[0]; switch(res) { case START_SUCCESS: 。。。 case START_DELIVERED_TO_TOP: 。。。 case START_TASK_TO_FRONT: 。。。 } } mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]); return res;} //锁到这里才结束 }
其中,加锁的是那个变量是
然后流向startActivity方法,又是一大串巨长的方法。。。。private final ActivityManagerService mService;
//12, ActivityStarter启动activity private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, TaskRecord inTask, String reason, boolean allowPendingRemoteAnimationRegistryLookup) { if (TextUtils.isEmpty(reason)) { throw new IllegalArgumentException("Need to specify a reason."); } 。。。 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord, inTask, allowPendingRemoteAnimationRegistryLookup); 。。。 return getExternalResult(mLastStartActivityResult); } static int getExternalResult(int result) { // Aborted results are treated as successes externally, but we must track them internally. return result != START_ABORTED ? result : START_SUCCESS; }
然后,又一个巨长的方法,看起来是对参数的救赎
然后,一个通过try catch控制流程的经典案例。。。。//13, ActivityStarter 启动Activity 长长长长长 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) { int err = ActivityManager.START_SUCCESS; // Pull the optional Ephemeral Installer-only bundle out of the options early. final Bundle verificationBundle = options != null ? options.popAppVerificationBundle() : null; ProcessRecord callerApp = null; 。。。 final int launchFlags = intent.getFlags(); 。。。 mController.doPendingActivityLaunches(false); return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask, outActivity); }
加锁的方法由WindowManagerService倾情提供//14,ActivityStarter 启动Activity private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { int result = START_CANCELED; try { mService.mWindowManager.deferSurfaceLayout(); //这是个加锁的方法 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, outActivity); } finally { // If we are not able to proceed, disassociate the activity from the task. Leaving an // activity in an incomplete state can lead to issues, such as performing operations // without a window container. final ActivityStack stack = mStartActivity.getStack(); if (!ActivityManager.isStartResultSuccessful(result) && stack != null) { stack.finishActivityLocked(mStartActivity, RESULT_CANCELED, null /* intentResultData */, "startActivity", true /* oomAdj */); } mService.mWindowManager.continueSurfaceLayout(); } postStartActivityProcessing(r, result, mTargetStack); return result; }
假设上面这个加锁的方法执行成功了,那么终于能看到曙光/** * Starts deferring layout passes. Useful when doing multiple changes but to optimize 开始推迟布局传递。 在进行多项更改但优化性能时很有用,只需要完成一次布局。 * performance, only one layout pass should be done. This can be called multiple times, and这可以多次调用,一旦最后一个调用者调用{@link #continueSurfaceLayout},布局就会恢复 * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout} */ public void deferSurfaceLayout() { synchronized (mWindowMap) { mWindowPlacerLocked.deferLayout(); } }
其中mSupervisor变量为// Note: This method should only be called from {@link startActivity}. private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { 。。。 if (reusedActivity != null) { 。。。 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity); 。。。 } if (mStartActivity.packageName == null) { final ActivityStack sourceStack = mStartActivity.resultTo != null ? mStartActivity.resultTo.getStack() : null; if (sourceStack != null) { sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo, mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null /* data */); } ActivityOptions.abort(mOptions); return START_CLASS_NOT_FOUND; } // If the activity being launched is the same as the one currently at the top, then // we need to check if it should only be launched once. final ActivityStack topStack = mSupervisor.mFocusedStack; final ActivityRecord topFocused = topStack.getTopActivity(); final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); final boolean dontStart = top != null && mStartActivity.resultTo == null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId && top.app != null && top.app.thread != null && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)); if (dontStart) { // For paranoia, make sure we have correctly resumed the top activity. topStack.mLastPausedActivity = null; if (mDoResume) { mSupervisor.resumeFocusedStackTopActivityLocked(); } ActivityOptions.abort(mOptions); if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and the client said not to do // anything if that is the case, so this is it! return START_RETURN_INTENT_TO_CALLER; } deliverNewIntent(top); // Don't use mStartActivity.task to show the toast. We're not starting a new activity // but reusing 'top'. Fields in mStartActivity may not be fully initialized. mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode, preferredLaunchDisplayId, topStack); return START_DELIVERED_TO_TOP; } boolean newTask = false; final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null) ? mSourceRecord.getTask() : null; // Should this be considered a new task? int result = START_SUCCESS; if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { newTask = true; result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack); } else if (mSourceRecord != null) { result = setTaskFromSourceRecord(); } else if (mInTask != null) { result = setTaskFromInTask(); } else { // This not being started from an existing activity, and not part of a new task... // just put it in the top task, though these days this case should never happen. setTaskToCurrentTopOrCreateNewTask(); } if (result != START_SUCCESS) { return result; } 。。。 ActivityStack.logStartActivity( EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask()); 。。。 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity); mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition, mOptions); if (mDoResume) { final ActivityRecord topTaskActivity = mStartActivity.getTask().topRunningActivityLocked(); if (!mTargetStack.isFocusable() || (topTaskActivity != null && topTaskActivity.mTaskOverlay && mStartActivity != topTaskActivity)) { // If the activity is not focusable, we can't resume it, but still would like to // make sure it becomes visible as it starts (this will also trigger entry // animation). An example of this are PIP activities. // Also, we don't want to resume activities in a task that currently has an overlay // as the starting activity just needs to be in the visible paused state until the // over is removed. mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); // Go ahead and tell window manager to execute app transition for this activity // since the app transition will not be triggered through the resume channel. mService.mWindowManager.executeAppTransition(); } else { // If the target stack was not previously focusable (previous top running activity // on that stack was not visible) then any prior calls to move the stack to the // will not update the focused stack. If starting the new activity now allows the // task stack to be focusable, then ensure that we now update the focused stack // accordingly. if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityUnchecked"); } mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); } } else if (mStartActivity != null) { mSupervisor.mRecentTasks.add(mStartActivity.getTask()); } mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode, preferredLaunchDisplayId, mTargetStack); return START_SUCCESS; //终于,返回了SUSS }
private final ActivityStackSupervisor mSupervisor;
6)ActivityStackSupervisor与ActivityStack
最后,又回到了ActivityStackSupervisor//15,与ActivityStack深度交流 boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (!readyToResume()) { return false; } if (targetStack != null && isFocusedStack(targetStack)) { return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } final ActivityRecord r = mFocusedStack.topRunningActivityLocked(); if (r == null || !r.isState(RESUMED)) { mFocusedStack.resumeTopActivityUncheckedLocked(null, null); } else if (r.isState(RESUMED)) { // Kick off any lingering app transitions form the MoveTaskToFront operation. mFocusedStack.executeAppTransition(targetOptions); } return false; }
//17, 根据app是否启动来启动Activity或创建进程 void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // Is this activity's application already running? ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); getLaunchTimeTracker().setLaunchTime(r); if (app != null && app.thread != null) { try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { // Don't add this if it is a platform component that is marked // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode, mService.mProcessStats); } realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); } // If a dead object exception was thrown -- fall through to // restart the application. } mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }
7)ActivityManagerService创建进程
然后,又经过了一堆的准备//18,启动进程 @GuardedBy("this") final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, boolean keepIfLarge) { return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType, hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */); }
在启动前,还做了异步跟同步的判断,异步加锁synchronized (ActivityManagerService.this),最后调用的是同一个启动进程方法
后来发生了什么。。。。//23,终于启动进程了。。。。 private ProcessStartResult startProcess(String hostingType, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) { try { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + app.processName); checkTime(startTime, "startProcess: asking zygote to start proc"); final ProcessStartResult startResult; if (hostingType.equals("webview_service")) { startResult = startWebView(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); } else { startResult = Process.start(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); } checkTime(startTime, "startProcess: returned from zygote!"); return startResult; } finally { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } }
8)进程存在时直接创建Activity
然后,回到17,调用realStartActivityLocked方法,原来也变了呀。。。。
看来realStartActivity变到了LaunchActivityItem里//24,进程存在,启动activity real,前面都是假的,呵 final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { 。。。 try { r.startFreezingScreenLocked(app, 0);//冻结屏幕 // schedule launch ticks to collect information about slow apps. r.startLaunchTickingLocked(); r.setProcess(app); if (getKeyguardController().isKeyguardLocked()) { r.notifyUnknownVisibilityLaunched(); } // Have the window manager re-evaluate the orientation of the screen based on the new让窗口管理器根据新窗口重新评估屏幕的方向 // activity order. Note that as a result of this, it can call back into the activity // manager with a new orientation. We don't care about that, because the activity is // not currently running so we are just restarting it anyway. if (checkConfig) {//根据新的 Activity 顺序重新评估屏幕的方向 // Deferring resume here because we're going to launch new activity shortly. // We don't want to perform a redundant launch of the same record while ensuring // configurations and trying to resume top activity of focused stack. ensureVisibilityAndConfig(r, r.getDisplayId(), false /* markFrozenIfConfigChanged */, true /* deferResume */); } if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */, true /* isTop */)) { // We only set the visibility to true if the activity is allowed to be visible // based on // keyguard state. This avoids setting this into motion in window manager that is // later cancelled due to later calls to ensure visible activities that set // visibility back to false. r.setVisibility(true); } 。。。 if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r); int idx = app.activities.indexOf(r); if (idx < 0) { app.activities.add(r);//将 Activity 添加到应用进程中 } mService.updateLruProcessLocked(app, true, null); mService.updateOomAdjLocked(); 。。。 try { if (app.thread == null) { throw new RemoteException(); } List<ResultInfo> results = null; List<ReferrerIntent> newIntents = null; if (andResume) { // We don't need to deliver new intents and/or set results if activity is going // to pause immediately after launch. results = r.results; newIntents = r.newIntents; } if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Launching: " + r + " icicle=" + r.icicle + " with results=" + results + " newIntents=" + newIntents + " andResume=" + andResume); 。。。 // Create activity launch transaction.搞了个跳转客户端吗 final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread, r.appToken); clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, mService.isNextTransitionForward(), profilerInfo)); // Set desired final state.这个是生命周期吧 final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward()); } else { lifecycleItem = PauseActivityItem.obtain(); } clientTransaction.setLifecycleStateRequest(lifecycleItem); // Schedule transaction. mService.getLifecycleManager().scheduleTransaction(clientTransaction); 。。。 } catch (RemoteException e) { 。。。 } } finally { //这个是外圈的 endDeferResume(); } 。。。 return true; }
9)LaunchActivityItem到ActivityThread
真的会到吗…(⊙_⊙;)…public class LaunchActivityItem extends ClientTransactionItem { 。。。 @Override public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState, mPendingResults, mPendingNewIntents, mIsForward, mProfilerInfo, client); client.handleLaunchActivity(r, pendingActions, null /* customIntent */); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } // ObjectPoolItem implementation private LaunchActivityItem() {} /** Obtain an instance initialized with provided params. */ public static LaunchActivityItem obtain(Intent intent, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo) { LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class); if (instance == null) { instance = new LaunchActivityItem(); } setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer, voiceInteractor, procState, state, persistentState, pendingResults, pendingNewIntents, isForward, profilerInfo); return instance; } }
7,DNS劫持
HttpDnsService;
8,插件化动态加载方案
从页面A,调到页面B,B承载第三方入口;
B,壳,或ProxyActivity,对他的生命周期注入三方实现;
IPlugin,提供标准,此标准根据页面B所需定制,第三方页面C实现此标准,这样在B页面进行调用时,实际调用的是C,实现了Proxy。
package dc.test.surname.kong;
有必要填一下坑啊。。。。
2019年05月15日22:57:38
--
senRsl
2019年05月09日15:17:47
senRsl
2019年05月09日15:17:47
没有评论 :
发表评论