源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

详解Android开发中Activity的四种launchMode

  • 时间:2021-12-06 21:53 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:详解Android开发中Activity的四种launchMode
Activity栈主要用于管理Activity的切换。当使用Intent跳转至某个目标Activity,需要根据目标Activity的加载模式来加载。 Activity一共有以下四种launchMode: 1.standard:默认,每次使用Intent跳转到目标Activity时都创建一个新的实例。坏处是每次进入都要创建新的实例,执行OnCreate方法。 [img]http://files.jb51.net/file_images/article/201603/201638150942001.jpg?201628151031[/img] 2.singleTop:如果要跳转的目标Activity正好在task的顶部(说明当前肯定不在目标task里,例如我在微信首页,然后想使用Intent跳转到InnoXYZ应用的首页,那么加入InnoXYZ首页正好在InnoXYZ的task顶部,就直接跳转而不会创建实例),那么就直接跳转过去而不会创建新的。(例子,当前在Home Screen, 收到一条微信首页的推送,而此时task栈里的微信task里的Activity栈里的最顶部正好就是微信首页,那么点击推送就直接进入该实例而不会创建新的实例) [img]http://files.jb51.net/file_images/article/201603/201638151101876.jpg?201628151114[/img] 3.singleTask:会在一个新的task中产生这个实例,以后每次调用都会使用这个,不会去产生新的实例了。 4.singleInstance:是其所在栈的唯一activity,它会每次都被重用。 launchMode在多个Activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity实例,是否重用已存在的Activity实例,是否和其他Activity实例公用一个task里。这里简单介绍一下task的概念,task是一个具有栈结构的对象,一个task可以管理多个Activity,启动一个应用,也就创建一个与之对应的task。 我们可以在AndroidManifest.xml配置<activity>的android:launchMode属性为以上四种之一即可。 下面我们结合实例一一介绍这四种lanchMode: [b]1.standard [/b]standard模式是默认的启动模式,不用为<activity>配置android:launchMode属性即可,当然也可以指定值为standard。 我们将会一个Activity,命名为FirstActivity,来演示一下标准的启动模式。FirstActivity代码如下: standard模式是默认的启动模式,不用为<activity>配置android:launchMode属性即可,当然也可以指定值为standard。 我们将会一个Activity,命名为FirstActivity,来演示一下标准的启动模式。FirstActivity代码如下:
package com.scott.launchmode; 
 
import android.app.Activity; 
import android.content.Intent; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
 
public class FirstActivity extends Activity { 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.first); 
    TextView textView = (TextView) findViewById(R.id.textView); 
    textView.setText(this.toString()); 
    Button button = (Button) findViewById(R.id.button); 
    button.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
        Intent intent = new Intent(FirstActivity.this, FirstActivity.class); 
        startActivity(intent); 
      } 
    }); 
  } 
} 
我们FirstActivity界面中的TextView用于显示当前Activity实例的序列号,Button用于跳转到下一个FirstActivity界面。 然后我们连续点击几次按钮,将会出现下面的现象: [img]http://files.jb51.net/file_images/article/201603/201638151308968.gif?201628151317[/img] [img]http://files.jb51.net/file_images/article/201603/201638151209028.gif?201628151224[/img] [img]http://files.jb51.net/file_images/article/201603/201638151327302.gif?201628151335[/img] 我们注意到都是FirstActivity的实例,但序列号不同,并且我们需要连续按后退键两次,才能回到第一个FristActivity。standard模式的原理如下图所示: [img]http://files.jb51.net/file_images/article/201603/201638151352070.gif?20162815140[/img] 如图所示,每次跳转系统都会在task中生成一个新的FirstActivity实例,并且放于栈结构的顶部,当我们按下后退键时,才能看到原来的FirstActivity实例。 这就是standard启动模式,不管有没有已存在的实例,都生成新的实例。 [b]2.singleTop [/b]我们在上面的基础上为<activity>指定属性android:launchMode="singleTop",系统就会按照singleTop启动模式处理跳转行为。我们重复上面几个动作,将会出现下面的现象: [img]http://files.jb51.net/file_images/article/201603/201638151417517.gif?201628151425[/img] [img]http://files.jb51.net/file_images/article/201603/201638151838515.gif?201628151850[/img] [img]http://files.jb51.net/file_images/article/201603/201638151858469.gif?20162815199[/img] 我们看到这个结果跟standard有所不同,三个序列号是相同的,也就是说使用的都是同一个FirstActivity实例;如果按一下后退键,程序立即退出,说明当前栈结构中只有一个Activity实例。singleTop模式的原理如下图所示: [img]http://files.jb51.net/file_images/article/201603/201638151434213.gif?201628151443[/img] 正如上图所示,跳转时系统会先在栈结构中寻找是否有一个FirstActivity实例正位于栈顶,如果有则不再生成新的,而是直接使用。也许朋友们会有疑问,我只看到栈内只有一个Activity,如果是多个Activity怎么办,如果不是在栈顶会如何?我们接下来再通过一个示例来证实一下大家的疑问。 我们再新建一个Activity命名为SecondActivity,如下:
package com.scott.launchmode; 
 
import android.app.Activity; 
import android.content.Intent; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
 
public class SecondActivity extends Activity { 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.second); 
    TextView textView = (TextView) findViewById(R.id.textView); 
    textView.setText(this.toString()); 
    Button button = (Button) findViewById(R.id.button); 
    button.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
        Intent intent = new Intent(SecondActivity.this, FirstActivity.class); 
        startActivity(intent);        
      } 
    }); 
  } 
} 
然后将之前的FirstActivity跳转代码改为:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class); 
startActivity(intent); 
  是的,FirstActivity会跳转到SecondActivity,SecondActivity又会跳转到FirstActivity。演示结果如下: [img]http://files.jb51.net/file_images/article/201603/201638151515857.gif?201628151524[/img] [img]http://files.jb51.net/file_images/article/201603/201638151530469.gif?201628151541[/img] [img]http://files.jb51.net/file_images/article/201603/201638151550299.gif?201628151557[/img] 我们看到,两个FirstActivity的序列号是不同的,证明从SecondActivity跳转到FirstActivity时生成了新的FirstActivity实例。原理图如下: [img]http://files.jb51.net/file_images/article/201603/201638151628506.gif?201628151637[/img] [img]http://files.jb51.net/file_images/article/201603/201638151647962.gif?201628151654[/img] [img]http://files.jb51.net/file_images/article/201603/201638151701357.gif?20162815178[/img] [img]http://files.jb51.net/file_images/article/201603/201638151723858.gif?201628151736[/img] 我们看到,当从SecondActivity跳转到FirstActivity时,系统发现存在有FirstActivity实例,但不是位于栈顶,于是重新生成一个实例。 这就是singleTop启动模式,如果发现有对应的Activity实例正位于栈顶,则重复利用,不再生成新的实例。 [b]3.singleTask [/b]在上面的基础上我们修改FirstActivity的属性android:launchMode="singleTask"。演示的结果如下: 我们注意到,在上面的过程中,FirstActivity的序列号是不变的,SecondActivity的序列号却不是唯一的,说明从SecondActivity跳转到FirstActivity时,没有生成新的实例,但是从FirstActivity跳转到SecondActivity时生成了新的实例。singleTask模式的原理图如下图所示: [img]http://files.jb51.net/file_images/article/201603/201638151803687.gif?201628151820[/img] 在图中的下半部分是SecondActivity跳转到FirstActivity后的栈结构变化的结果,我们注意到,SecondActivity消失了,没错,在这个跳转过程中系统发现有存在的FirstActivity实例,于是不再生成新的实例,而是将FirstActivity之上的Activity实例统统出栈,将FirstActivity变为栈顶对象,显示到幕前。也许朋友们有疑问,如果将SecondActivity也设置为singleTask模式,那么SecondActivity实例是不是可以唯一呢?在我们这个示例中是不可能的,因为每次从SecondActivity跳转到FirstActivity时,SecondActivity实例都被迫出栈,下次等FirstActivity跳转到SecondActivity时,找不到存在的SecondActivity实例,于是必须生成新的实例。但是如果我们有ThirdActivity,让SecondActivity和ThirdActivity互相跳转,那么SecondActivity实例就可以保证唯一。 这就是singleTask模式,如果发现有对应的Activity实例,则使此Activity实例之上的其他Activity实例统统出栈,使此Activity实例成为栈顶对象,显示到幕前。 [b]4.singleInstance [/b]这种启动模式比较特殊,因为它会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其他Activity实例进入。 我们修改FirstActivity的launchMode="standard",SecondActivity的launchMode="singleInstance",由于涉及到了多个栈结构,我们需要在每个Activity中显示当前栈结构的id,所以我们为每个Activity添加如下代码:
TextView taskIdView = (TextView) findViewById(R.id.taskIdView); 
taskIdView.setText("current task id: " + this.getTaskId()); 
然后我们再演示一下这个流程: [img]http://files.jb51.net/file_images/article/201603/201638151951749.gif?20162815202[/img] [img]http://files.jb51.net/file_images/article/201603/201638152011045.gif?201628152020[/img] 我们发现这两个Activity实例分别被放置在不同的栈结构中,关于singleInstance的原理图如下: [img]http://files.jb51.net/file_images/article/201603/201638152030493.gif?201628152037[/img] 我们看到从FirstActivity跳转到SecondActivity时,重新启用了一个新的栈结构,来放置SecondActivity实例,然后按下后退键,再次回到原始栈结构;图中下半部分显示的在SecondActivity中再次跳转到FirstActivity,这个时候系统会在原始栈结构中生成一个FirstActivity实例,然后回退两次,注意,并没有退出,而是回到了SecondActivity,为什么呢?是因为从SecondActivity跳转到FirstActivity的时候,我们的起点变成了SecondActivity实例所在的栈结构,这样一来,我们需要“回归”到这个栈结构。 如果我们修改FirstActivity的launchMode值为singleTop、singleTask、singleInstance中的任意一个,流程将会如图所示: [img]http://files.jb51.net/file_images/article/201603/201638152048827.gif?201628152056[/img] singleInstance启动模式可能是最复杂的一种模式,为了帮助大家理解,我举一个例子,假如我们有一个share应用,其中的ShareActivity是入口Activity,也是可供其他应用调用的Activity,我们把这个Activity的启动模式设置为singleInstance,然后在其他应用中调用。我们编辑ShareActivity的配置:
<activity android:name=".ShareActivity" android:launchMode="singleInstance"> 
  <intent-filter> 
    <action android:name="android.intent.action.MAIN" /> 
    <category android:name="android.intent.category.LAUNCHER" /> 
  </intent-filter> 
  <intent-filter> 
    <action android:name="android.intent.action.SINGLE_INSTANCE_SHARE" /> 
    <category android:name="android.intent.category.DEFAULT" /> 
  </intent-filter> 
</activity> 
  然后我们在其他应用中这样启动该Activity:
Intent intent = new Intent("android.intent.action.SINGLE_INSTANCE_SHARE"); 
startActivity(intent); 
当我们打开ShareActivity后再按后退键回到原来界面时,ShareActivity做为一个独立的个体存在,如果这时我们打开share应用,无需创建新的ShareActivity实例即可看到结果,因为系统会自动查找,存在则直接利用。大家可以在ShareActivity中打印一下taskId,看看效果。关于这个过程,原理图如下: [img]http://files.jb51.net/file_images/article/201603/201638152118151.gif?201628152126[/img]
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部