
amdroid将Activity放入全局栈如下:
import javautilStack;
import androidappActivity;
public class ScreenManager {
private static Stack activityStack;
private static ScreenManager instance;
private ScreenManager(){
}
public static ScreenManager getScreenManager(){
if(instance==null){
Activity是Android程序的表现层。程序的每一个显示屏幕就是一个Activity。正在运行的Activity处在栈的最顶端,它是运行状态的。
在Android中每个界面都是一个Activity,切换界面 *** 作其实是多个不同Activity之间的实例化 *** 作。在Android中Activity的启动模式决定了Activity的启动运行方式。
Android总Activity的启动模式分为四种:
Activity启动模式设置:
<activity android:name="MainActivity" android:launchMode="standard" />
Activity的四种启动模式:
1 standard
模式启动模式,每次激活Activity时都会创建Activity,并放入任务栈中。
2 singleTop
如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。
3 singleTask
如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
4 singleInstance
在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦改模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。
其中standard是系统默认的启动模式。
下面通过实例来演示standard的运行机制:
1 private TextView text_show;
2 private Button btn_mode;
3
4 @Override
5 public void onCreate(Bundle savedInstanceState) {
6 superonCreate(savedInstanceState);
7 setContentView(Rlayoutactivity_main);
8
9 text_show = (TextView) thisfindViewById(Ridtext_show);
10
11 text_showsetText(thistoString());
12
13 btn_mode = (Button) thisfindViewById(Ridbtn_mode);
14
15 }
16
//按钮单击事件
17 public void LaunchStandard(View v){
18 startActivity(new Intent(this,MainActivityclass));
19
20 text_showsetText(thistoString());
21 }
android开发中获取当前的Activity有多种情况; 在Activity中,this就是当前的Activity,例如thisstartActivity。 在Fragment中可以通过 getActivity()来得到当前装载这个Fragment的Activity。 通过Activity堆栈来获取当前显示的这个ActivityAc。详细的可以看看安卓巴士教程:>
首先是新建一个Android工程,然后修改mainxml文件如下:
添加一个ListView
[html] view plaincopy
<xml version="10" encoding="utf-8">
<LinearLayout xmlns:android=">
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/tasklist"
/>
</LinearLayout>
然后编辑java代码
[java] view plaincopy
package comcaydenrun;
import javautilArrayList;
import javautilIterator;
import javautilList;
import androidappActivity;
import androidappActivityManager;
import androidappActivityManagerRunningTaskInfo;
import androidcontentContext;
import androidosBundle;
import androidwidgetArrayAdapter;
import androidwidgetListAdapter;
import androidwidgetListView;
public class MyActivityRunDemo extends Activity {
private ListView tasklist=null;
private ListAdapter adapter=null;
private List<String> all=new ArrayList<String>();
private ActivityManager activityManager=null;
/ Called when the activity is first created /
@Override
public void onCreate(Bundle savedInstanceState) {
superonCreate(savedInstanceState);
setContentView(Rlayoutmain);
tasklist=(ListView)thisfindViewById(Ridtasklist);
activityManager=(ActivityManager)supergetSystemService(ContextACTIVITY_SERVICE);
listActivity();
}
public void listActivity(){
List<RunningTaskInfo> tasks= activityManagergetRunningTasks(30);
Iterator<RunningTaskInfo> itInfo=tasksiterator();
while(itInfohasNext()){
RunningTaskInfo info=itInfonext();
alladd("id="+infoid+","+infobaseActivitygetClassName());
}
adapter=new ArrayAdapter<String>(this, androidRlayoutsimple_list_item_1,thisall);
tasklistsetAdapter(adapter);
}
}
最后需要再配置所需要的权限AndroidManifestxml
[html] view plaincopy
<xml version="10" encoding="utf-8">
<manifest xmlns:android=">
package="comcaydenrun"
android:versionCode="1"
android:versionName="10">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name="MyActivityRunDemo"
android:label="@string/app_name">
<intent-filter>
<action android:name="androidintentactionMAIN" />
<category android:name="androidintentcategoryLAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="androidpermissionGET_TASKS"></uses-permission>
</manifest>
程序运行效果如图所示:
public void updateServiceNotification(String message) {
if (!PreferenceUtilsgetPrefBoolean(this,
PreferenceConstantsFOREGROUND, true))
return;
String title = PreferenceUtilsgetPrefString(this,
PreferenceConstantsACCOUNT, "");
Notification n = new Notification(Rdrawablelogin_default_avatar,
title, SystemcurrentTimeMillis());
nflags = NotificationFLAG_ONGOING_EVENT | NotificationFLAG_NO_CLEAR;
Intent notificationIntent = new Intent(this, MainActivityclass);
notificationIntentsetFlags(IntentFLAG_ACTIVITY_CLEAR_TOP);
ncontentIntent = PendingIntentgetActivity(this, 0,
notificationIntent, PendingIntentFLAG_UPDATE_CURRENT);
nsetLatestEventInfo(this, title, message, ncontentIntent);
startForeground(SERVICE_NOTIFICATION, n);
}
// 判断程序是否在后台运行的任务,其实个人觉得这个办法并不太好,
Runnable monitorStatus = new Runnable() {
public void run() {
try {
Li("monitorStatus is running " + mPackageName);
mMainHandlerremoveCallbacks(monitorStatus);
// 如果在后台运行并且连接上了
if (!isAppOnForeground()) {
Li("app run in background");
// if (isAuthenticated())//不判断是否连接上了。
updateServiceNotification(getString(Rstringrun_bg_ticker));
return;// 服务已在前台运行,可以停止重复执行此任务
} else {
stopForeground(true);
}
mMainHandlerpostDelayed(monitorStatus, 1000L);
} catch (Exception e) {
eprintStackTrace();
Li("monitorStatus:"+egetMessage());
}
}
LaunchMode 定义的是activity实例与task之间的关系,可以通过下面的两种方式来定义:
在Activity A中启动B,可以利用Activity B在清单中的launchmode定义,也可以在A中调用startActivity()的时候通过intent的flag传入,当两种方式都有定义,intent的flag参数会覆盖掉B原有的定义。
利用Activity 元素的launchMode属性
launchMode属性指定Activity如何被运行到一个task中。launchMode的值有四种:
默认, 每次启动Activity系统都会产生一个新的实例,并且把intent发送给新产生的实例,这个Activity可以被实例化多次,每个实例可以属于不同的task,每个task也可以保有多个此Activity的实例。
如果当前task 的回退栈栈顶已经存在一个此Activity的实例,系统通过调用这个实例的onNewIntent()方法把intent发送给这个Activity实例,而不是创建一个新的此Activity的实例。这个Activity也可以被实例化多次,每个实例可以属于不同的task,每个task可一个保有多个实例(仅限于此Activity已存在的实例不在栈顶)
注意:
应用场合如下:不想出现2个同样的activity在顶部。比如用户正在一个activity阅读信息,这时来了notification,用户点击后应该更新这些信息,而不是新建一个activity,这样在点击back时,就不会出现回到旧信息activity的情况了。这种情况正是下面这段英语提到的。
Note: When a new instance of an activity is created, the user can press the Back button to return to the previous activity But when an existing instance of an activity handles a new intent, the user cannot press the Back button to return to the state of the activity before the new intent arrived in onNewIntent()
例如,当前回退栈中有A,B,C,D四个Activity,全部是Standard,在D中调用startActivity()去启动B,intent的flag设置成FLAG_ACTIVITY_CLEAR_TOP 和FLAG_ACTIVITY_NEW_TASK,系统发现栈中有B,会先销毁这个B,再原位置重建B,清空CD,而不是把这个新建的B的实例压入栈顶,这里之所以会销毁B再新建B,因为B的launchmode是Standard,无论什么情况下启动,都需要new一个B的实例,但如果此时B是SingleTop的,系统会把这个intent通过onNewIntent传给已经在栈中的B的实例,不需要销毁再创建,仍需要清空CD。
系统会创建一个新的task并且把这个实例放在栈底( 此处有疑问,测试发现并不一定是栈底 ),但是,如果在一个单独的task中已经存在一个此Activity的实例,系统会把intent通过onNewIntent()发送给这个实例( 测试发现如果在回退栈中,该Activity的上面还有其他Activity,启动此Activity会清空栈中此Activity上面的其他Activity ),而不是创建一个新的实例。同一时间在只有一个此Activity的实例存在于系统中。
与SingleTask一样,不同的是SingleTask的Activity所在的task中可以有其他的Activity,而SingleInstance的Activity独占一个task,并且在整个系统中只有唯一的一个实例。由这个Activity启动的其他Activity都会在新的task中打开。
另一个例子,系统自带浏览器APP把浏览器Activity声明为SingleTask,通过在Activity标签里的launchMode进行指定,这意味着如果你发送一个intent启动浏览器,不管是为浏览器新开启一个task还是从浏览器已经在后台保有的task中启动浏览器,浏览器Activity与你的APP不在同一个task。
不管一个Activity是不是在一个新的task中启动,点击返回都会返回前一个Activity。不过,如果启动一个LaunchMode为singleTask的Activity,如果该Activity此时在一个处于后台的task中,整个task会变成前台task,此时,回退栈会包含由这个后台task携带过来所有Activity,放在回退栈的栈顶,下图说明这种情况。
在一个新的task里启动Activity 如果已经有Activity实例运行在某一task中,启动这个Activity会把该实例所在的task带到前台,由该实例的onNewIntent()来接收新的intent。
如果被启动的Activity就是当前的Activity,这个已经存在的实例通过onNewIntent()接收intent,不会产生新的实例。
被启动的Activity如果已经存运行于当前task,回退栈中所有在此Activity上面的Activity都将被销毁,此Activity通过onNewIntent()接收新的intent。
例如,一个task中有A,B,C,D,四个Activity,如果D 调用startActivtiy()启动Activity B,C和D会被销毁,B接收这个intent,回退栈中有A,B。
上例中的Activity B的实例,或者通过onNewIntent()接收新的intent,或者销毁新建来处理新的intent。如果B的launchmode是standard,并且没有设置FLAG_ACTIVITY_SINGLE_TOP,那么B会被销毁重启,如果是其他launchmode或者设置了FLAG_ACTIVITY_SINGLE_TOP,则会通过onNewIntent()接收。
FLAG_ACTIVITY_CLEAR_TOP 和FLAG_ACTIVITY_NEW_TASK结合使用会有个不错的效果。
如果启动的Activity位于task的底部,它会把所在task带到前台,并且清理状态至root状态,当从通知栏里打开一个Activity的会非常有用。
Affinity指的是一个Activity偏向于从属于哪个task,默认情况下,一个APP内的所有Activity互相之间共享一个affinity的值,所以,所有同一APP下的所有Activity都偏向于从属于同一个task。但是,这个值是可以更改的,不同APP内的Activity可以共享一个affinity,同一个APP内的Activity也可以被分配不同的affinity的值。
affinity的值可以通过修改Activity标签的taskAffinity属性来修改。
这个属性接收一个String的值,必须在manifest标签范围内是唯一的值,因为系统是通过名称来标识APP的affinity的值的。
Affinity作用于以下两种情况:
通过startActivity()启动一个新的Activity时,默认情况下,新的Activity会被压入与启动者相同的回退栈中。但是,如果在启动Activity的时候,使用了FLAG_ACTIVITY_NEW_TASK 这个标志,系统会为新的Activity寻找一个新的task。通常情况下,是一个新的task。但是也并不是必须的。如果系统中有一个task的affinity值与新的Activity的值相同,新的Activity会被分配到这个task中。如果没有这样的task,就启动一个新的task。如果这个标志产生了一个新的task,当用户点击home键离开的时候,必须要有某种方式能够使用户返回到这个task来。有些实体(例如通知管理器)总是从一个外部task中启动Activity,所以在通过startActivity()启动新的Activity时总是需要传递FLAG_ACTIVITY_NEW_TASK 这个标志。如果你有一个Activity可以被外部实体可能这个标志启动,注意用户可以有一种独立的方式回到启动它的task,例如点击启动图标。
这种情况下,一个Activity可以动启动它的那个task移动到它的affinity值对应的task中,当那个task回到前台。例如,假设,一个报告指定城市天气情况的Activity作为一个旅行APP的一部分,它跟其他处在同一APP的Activity一样有一个相同的affinity值,并且允许通过这个属性来调整目标task。当你的一个Activity启动了这个天气预报Activity,它默认跟你的Activity在一个task里,但是,当旅行APP进入到前台,这个天气预报Activity又会被重新分配给旅行APP并且在旅行APP内展示。
提示:
如果一个APK文件从用户的角度看是多款APP,可能需要这个属性来设置不同的affinity来关联不同的APP。
如果用户离开一个task太长时间,系统会清除task中的所有Activity仅仅保留这下根Activity。当用户返回到这个task的时候,只有这个根Activity会被恢复。系统通过这种方式来处理,是因为经过相当长的一段时间之后,用户已经抛弃他们曾经正在做的事情,计划再回来的时候做点新的事情。
你可以通过如下属性来更改这种行为:
参考文献:
Tasks and Back Stack
<activity>
Android 阅读Tasks and Back Stack文章后的重点摘抄
以上就是关于android怎样将activity放入全局栈全部的内容,包括:android怎样将activity放入全局栈、android 怎么获取一个activity启动模式、安卓自动化测试怎么获取当前正在运行activity等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)