区分Activity的四种加载模式-activity

转载:http://marshal.easymorse.com/archives/2950

 

在多Activity开发中,有可能是自己应用之间的Activity跳转,或者夹带其他应用的可复用Activity。可能会希望跳转到原来某个Activity实例,而不是产生大量重复的Activity。

这需要为Activity配置特定的加载模式,而不是使用默认的加载模式。

加载模式分类及在哪里配置

Activity有四种加载模式:

  • standard
  • singleTop
  • singleTask
  • singleInstance

设置的位置在AndroidManifest.xml文件中activity元素的android:launchMode属性:

<activity android:name="ActB" android:launchMode="singleTask"></activity>

也可以在Eclipse ADT中图形界面中编辑:

image

 

区分Activity的加载模式,通过示例一目了然。这里编写了一个Activity A(ActA)和Activity B(ActB)循环跳转的例子。对加载模式修改和代码做稍微改动,就可以说明四种模式的区别。

standard

首先说standard模式,也就是默认模式,不需要配置launchMode。先只写一个名为ActA的Activity:

Java代码
    package com.easymorse.activities;  import android.app.Activity;  import android.content.Intent;  import android.os.Bundle;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.Button;  import android.widget.LinearLayout;  import android.widget.TextView;  public class ActA extends Activity {  /** Called when the activity is first created. */  @Override  public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  TextView textView = new TextView(this);  textView.setText(this + "");  Button button = new Button(this);  button.setText("go actA");  button.setOnClickListener(new OnClickListener() {  @Override  public void onClick(View v) {  Intent intent = new Intent();  intent.setClass(ActA.this, ActA.class);  startActivity(intent);  }  });  LinearLayout layout = new LinearLayout(this);  layout.setOrientation(LinearLayout.VERTICAL);  layout.addView(textView);  layout.addView(button);  this.setContentView(layout);  }  }  

 

例子中都没有用layout,免得看着罗嗦。可见是ActA –> ActA的例子。在界面中打印出对象的toString值可以根据hash code识别是否创建新ActA实例。

第一个界面:

image

点击按钮后:

image

可以多点几次。发现每次都创建了该Activity的新实例。standard的加载模式就是这样的,intent将发送给新的实例。

现在点Android设备的回退键,可以看到是按照刚才创建Activity实例的倒序依次出现,类似退栈的操作,而刚才操作跳转按钮的过程是压栈的操作。如下图:

image

singleTop

singleTop和standard模式,都会将intent发送新的实例(后两种模式不发送到新的实例,如果已经有了的话)。不过,singleTop要求如果创建intent的时候栈顶已经有要创建的Activity的实例,则将intent发送给该实例,而不发送给新的实例。

还是用刚才的示例,只需将launchMode改为singleTop,就能看到区别。

运行的时候会发现,按多少遍按钮,都是相同的ActiA实例,因为该实例在栈顶,因此不会创建新的实例。如果回退,将退出应用。

image

singleTop模式,可用来解决栈顶多个重复相同的Activity的问题。

如果是A Activity跳转到B Activity,再跳转到A Activity,行为就和standard一样了,会在B Activity跳转到A Activity的时候创建A Activity的新实例,因为当时的栈顶不是A Activity实例。

ActA类稍作改动:

Java代码
    package com.easymorse.activities;  import android.app.Activity;  import android.content.Intent;  import android.os.Bundle;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.Button;  import android.widget.LinearLayout;  import android.widget.TextView;  public class ActA extends Activity {  /** Called when the activity is first created. */  @Override  public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  TextView textView = new TextView(this);  textView.setText(this + "");  Button button = new Button(this);  button.setText("go actB");  button.setOnClickListener(new OnClickListener() {  @Override  public void onClick(View v) {  Intent intent = new Intent();  intent.setClass(ActA.this, ActB.class);  startActivity(intent);  }  });  LinearLayout layout = new LinearLayout(this);  layout.setOrientation(LinearLayout.VERTICAL);  layout.addView(textView);  layout.addView(button);  this.setContentView(layout);  }  }  

 

 

ActB类:

Java代码
    package com.easymorse.activities;  import android.app.Activity;  import android.content.Intent;  import android.os.Bundle;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.Button;  import android.widget.LinearLayout;  public class ActB extends Activity {  @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  Button button=new Button(this);  button.setText("go actA");  button.setOnClickListener(new OnClickListener() {  @Override  public void onClick(View v) {  Intent intent=new Intent();  intent.setClass(ActB.this, ActA.class);  startActivity(intent);  }  });  LinearLayout layout=new LinearLayout(this);  layout.addView(button);  this.setContentView(layout);  }  }  

 

 

ActB类使用默认(standard)加载,ActA使用singleTop加载。结果类似下图:

image

如果把ActA的加载模式改为standard,情况一样。

singleTask

singleTask模式和后面的singleInstance模式都是只创建一个实例的。

当intent到来,需要创建singleTask模式Activity的时候,系统会检查栈里面是否已经有该Activity的实例。如果有直接将intent发送给它。

把上面singleTop的实例中的ActA的launchMode改为singleTask,ActB的改为standard。那么会发现在ActA界面中按一次按钮:

image

然后在ActB1界面中按按钮,因为ActA是singleTask,会使用原来的ActA1实例。这时候栈内的情况:

image

如果多次按按钮跳转,会发现始终只有ActA1这一个ActA类的实例。

singleInstance

解释singleInstance模式比较麻烦。

首先要说一下Task(任务)的概念。

如果是Swing或者Windows程序,可能有多个窗口可以切换,但是你无法在自己程序中复用人家的窗口。注意是直接复用人家的二进制代码,不是你拿到人家api后的源代码级调用。

Android可以做到,让别人的程序直接复用你的Activity(类似桌面程序的窗口)。

Android为提供这种机制,就引入了Task的概念。Task可以认为是一个栈,可放入多个Activity。比如启动一个应用,那么Android就创建了一个Task,然后启动这个应用的入口Activity,就是intent-filter中配置为main和launch的那个(见一个APK文件部署产生多个应用安装的效果)。这个Activity是根(Root)Activity,可能会在它的界面调用其他Activity,这些Activity如果按照上面那三个模式,也会在这个栈(Task)中,只是实例化的策略不同而已。

验证的办法是调用和打印Activity的taskId:

TextView textView2 = new TextView(this);
textView2.setText("task id: "+this.getTaskId());

会发现,无论切换Activity,taskId是相同的。

当然也可以在这个单一的Task栈中,放入别人的Activity,比如google地图,这样用户看过地图按回退键的时候,会退栈回到调用地图的Activity。对用户来说,并不觉得在操作多个应用。这就是Task的作用。

但是,有这样的需求,多个Task共享一个Activity(singleTask是在一个task中共享一个Activity)。

现成的例子是google地图。比如我有一个应用是导游方面的,其中调用的google地图Activity。那么现在我比如按home键,然后到应用列表中打开google地图,你会发现显示的就是刚才的地图,实际上是同一个Activity。

如果使用上面三种模式,是无法实现这个需求的。google地图应用中有多个上下文Activity,比如路线查询等的,导游应用也有一些上下文Activity。在各自应用中回退要回退到各自的上下文Activity中。

singleInstance模式解决了这个问题(绕了这么半天才说到正题)。让这个模式下的Activity单独在一个task栈中。这个栈只有一个Activity。导游应用和google地图应用发送的intent都由这个Activity接收和展示。

这里又有两个问题:

  • 如果是这种情况,多个task栈也可以看作一个应用。比如导游应用启动地图Activity,实际上是在导游应用task栈之上singleInstance模式创建的(如果还没有的话,如果有就是直接显示它)一个新栈,当这个栈里面的唯一Activity,地图Activity回退的时候,只是把这个栈移开了,这样就看到导游应用刚才的Activity了;
  • 多个应用(Task)共享一个Activity要求这些应用都没有退出,比如刚才强调要用home键从导游应用切换到地图应用。因为,如果退出导游应用,而这时也地图应用并未运行的话,那个单独的地图Activity(task)也会退出了。

如果还是拿刚才的ActA和ActB的示例,可以把ActB的模式改为singleInstance,ActA为standard,如果按一次按钮切换到ActB,看到现象用示意图类似这样:

image

如果是第一次按钮切换到ActB,在ActB在按按钮切换到ActA,然后再回退,示意图是:

image

另外,可以看到两个Activity的taskId是不同的


转载于:https://www.cnblogs.com/java20130722/archive/2012/08/28/3207324.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/494743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nature:AI为什么总是歧视重重?

来源&#xff1a;网络大数据摘要&#xff1a;当使用谷歌翻译将西班牙语的新闻翻译为英语时&#xff0c;涉及到女性的短语通常都会翻译为“他说”或“他写道”。当使用谷歌翻译将西班牙语的新闻翻译为英语时&#xff0c;涉及到女性的短语通常都会翻译为“他说”或“他写道”。常…

※【python自学】7个Python生态系统核心库,你值得拥有

无论你是想快速入手Python&#xff0c;还是想成为数据分析大神或者机器学习大佬&#xff0c;亦或者对Python代码进行优化&#xff0c;本文的python库都能为你提供一些帮助。 一 概述 Python生态系统的一些核心基础数据分析库&#xff1a; NumPy&#xff1a;支持大量的维度数…

Eclipse编写Java程序

Eclipse的Java开发工具(JDT),允许用户使用它的环境进行编辑、调试及运行Java程序。1. Java运行环境设置 指定JRE的版本。Eclipse设置默认的运行环境的JRE设置成当前配置&#xff0c;用户可以修改多个JRE版本的运行环境&#xff0c;并选择符合其需求的运行环境。[窗口 Window]…

㊙️【教你用python挣零花钱】自动化简历内推,学弟直呼牛逼!!

最近&#xff0c;小编在处理简历时&#xff0c;发现大量简历需要一个个打开文件&#xff0c;复制姓名、邮箱、电话号码、学历等关键信息&#xff0c;效率特别低且部分文件无法直接复制。于是&#xff0c;小编便写了简历解析处理的脚本&#xff0c;支持文件格式有&#xff1a;do…

MySQL流浪记(六)—— CONCAT到GROUP_CONCAT的沿途风景(图文详解)

本文中的案例如下&#xff0c;可以自己测试一下&#xff0c;有问题可以留言哦。 CREATE TABLE staff (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50),job_id INT, joindate DATE,salary DECIMAL(7,2) ); INSERT INTO staff(name,job_id,joindate,salary) VALUES (孙悟…

收藏!最新大数据产业地图 十大生态金矿百大公司起底【附下载】

来源&#xff1a;智东西人工智能的崛起&#xff0c;加速了大数据技术的应用落地。据中国大数据产业生态联盟调查显示&#xff0c;国内大数据企业年营业额4000万人民币以上的已经超过40%&#xff0c;这意味着&#xff0c;这些企业已经度过生存期&#xff0c;开始进入应用落地和品…

【一鸣离职,左晖去世】互联网老兵给大家的三个建议

2021年5月20日&#xff0c;除了娱乐圈的分分合合&#xff0c;互联网圈发生了两件大事&#xff1a; 1、字节跳动创始人张一鸣发布内部全员信&#xff0c;宣布卸任CEO一职。 2、贝壳发布讣告&#xff0c;公司创始人兼董事长左晖先生因疾病意外恶化于2021年5月20日…

MySQL流浪记(七)—— MySQL删除表数据

删除全表数据&#xff1a; delete from [表名]&#xff1a;会生成日志   truncate table [表名]&#xff1a;不会生成日志 删除表中部分数据 delete from [表名] where … &#xff1a;删除表中的部分数据只能使用delete where 不能使用truncate。 区别 从效果上看&#x…

Android布局

1. xml: 静态、较确定&#xff1b; 2. view&#xff1a;runtime动态改变&#xff1b; 3. Adapter&#xff1a;把datasource绑定到AdapterView的子类&#xff1b;如&#xff1a;从array获取数据&#xff0c;convert每项data为一个可以加到AdapterView layout 中的view&#xff1…

科大讯飞:让世界听见AI的声音

来源&#xff1a;华为怀揣着“让世界聆听我们的声音”的梦想&#xff0c;科大讯飞依托世界领先的核心技术&#xff0c;引领智能浪潮&#xff0c;服务亿万用户&#xff0c;从中国语音产业的拓荒者一跃成为世界人工智能产业的领军者&#xff0c;而最初科大讯飞把语音作为切入点却…

Linux中的chmod详解

chmod&#xff08;英文全拼&#xff1a;change mode&#xff09;命令是控制用户对文件的权限的命令。Linux/Unix 的文件调用权限分为三级 : 文件所有者&#xff08;Owner&#xff09;、用户组&#xff08;Group&#xff09;、其它用户&#xff08;Other Users&#xff09;。只有…

hdu 3999The order of a Tree

题目地址&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid3999 本题为简单二叉排序树&#xff0c;先按排序树创建树&#xff0c;然后先序遍历二叉树&#xff0c;输出的时候最后一个数字后面没有空格。 数组实现&#xff1a; #include<stdio.h> #include<strin…

【程序员薪资】2021年04月新鲜出炉,看看你拖后腿了吗?

程序员一直都是一个备受人们关注的群体。据IDC统计&#xff0c;全球约有1850万名程序员&#xff08;数据还在持续增长&#xff09;&#xff0c;中国占10%左右。随着近年全国互联网创业热潮的兴起&#xff0c;“互联网”、“云计算”以及“智能硬件”等领域发展迅速&#xff0c;…

CICC科普栏目|神经网络浅讲:从神经元到深度学习

图1 人脑神经网络来源&#xff1a; 计算机的潜意识摘要&#xff1a;神经网络是一门重要的机器学习技术。它是目前最为火热的研究方向–深度学习的基础。神经网络是一门重要的机器学习技术。它是目前最为火热的研究方向–深度学习的基础。学习神经网络不仅可以让你掌握一门强大的…

linux安装Redis(超详细,只要三分钟,每一步命令都有命令截图及运行截图)

Redis redis是一个key-value存储系统。和Memcached类似&#xff0c;它支持存储的value类型相对更多&#xff0c;包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash&#xff08;哈希类型&#xff09;。这些数据类型都支持push/pop、add/remove及取…

鬼才!用Python计算圆周率 π

目录 一、圆周率的历史发展 1、中国 2、印度 3、欧洲 二、用python计算圆周率 A货&#xff1a;什么&#xff01;你不会背圆周率&#xff08;鄙夷的眼神&#xff09; 3.1415926535 8979323846 26433... 桥哥&#xff1a;我会算呀 &#xff01;&#xff01;&#xff01; 一…

一个简单WCF项目的建立 by wsz

由于搬砖的需要&#xff0c;不得不学一点与WCF有关的东西。具体是因为前几周在64位环境下写的一个dll不能被集成到合作伙伴的32位工程中&#xff0c;但是要修改文件实在是划不来&#xff0c;一个压缩后600M的文件搬来搬去的也是让人蛋碎。因此想到了WCF。这样只要提供一个servi…

大数据常见问题:数据倾斜

offer收割系列介绍&#xff1a; 1、分享桥哥本人或小伙伴在面试大厂时遇到的真题&#xff0c;并给出参考答案&#xff01;&#xff01;如果能帮到大家&#xff0c;点赞、收藏、评论是对我最大的支持&#xff01;&#xff01; 2、涉及岗位&#xff1a;主要为大数据开发、数据仓…

一图看懂新一代人工智能知识体系大全

来源&#xff1a;财经头条摘要&#xff1a;人工智能的发展离不开基础支持层和技术层&#xff0c;基础支持层包括大数据、计算力和算法&#xff1b;技术层包括计算机视觉、语音识别和自然语言处理。人工智能的技术本质是什么&#xff0c;本文会详细分析。人工智能的发展离不开基…

Redis是单线程为什么还那么快?

Redis为什么还那么快 基于内存   Redis完全基于内存&#xff0c;绝大部分请求是纯粹的内存操作&#xff0c;Redis将数据存储在内存中&#xff0c;读写数据的时候不会受到硬盘I/O速度的限制&#xff08;内存速度为什么比硬盘快&#xff1f;&#xff09;&#xff0c;类似于Hash…