Android之Activity LaunchMode
背景:
在众多Activity开发中,有可能是自己应用之间的Activity跳转,可能希望跳转到原来某个Activity实例,而不是产生大量重复的Activity实例。
这种需求需要通过配置Activity的LaunchMode来实现。
Activity有四种加载模式:
1.standard(标准模式,此项是默认的加载模式)
在此种模式情况下的Activity会每次都生成新的实例
我们首先定义了A这个Activity,然后它的内容如下:
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.TextView; public class A extends Activity implements OnClickListener { private TextView textView01; private Button btn01; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_a); textView01 = (TextView) findViewById(R.id.tv_01); btn01 = (Button) findViewById(R.id.button1); btn01.setOnClickListener(this); //获取当前Activity的任务栈ID int taskID = A.this.getTaskId(); //获取当前Activity实例的详细信息 String objectMsg = A.this.toString(); //将信息输出到屏幕上 textView01.setText("当前任务栈ID:" + taskID + "\r\n" + "当前Activity实例信息:"+ objectMsg); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button1: //开始跳转Activity Intent intent = new Intent(A.this, A.class); startActivity(intent); break; default: break; } } }
观察发现:这三个A同属于一个任务栈,因为栈的ID都相同,但是他们的实例名称都不一样,说明这个任务栈中现在已经存在了三个不同的A实例;如果此时点击手机上的《返回》按键,那么需要连续点击三次才能退出程序。
将以上总结为流程图如下:
2.singleTop模式
在此种模式下,
如果A在任务栈顶,那么A跳转到A将不生成新的实例,直接跳转到现在的栈顶A;
如果A不在任务栈顶,那么其他的Activity去跳转到A,将生成新的A实例;
我们在代码中定义两个Activity,分别是A和B,以上是这两个Activity的定义,其中A的launchMode属性被设置为singleTop。
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.TextView; public class A extends Activity implements OnClickListener { private TextView textView01; private Button btn01; private Button btn02; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_a); textView01 = (TextView) findViewById(R.id.tv_01); btn01 = (Button) findViewById(R.id.button1); btn01.setOnClickListener(this); btn02 = (Button) findViewById(R.id.button2); btn02.setOnClickListener(this); //获取当前Activity的任务栈ID int taskID = A.this.getTaskId(); //获取当前Activity实例的详细信息 String objectMsg = A.this.toString(); //将信息输出到屏幕上 textView01.setText("当前任务栈ID:" + taskID + "\r\n" + "当前Activity实例信息:"+ objectMsg); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button1: //A--->A Intent intent01 = new Intent(A.this, A.class); startActivity(intent01); break; case R.id.button2: //A---->B Intent intent02 = new Intent(A.this, B.class); startActivity(intent02); break; default: break; } } }
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.TextView; public class B extends Activity implements OnClickListener { private TextView textView01; private Button btn01; private Button btn02; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_a); textView01 = (TextView) findViewById(R.id.tv_01); btn01 = (Button) findViewById(R.id.button1); btn01.setOnClickListener(this); btn02 = (Button) findViewById(R.id.button2); btn02.setOnClickListener(this); //获取当前Activity的任务栈ID int taskID = B.this.getTaskId(); //获取当前Activity实例的详细信息 String objectMsg = B.this.toString(); //将信息输出到屏幕上 textView01.setText("当前任务栈ID:" + taskID + "\r\n" + "当前Activity实例信息:"+ objectMsg); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button1: //B--->A Intent intent01 = new Intent(B.this, A.class); startActivity(intent01); break; case R.id.button2: //B---->B Intent intent02 = new Intent(B.this, B.class); startActivity(intent02); break; default: break; } } }
在程序运行后,我们点击跳转到A,界面不会有任何变化,说明当A在任务栈顶时,你发送跳转到A的Intent,那么这个Intent会发送给栈顶的A实例;
以下三张图片展示的流程是A---->B---->A:
观察发现:这三个Activity实例是不同的实例,但是他们同属一个任务栈,因为他们的任务栈ID相同;我们这里可以很明显的发现,当B在栈顶的时候,跳转到A,会生成新的A实例。
将以上总结为流程图如下:
3.singleTask模式
在此种模式,任务栈中只能有一个A实例,不管它在任务栈的什么位置;
这里我们应当注意:当A在栈顶时,直接跳转到A实例;当A不在栈顶时,将会发生的事情是,在A之上的所有Activity实例被弹出任务栈,直至A到达栈顶。
本次仍然沿用上一次的代码,只是在manifest中将A的launchMode配置为singleTask,在B中添加一个Button跳转到C,然后C中只有一个按钮,这个按钮的作用是跳转到A。
以下四张图片展示了A---->B---->C---->A:
观察以上结果我们可以发现:总共有三个实例,A、B、C各一个,当C在栈顶的时候,跳转到A,我们会返现,Intent会直接发送到栈底的A实例,并且将B、C两个实例弹栈。
将以上总结为流程图如下:
4.singleInstance模式
此Activity加载模式是为了解决这样一类问题:
在同一App中,当有一个Activity需要被多个Activity共享(即是多个Activity可以跳转到这个Activity),那么我们肯定希望此Activity长期处于Alive状态,并且是同一个实例(这样更能节省手机资源),但是同一app中,所有的Activity实例都在同一个任务栈中,我们会发现,经常性的压栈和弹栈使我们无法确定此Activity会在什么时候被弹栈销毁掉了,这个时候我们可以通过将此Activity的加载模式设置为singleInstance来满足这样的需求,当设置为此模式后,此Activity被单独在一个任务栈中维护,而不受主任务栈中频繁的压栈和弹栈操作的影响。
其实写到这个地方我觉得文字的表现力始终不及图形,首先我们来看一下,将B的launchmode设置为singleInstance,然后再来分析以下的图片结果:
分析以上结果我们会发现:B实例的任务栈ID,与A实例所在的任务栈ID不相同,说明他们处于不同的任务栈中;
并且这只是一种情况,实际这里有好几种情况,我将其总结到下面这张图中,希望能够对读者真的产生帮助;
写这篇文章的时候我想起了古人的一句话,纸上得来终觉浅,绝知此事要躬行,网上流行一篇讲LaunchMode的文章,全是用蓝色的图解,实际上我很受益于这篇文章,但是当我写这篇文章的时候我发现“我认为以前的我完全懂了”是不全面的,我对LauchMode似乎有了新的认识,感谢实践!!!
下面来本篇最后一张我绘的流程图:
例行公事,把代码链接放这里:
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。