Task&Activity&ActivityRecord...
来源:互联网 发布:吉林破获特大网络诈骗 编辑:程序博客网 时间:2024/06/06 08:25
1、Activity
2、Stack
3、Task :一个Task是一系列Activity的集合,这个集合是以堆栈的形式来组织的,遵循后进先出的原则。事实上,Task是一个非常复杂的概念,有兴趣的读者可以到官网http://developer.android.com/guide/topics/manifest/activity-element.html查看相关的资料。
4、ActivityRecord
5、TaskRecord ActivityRecor 中有成员变量类型为TaskRecord
实现原理
三者之间的关系
activity for result 的实现
问题:切换或者是退出Activity的时候闪出其他页面
startActivity() ->startActivityForResult() ->
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, who, intent, requestCode, options);
上面的mMainThread是应用程序的主线程
在Instrumentation中的:
(Intrumentation用于监控系统和应用程序之间的交互)
int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
ActivityManagerNative
ActivityManagerService
ActivityManagerProxy
IActivityManager
ActivityManagerProxy、ActivityManagerNative都实现了IActivityManager接口
ActivityManagerNative 继承了 Binder
ActivityManagerService 继承了 ActivityManagerNative
最终进行startActivity是在类ActivityManagerService中,
ActivityManagerService的startActivity()中
//mMainStack是ActivityStackmMainStack.startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions, grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, null, null);
ActivityStack中的startActivityMayWait()方法 调用了startActivityLocked()方法:
startActivityLocked(caller, intent, resolvedType, grantedUriPermissions, grantedMode, aInfo, resultTo, resultWho, requestCode, callingPid, callingUid, onlyIfNeeded, componentSpecified);
ActivityManagerService是管理Activity的生命周周期的。
每个应用程序都有一个ActivityThread来表示应用程序的主进程,每个ActivityThread都包含一个ApplicationThread实例
activity启动过程:
Step 1. 无论是通过Launcher来启动Activity,还是通过Activity内部调用startActivity接口来启动新的Activity,都通过Binder进程间通信进入到ActivityManagerService进程中,并且调用ActivityManagerService.startActivity接口;
Step 2. ActivityManagerService调用ActivityStack.startActivityMayWait来做准备要启动的Activity的相关信息;
Step 3. ActivityStack通知ApplicationThread要进行Activity启动调度了,这里的ApplicationThread代表的是调用ActivityManagerService.startActivity接口的进程,对于通过点击应用程序图标的情景来说,这个进程就是Launcher了,而对于通过在Activity内部调用startActivity的情景来说,这个进程就是这个Activity所在的进程了;
Step 4. ApplicationThread不执行真正的启动操作,它通过调用ActivityManagerService.activityPaused接口进入到ActivityManagerService进程中,看看是否需要创建新的进程来启动Activity;
Step 5. 对于通过点击应用程序图标来启动Activity的情景来说,ActivityManagerService在这一步中,会调用startProcessLocked来创建一个新的进程,而对于通过在Activity内部调用startActivity来启动新的Activity来说,这一步是不需要执行的,因为新的Activity就在原来的Activity所在的进程中进行启动;
Step 6. ActivityManagerServic调用ApplicationThread.scheduleLaunchActivity接口,通知相应的进程执行启动Activity的操作;
Step 7. ApplicationThread把这个启动Activity的操作转发给ActivityThread,ActivityThread通过ClassLoader导入相应的Activity类,然后把它启动起来。
这样,Android应用程序的Activity启动过程就简要介绍到这里了,在接下来的两篇文章中,我们将根据Activity的这两种启动情景,深入到应用程序框架层的源代码里面去,一步一步地分析它们的启动过程:
在方法ActivityStack.startActivityMayWait()方法中:
public class ActivityStack { ...... final int startActivityMayWait(IApplicationThread caller, Intent intent, String resolvedType, Uri[] grantedUriPermissions, int grantedMode, IBinder resultTo, String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug, WaitResult outResult, Configuration config) { ...... boolean componentSpecified = intent.getComponent() != null; // Don't modify the client's object! intent = new Intent(intent); // Collect information about the target of the Intent. ActivityInfo aInfo; try { ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent( intent, resolvedType, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS); aInfo = rInfo != null ? rInfo.activityInfo : null; } catch (RemoteException e) { ...... } if (aInfo != null) { // Store the found target back into the intent, because now that // we have it we never want to do this again. For example, if the // user navigates back to this point in the history, we should // always restart the exact same activity. intent.setComponent(new ComponentName( aInfo.applicationInfo.packageName, aInfo.name)); ...... } synchronized (mService) { int callingPid; int callingUid; if (caller == null) { ...... } else { callingPid = callingUid = -1; } mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0; ...... if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) { ...... } int res = startActivityLocked(caller, intent, resolvedType, grantedUriPermissions, grantedMode, aInfo, resultTo, resultWho, requestCode, callingPid, callingUid, onlyIfNeeded, componentSpecified); if (mConfigWillChange && mMainStack) { ...... } ...... if (outResult != null) { ...... } return res; } } ...... }
上面代码中:
ActivityInfo aInfo; try { ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent( intent, resolvedType, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS); aInfo = rInfo != null ? rInfo.activityInfo : null; } catch (RemoteException e) { ...... }
是将Intent中的信息解析出来得到Activity的相关信息保存在aInfo中
在方法startActivityLocked()中:
final int startActivityLocked(IApplicationThread caller, Intent intent, String resolvedType, Uri[] grantedUriPermissions, int grantedMode, ActivityInfo aInfo, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, boolean onlyIfNeeded, boolean componentSpecified) { int err = START_SUCCESS; ProcessRecord callerApp = null; if (caller != null) { callerApp = mService.getRecordForAppLocked(caller); if (callerApp != null) { callingPid = callerApp.pid; callingUid = callerApp.info.uid; } else { ...... } } ...... ActivityRecord sourceRecord = null; ActivityRecord resultRecord = null; if (resultTo != null) { int index = indexOfTokenLocked(resultTo); ...... if (index >= 0) { sourceRecord = (ActivityRecord)mHistory.get(index); if (requestCode >= 0 && !sourceRecord.finishing) { ...... } } } int launchFlags = intent.getFlags(); if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) { ...... } if (err == START_SUCCESS && intent.getComponent() == null) { ...... } if (err == START_SUCCESS && aInfo == null) { ...... } if (err != START_SUCCESS) { ...... } ...... ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified); ...... return startActivityUncheckedLocked(r, sourceRecord, grantedUriPermissions, grantedMode, onlyIfNeeded, true); }
sourceRecord = (ActivityRecord)mHistory.get(index);
ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified);
即将要启动的Activity的相关信息,并保存在r变量中(r变量是ActivityRecord)
从参数caller得到调用者的进程信息,并保存在callApp中
参数resultTo是Launcher这个Activity里面的一个Binder对象,通过它可以获得Launcher这个Activity的相关信息,保存在sourceRecord变量中。
launcher也是一个Activity,
他的方法startActivitySafely():
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 会在一个新的task中加载Activity。
// Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); } boolean componentSpecified = intent.getComponent() != null; // Don't modify the client's object! intent = new Intent(intent); // Collect information about the target of the Intent. ActivityInfo aInfo; try { ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent( intent, resolvedType, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS); aInfo = rInfo != null ? rInfo.activityInfo : null; } catch (RemoteException e) { aInfo = null; } if (aInfo != null) { // Store the found target back into the intent, because now that // we have it we never want to do this again. For example, if the // user navigates back to this point in the history, we should // always restart the exact same activity. intent.setComponent(new ComponentName( aInfo.applicationInfo.packageName, aInfo.name)); // Don't debug things in the system process if (debug) { if (!aInfo.processName.equals("system")) { mService.setDebugApp(aInfo.processName, true, false); } } } synchronized (mService) { int callingPid; int callingUid; if (caller == null) { callingPid = Binder.getCallingPid(); callingUid = Binder.getCallingUid(); } else { callingPid = callingUid = -1; } mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0; if (DEBUG_CONFIGURATION) Slog.v(TAG, "Starting activity when config will change = " + mConfigWillChange); final long origId = Binder.clearCallingIdentity(); if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) { // This may be a heavy-weight process! Check to see if we already // have another, different heavy-weight process running. if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) { if (mService.mHeavyWeightProcess != null && (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid || !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) { int realCallingPid = callingPid; int realCallingUid = callingUid; if (caller != null) { ProcessRecord callerApp = mService.getRecordForAppLocked(caller); if (callerApp != null) { realCallingPid = callerApp.pid; realCallingUid = callerApp.info.uid; } else { Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + realCallingPid + ") when starting: " + intent.toString()); return START_PERMISSION_DENIED; } } IIntentSender target = mService.getIntentSenderLocked( IActivityManager.INTENT_SENDER_ACTIVITY, "android", realCallingUid, null, null, 0, intent, resolvedType, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT); Intent newIntent = new Intent(); if (requestCode >= 0) { // Caller is requesting a result. newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true); } newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT, new IntentSender(target)); if (mService.mHeavyWeightProcess.activities.size() > 0) { ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0); newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName); newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.task.taskId); } newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP, aInfo.packageName); newIntent.setFlags(intent.getFlags()); newIntent.setClassName("android", HeavyWeightSwitcherActivity.class.getName()); intent = newIntent; resolvedType = null; caller = null; callingUid = Binder.getCallingUid(); callingPid = Binder.getCallingPid(); componentSpecified = true; try { ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent( intent, null, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS); aInfo = rInfo != null ? rInfo.activityInfo : null; } catch (RemoteException e) { aInfo = null; } } } } int res = startActivityLocked(caller, intent, resolvedType, grantedUriPermissions, grantedMode, aInfo, resultTo, resultWho, requestCode, callingPid, callingUid, onlyIfNeeded, componentSpecified); if (mConfigWillChange && mMainStack) { // If the caller also wants to switch to a new configuration, // do so now. This allows a clean switch, as we are waiting // for the current activity to pause (so we will not destroy // it), and have not yet started the next activity. mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, "updateConfiguration()"); mConfigWillChange = false; if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating to new configuration after starting activity."); mService.updateConfigurationLocked(config, null); } Binder.restoreCallingIdentity(origId); if (outResult != null) { outResult.result = res; if (res == IActivityManager.START_SUCCESS) { mWaitingActivityLaunched.add(outResult); do { try { mService.wait(); } catch (InterruptedException e) { } } while (!outResult.timeout && outResult.who == null); } else if (res == IActivityManager.START_TASK_TO_FRONT) { ActivityRecord r = this.topRunningActivityLocked(null); if (r.nowVisible) { outResult.timeout = false; outResult.who = new ComponentName(r.info.packageName, r.info.name); outResult.totalTime = 0; outResult.thisTime = 0; } else { outResult.thisTime = SystemClock.uptimeMillis(); mWaitingActivityVisible.add(outResult); do { try { mService.wait(); } catch (InterruptedException e) { } } while (!outResult.timeout && outResult.who == null); } } } return res; }}//______________________________________________________________________________________________________________Binder对象的远程接口
要想将新的Activity在新的Task中打开,则必须设置intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),并且设置
这个Activity在Manifest.xml中的声明中添加了Task affinity,这个与之前的Activity所在栈的affinity不相同,才能在新的Task中打开新的Activity
adb dump 工具:adb shell dumpsys activity >c:\activity.txt :生成dump文件
- Task&Activity&ActivityRecord...
- Activity的代表ActivityRecord
- android activity管理(三)之ActivityRecord生命周期管理
- android activity管理(五)之ActivityRecord的启动
- android activity管理(六)之ActivityRecord的回收
- activity task
- activity task
- activity task
- Activity Task
- Activity,Task和task栈
- Application,Activity,Task,Activity Stack
- 重用Activity activity task taskAffinity
- activity基础(Activity Task)
- Task和Activity相关
- Task和Activity相关
- Task 和Activity相关
- Task和Activity相关
- Task和Activity相关
- iOS开发UI篇—核心动画(关键帧动画)
- java JVM 运行时数据区
- php实现协程,真正的异步
- thinkphp图片拖动验证码
- iOS Widget快速浏览页面的创建以及证书添加标识符
- Task&Activity&ActivityRecord...
- uboot的移植2-从uboot官方标准uboot开始移植
- ZOJ 2314 Reactor Cooling
- Android内存优化工具(三)MAT
- iOS开发UI篇—核心动画(转场动画和组动画)
- android studio开发手机状态栏颜色更改
- DataBase学习笔记 --- SQL实现如果存在表,则删除
- 负载均衡详解
- uboot杂记-logo显示和fastboot原理等