The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance. Only one instance of the activity can exist at a time.
Running activities (most recent first):
TaskRecord{4070d8f8 #3 A shy.luo.task}
Run #2: HistoryRecord{406a13f8 shy.luo.task/.SubActivity}
Run #1: HistoryRecord{406a0e00 shy.luo.task/.MainActivity}
TaskRecord{4067a510 #2 A com.android.launcher}
Run #0: HistoryRecord{40677518 com.android.launcher/com.android.launcher2.Launcher}
果然,SubActivity和MainActivity都是运行在TaskRecord#3中,并且SubActivity在MainActivity 的上面。这是怎么回事呢?碰到这种情况,Linus Torvalds告诫我们:Read the fucking source code;去年张麻子又说:枪在手,跟我走;我们没有枪,但是有source code,因此,我要说:跟着代码走。
publicclass ActivityStack {
......
finalint startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, Uri[] grantedUriPermissions,
int grantedMode, boolean onlyIfNeeded, boolean doResume){final Intent intent = r.intent;finalint callingUid = r.launchedFromUid;int launchFlags = intent.getFlags();
......
ActivityRecord notTop =(launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)!=0? r :null;
......
if(sourceRecord ==null){
......
}elseif(sourceRecord.launchMode== ActivityInfo.LAUNCH_SINGLE_INSTANCE){
......
}elseif(r.launchMode== ActivityInfo.LAUNCH_SINGLE_INSTANCE|| r.launchMode== ActivityInfo.LAUNCH_SINGLE_TASK){// The activity being started is a single instance... it always// gets launched into its own task.
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;}
......
boolean addingToTask =false;if(((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0&&(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK)==0)|| r.launchMode== ActivityInfo.LAUNCH_SINGLE_TASK|| r.launchMode== ActivityInfo.LAUNCH_SINGLE_INSTANCE){// If bring to front is requested, and no result is requested, and// we can find a task that was started with this same// component, then instead of launching bring that one to the front.if(r.resultTo==null){// See if there is a task to bring to the front. If this is// a SINGLE_INSTANCE activity, there can be one and only one// instance of it in the history, and it is always in its own// unique task, so we do a special search.
ActivityRecord taskTop = r.launchMode!= ActivityInfo.LAUNCH_SINGLE_INSTANCE? findTaskLocked(intent, r.info): findActivityLocked(intent, r.info);if(taskTop !=null){
......
if((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP)!=0|| r.launchMode== ActivityInfo.LAUNCH_SINGLE_TASK|| r.launchMode== ActivityInfo.LAUNCH_SINGLE_INSTANCE){// In this situation we want to remove all activities// from the task up to the one being started. In most// cases this means we are resetting the task to its// initial state.
ActivityRecord top = performClearTaskLocked(
taskTop.task.taskId, r, launchFlags, true);if(top !=null){
......
}else{// A special case: we need to// start the activity because it is not currently// running, and the caller has asked to clear the// current task to have this activity at the top.
addingToTask =true;// Now pretend like this activity is being started// by the top of its task, so it is put in the// right place.
sourceRecord = taskTop;}}elseif(r.realActivity.equals(taskTop.task.realActivity)){
......
}elseif((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)==0){
......
}elseif(!taskTop.task.rootWasReset){
......
}
......
}}}
......
if(r.packageName!=null){// 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.
ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);if(top !=null&& r.resultTo==null){if(top.realActivity.equals(r.realActivity)){if(top.app!=null&& top.app.thread!=null){
......
}}}}else{
......
}boolean newTask =false;// Should this be considered a new task?if(r.resultTo==null&&!addingToTask
&&(launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0){// todo: should do better management of integers.
mService.mCurTask++;if(mService.mCurTask<=0){
mService.mCurTask=1;}
r.task=new TaskRecord(mService.mCurTask, r.info, intent,
(r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH)!=0);if(DEBUG_TASKS) Slog.v(TAG, "Starting new activity "+ r
+" in new task "+ r.task);
newTask =true;if(mMainStack){
mService.addRecentTaskLocked(r.task);}}elseif(sourceRecord !=null){if(!addingToTask &&(launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP)!=0){
......
}elseif(!addingToTask &&(launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)!=0){
......
}// An existing activity is starting this new activity, so we want// to keep the new one in the same task as the one that is starting// it.
r.task= sourceRecord.task;
......
}else{
......
}
......
startActivityLocked(r, newTask, doResume);return START_SUCCESS;}
......
}
if(sourceRecord ==null){
......
}elseif(sourceRecord.launchMode== ActivityInfo.LAUNCH_SINGLE_INSTANCE){
......
}elseif(r.launchMode== ActivityInfo.LAUNCH_SINGLE_INSTANCE|| r.launchMode== ActivityInfo.LAUNCH_SINGLE_TASK){// The activity being started is a single instance... it always// gets launched into its own task.
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;}
publicclass ActivityStack {
......
/**
* Perform clear operation as requested by
* {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
* stack to the given task, then look for
* an instance of that activity in the stack and, if found, finish all
* activities on top of it and return the instance.
*
* @param newR Description of the new activity being started.
* @return Returns the old activity that should be continue to be used,
* or null if none was found.
*/privatefinal ActivityRecord performClearTaskLocked(int taskId,
ActivityRecord newR, int launchFlags, boolean doClear){int i = mHistory.size();// First find the requested task.while(i >0){
i--;
ActivityRecord r =(ActivityRecord)mHistory.get(i);if(r.task.taskId== taskId){
i++;break;}}// Now clear it.while(i >0){
i--;
ActivityRecord r =(ActivityRecord)mHistory.get(i);if(r.finishing){continue;}if(r.task.taskId!= taskId){returnnull;}if(r.realActivity.equals(newR.realActivity)){// Here it is! Now finish everything in front...
ActivityRecord ret = r;if(doClear){while(i <(mHistory.size()-1)){
i++;
r =(ActivityRecord)mHistory.get(i);if(r.finishing){continue;}if(finishActivityLocked(r, i, Activity.RESULT_CANCELED,
null, "clear")){
i--;}}}// Finally, if this is a normal launch mode (that is, not// expecting onNewIntent()), then we will finish the current// instance of the activity so a new fresh one can be started.if(ret.launchMode== ActivityInfo.LAUNCH_MULTIPLE&&(launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP)==0){if(!ret.finishing){int index = indexOfTokenLocked(ret);if(index >=0){
finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
null, "clear");}returnnull;}}return ret;}}returnnull;}
......
}
if(top !=null){
......
}else{// A special case: we need to// start the activity because it is not currently// running, and the caller has asked to clear the// current task to have this activity at the top.
addingToTask =true;// Now pretend like this activity is being started// by the top of its task, so it is put in the// right place.
sourceRecord = taskTop;}
if(r.packageName!=null){// 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.
ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);if(top !=null&& r.resultTo==null){if(top.realActivity.equals(r.realActivity)){if(top.app!=null&& top.app.thread!=null){
......
}}}}else{
......
}
boolean newTask =false;// Should this be considered a new task?if(r.resultTo==null&&!addingToTask
&&(launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0){
......
}elseif(sourceRecord !=null){if(!addingToTask &&(launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP)!=0){
......
}elseif(!addingToTask &&(launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)!=0){
......
}// An existing activity is starting this new activity, so we want// to keep the new one in the same task as the one that is starting// it.
r.task= sourceRecord.task;
......
}else{
......
}
到这里,思路就理清了,虽然SubActivity的launchMode被设置为”singleTask”模式,但是它并不像官方文档描述的一 样:The system creates a new task and instantiates the activity at the root of the new task,而是在跟它有相同taskAffinity的任务中启动,并且位于这个任务的堆栈顶端,于是,前面那个图中,就会出现一个带 着”singleTask”标签的箭头指向一个任务堆栈顶端的Activity Y了。 那么,我们有没有办法让一个”singleTask”的Activity在新的任务中启动呢?答案是肯定的。从上面的代码分析中,只要我们能够进入函数startActivityUncheckedLocked的这个if语句中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if(r.resultTo==null&&!addingToTask
&&(launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0){// todo: should do better management of integers.
mService.mCurTask++;if(mService.mCurTask<=0){
mService.mCurTask=1;}
r.task=new TaskRecord(mService.mCurTask, r.info, intent,
(r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH)!=0);if(DEBUG_TASKS) Slog.v(TAG, "Starting new activity "+ r
+" in new task "+ r.task);
newTask =true;if(mMainStack){
mService.addRecentTaskLocked(r.task);}}
Running activities (most recent first):
TaskRecord{4069c020 #4 A shy.luo.task.sub.activity}
Run #2: HistoryRecord{40725040 shy.luo.task/.SubActivity}
TaskRecord{40695220#3 A shy.luo.task.main.activity}
Run #1: HistoryRecord{406b26b8 shy.luo.task/.MainActivity}
TaskRecord{40599c90 #2 A com.android.launcher}
Run #0: HistoryRecord{40646628 com.android.launcher/com.android.launcher2.Launcher}
As shown in the table above, standard is the default mode and is appropriate for most types of activities. SingleTop is also a common and useful launch mode for many types of activities. The other modes — singleTask and singleInstance —are not appropriate for most applications, since they result in an interaction model that is likely to be unfamiliar to users and is very different from most other applications. Regardless of the launch mode that you choose, make sure to test the usability of the activity during launch and when navigating back to it from other activities and tasks using the BACK key.
这样看,官方文档也没有坑我们呢,它告诫我们:make sure to test the usability of the activity during launch。
刚在一台IBM Xserver服务器上装了RedHat Linux Enterprise AS 4,为了提高网络的可靠性配置双网卡绑定。
一、环境描述
我的RedHat Linux Enterprise AS 4安装双口的Intel千兆网卡,通过ifconfig -a命令看到eth0和eth1两张网卡。
二、双网卡绑定步骤:
2.1 修改/etc/sysconfig/network
1.AdviceMethods.java
package com.bijian.study.spring.aop.schema;
public class AdviceMethods {
public void preGreeting() {
System.out.println("--how are you!--");
}
}
2.beans.x
包括Spark Streaming在内的实时计算数据可靠性指的是三种级别:
1. At most once,数据最多只能接受一次,有可能接收不到
2. At least once, 数据至少接受一次,有可能重复接收
3. Exactly once 数据保证被处理并且只被处理一次,
具体的多读几遍http://spark.apache.org/docs/lates
具体思路参见:http://zhedahht.blog.163.com/blog/static/25411174200712895228171/
import java.util.ArrayList;
import java.util.List;
public class MinStack {
//maybe we can use origin array rathe
日期转换函数的详细使用说明
DATE_FORMAT(date,format) Formats the date value according to the format string. The following specifiers may be used in the format string. The&n