Tasks and Back Stack

Tasks and Back Stack

尽管这些Activity可能来自不同的应用程序,但Android通过将两个Activity保存在相同的任务栈中来保持这种无缝的用户体验。
当任务栈为空时,任务栈将会被销毁。
一个任务是一个整单元,当用户启动一个新的任务或者通过Home screen返回到主屏幕时,原先的任务就会变成后台任务。在后台任务栈中的Activity将会停止,但是都还在栈中,后台任务只是失去焦点而已。如图2所示:
后台任务可以返回到前台,这样用户就可以在离开的地方继续进行操作,比如:假设当前任务(Task A)有三个Activity。 用户按下“Home”按钮,然后从应用程序启动器启动新的应用程序。 当主屏幕出现时,任务A进入后台。 当新应用程序启动时,系统启动该应用程序的任务(任务B)包含多个Activity。 在与该应用程序交互后,用户再次返回Home并选择最初启动任务A的应用程序。现在,任务A进入前台,同时,堆栈中的所有三个Activity都是完整的,堆栈顶部的Activity恢复。 此时,用户还可以通过回到主页并选择开始该任务的应用程序图标(或从最近的应用程序屏幕中选择应用程序的任务)来切换回任务B。这是Android上多任务的一个例子。
注意:当多个任务栈同时运行在后台的时候,系统有可能销毁后台Activity已恢复内存,这样的话,activity的运行状态就可能丢失。
总结activity和task的默认行为:
1、当Activity A启动Activity B时,Activity A将会停止,Activity B获得交互焦点,当用户点击BACK键时,Activity B销毁,Activity A又返回原先的状态,输入的数据将会保持不变。
2、当用户通过按Home按钮离开一个任务时,当前的Activity就停止了,任务就进入了后台。系统保留任务中每个Activity的状态。如果用户通过选择启动该任务的启动器图标来恢复任务,任务就会出现在前台,并在堆栈顶部恢复Activity。
3、如果用户按下后退按钮,当前的Activity就会从堆栈中弹出并销毁。栈中的前一个Activity将被恢复。当一个Activity被销毁时,系统不会保留Activity的状态
4、Activity可以多次实例化,甚至可以从其他任务中实例化。

在后台任务栈的Activity,当系统回收内存的时候,有可能杀死它,如果Activtiy被杀,那么它在任务栈中的位置,没有改变,系统仍然会记住这个位置,当该位置到栈顶的时候系统只能重建该Activity。此时,Activity进入后台前的运行状态将会丢失,可以通过onSaveInstanceState()方法对Activtiy状态进行保存。
Android管理任务与返回栈与Activity之间的关联关系主要包括三个方面:
Activity的启动模式、关联关系、清除返回栈。这三种关系你可以在清单文件中设置也可以在递给 startActivity() 的 Intent 中进行标志。而在Intent中设置的优先级高于在清单文件中进行设置的。
Activity的启动模式:

一、使用清单文件,在清单文件中声明 Activity 时,您可以使用 <activity> 元素的 launchMode 属性指定 Activity 应该启动。

standard(默认模式):Activity每次启动的时候都会创建一个实例对象,同一个任务栈或不同任务栈中可以包含多个实例对象。

singleTop:当Activtiy实例对象在栈的顶部时,再次启动该Activity就不会再次创建该实例对象,不在顶部的话还会继续创建。当在顶部时,现有实例会通过onNewIntent() 接收 Intent。

singleTask:singleTask模式的Activity只允许在系统中有一个实例。如果系统中已经有了一个实例,持有这个实例的任务将移动到顶部,同时intent将被通过onNewIntent()发送。如果没有,则会创建一个新的Activity并置放在合适的任务中。 在同一个应用中的情况:如果系统中还没有singleTask的Activity,会新创建一个,并放在同一任务的栈顶。但是如果已经存在,singleTask Activity上面的所有Activity将以合适的方式自动销毁,让我们想要显示的Activity处于栈顶。同时Intent也会通过onNewIntent()方法发送到这个singleTask Activity。 和其他应用一起工作的情况:一旦intent是从另外的应用发送过来,并且系统中也没有任何Activity的实例,则会创建一个新的任务,并且新的Activity被作为根Activity创建。除非拥有这个singleTask Activity 的应用已经存在,那样的话,新建的Activity会置于这个任务的上面(而不是新建一个任务)。如图4所示:


singleInstance:当Activity被启动时会进去一个新的任务栈中。并且系统中只有唯一一个实例对象。

注:为某个 Activity 创建新实例时,用户可以按“返回”按钮返回到前一个 Activity。 但是,当 Activity 的现有实例处理新 Intent 时,则在新 Intent 到达 onNewIntent() 之前,用户无法按“返回”按钮返回到 Activity 的状态。

二、使用Intent标志setFlags()

FLAG_ACTIVITY_NEW_TASK:此种方式和”singleTask”模式相同。

FLAG_ACTIVITY_SINGLE_TOP:此种方式和”singleTop”模式相同。

FLAG_ACTIVITY_CLEAR_TOP:如果正在启动的 Activity 已在当前任务中运行,则会销毁当前任务顶部的所有 Activity,并通过 onNewIntent() 将此 Intent 传递给 Activity 已恢复的实例(现在位于顶部),而不是启动该 Activity 的新实例。

注:如果指定 Activity 的启动模式为 "standard",则该 Activity 也会从堆栈中移除,并在其位置启动一个新实例,以便处理传入的 Intent。 这是因为当启动模式为 "standard" 时,将始终为新 Intent 创建新实例。其他的启动模式将不会重新创建。

处理关联

默认情况下,同一个应用程序的Activity彼此关联,所以一般它们都优先位于同一个任务栈中,但是可以修改默认关联:

taskAffinity属性取值字符串,但是必须和默认包名不一样,因为taskAffinity的值是默认包名。taskAffinity的使用一般分为以下两种情况:

第一种和FLAG_ACTIVITY_NEW_TASK放在一起使用:

当一个应用程序加载一个singleTask模式的Activity时,首先该Activity会检查是否存在与它的taskAffinity相同的Task。

1、如果存在,那么检查Activity是否实例化,如果Activity已经实例化,那么销毁在该Activity以上的Activity并调用onNewIntent。如果没有实例化,那么该Activity实例化并入栈。

 2、如果不存在,那么就重新创建Task,并入栈。

  1、当一个应用程序加载一个singleInstance模式的Activity时,如果该Activity没有被实例化,那么就重新创建一个Task,并入栈,如果已经被实例化,那么就调用该Activity的onNewIntent;

   2、singleInstance的Activity所在的Task不允许存在其他Activity,任何从该Activity加载的其它 Actiivty(假设为Activity2)都会被放入其它的Task中,如果存在与Activity2相同affinity的Task,则在该 Task内创建Activity2。如果不存在,则重新生成新的Task并入栈。

<application android:icon="@drawable/icon" android:label="@string/app_name"> 
        <activity android:name=".Activity1" 
                  android:taskAffinity="com.winuxxan.task" 
                  android:label="@string/app_name"> 
        </activity> 
        <activity android:name=".Activity2"> 
            <intent-filter> 
                <action android:name="android.intent.action.MAIN" /> 
                <category android:name="android.intent.category.LAUNCHER" /> 
            </intent-filter> 
        </activity> 
    </application> 


 Activity2的代码如下: 

    public class Activity2 extends Activity {  
        private static final String TAG = "Activity2";  
        @Override 
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.main2);    
        }  
               
        @Override 
        public boolean onTouchEvent(MotionEvent event) {  
            Intent intent = new Intent(this, Activity1.class);  
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
            startActivity(intent);  
            return super.onTouchEvent(event);  
        }  
    } 


 然后,我们再写一个应用MyActivity,它包含一个Activity(MyActivity),AndroidManifest.xml如下: 

<application android:icon="@drawable/icon" android:label="@string/app_name"> 
        <activity android:name=".MyActivity" 
                  android:taskAffinity="com.winuxxan.task" 
                  android:label="@string/app_name"> 
            <intent-filter> 
                <action android:name="android.intent.action.MAIN"/> 
                <category android:name="android.intent.category.LAUNCHER"/> 
            </intent-filter> 
        </activity>

第二种情况。如果该Activity的allowTaskReparenting设置为true,它进入后台,当一个和它有相同affinity的Task进入前台时,它会重新宿主,进入到该前台的task中。

例如,假设将报告所选城市天气状况的 Activity 定义为旅行应用的一部分。它与同一应用中的其他 Activity 具有相同的关联(默认应用关联),并允许利用此属性重定父级。当您的一个 Activity 启动天气预报 Activity 时,它最初所属的任务与您的 Activity 相同。但是,当旅行应用的任务出现在前台时,系统会将天气预报 Activity 重新分配给该任务并显示在其中。

清理返回栈

如果用户长时间离开任务,系统就会把该任务栈中的Acitvity全部销毁,只留下根Activity。但是可以通过这些设置进行销毁。

alwaysRetainTaskState:如果在任务的根 Activity 中将此属性设置为 "true",则不会发生刚才所述的默认行为。即使在很长一段时间后,任务仍将所有 Activity 保留在其堆栈中。

clearTaskOnLaunch:如果在任务的根 Activity 中将此属性设置为 "true",则每当用户离开任务然后返回时,系统都会将堆栈清除到只剩下根 Activity。换而言之,它与 alwaysRetainTaskState 正好相反。 即使只离开任务片刻时间,用户也始终会返回到任务的初始状态。

finishOnTaskLaunc:此属性类似于 clearTaskOnLaunch,但它对单个 Activity 起作用,而非整个任务。此外,它还有可能会导致任何 Activity 停止,包括根 Activity。设置为 "true" 时,Activity 仍是任务的一部分,但是仅限于当前会话。如果用户离开然后返回任务,则任务将不复存在。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值