Android学习随笔(4)------活动的启动模式

学习流程来自《第一行代码》(第二版)

活动的启动模式

启用模式有4种 :
standard
singleTop
singleTask
singleInstance

在AndroidManifest.xml中通过给activity标签的android:launchMode属性来选择启动模式。

standard

是默认的启动模式,每次启动都会创建该活动的一个新的实例,并把它加入到返回栈中。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.first_layout);    // 给当前活动加载一个布局
    Log.d("FirstActivity",this.toString());     // 输出当前活动的内存
    Button button1 = (Button) findViewById(R.id.button_1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v){
        Intent(FirstActivity.this,FirstActivity.class);    //活动的standard启动模式
        startActivity(intent);
        }
    });
}

Exler
从我们输出的日志中可以看到,每次点击button 都会打开一个新的Activity实例。

Exler

singleTop

返回栈栈顶已经存在此活动的时候,可直接使用它,不会再重新创建新的Activity实例。
在AndroidManifest.xml文件中 :

    <activity
        android:name=".FirstActivity"
        android:launchMode="singleTop"
        android:label="This is FirstActivity">
        <!--
            name(注册哪个活动)=缩写(外层标签package)
            launchMode 活动的启动模式
                singleTop返回栈栈顶已经是该活动 则直接使用它   不是则重新创建
                singleTask该应用的返回栈中存在则取出来用,不创建新Activity,且在此活动之上的所有活动出栈
                singleInstance启用一个新的返回栈来管理这个活动 可以做到多个程序共享此返回栈
                label=标题栏的text还会成为启动器(Launcher)中应用程序显示的名称(应用的名称)
        -->
        <intent-filter> <!-- 不是主活动不需要配置 -->
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

再在FirstActivity中添加一个button,这个button用于打开SecondActivty,在SecondActivity中添加一个button用于打开FirstActivity
FirstActivity.java

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);    // 给当前活动加载一个布局
        Log.d("FirstActivity",this.toString());     // 输出当前活动的内存
        Button button1 = (Button) findViewById(R.id.button_1);
        button1.setOnClickListener(new View.OnClickListener() {    
            @Override
            public void onClick(View v){
            Intent intent = new      Intent(FirstActivity.this,FirstActivity.class);    //活动的standard启动模式
            startActivity(intent);
            }
        });
        Button button2 = (Button) findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(FirstActivity.this,SecondActivity.class);    //活动的singleTop非栈顶活动  FirstActivity back SecondActivity back FirstActivity 有n个FirstActivity就要back 2n次
                startActivity(intent);
            }
        });
    }

SecondActivity.java :

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_layout);
        Log.d("SecondActivity",this.toString());
        Button button2 = (Button)findViewById(R.id.button_3);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(SecondActivity.this, FirstActivity.class);
                startActivity(intent);
            }
        });
    }

运行,此时点击button1 :

Exler

无论我们点多少下都只会停在当前FirstActivity实例。
但当我们点击button2,并且点击SecondActivity中的button返回FirstActivity时 :

Exler

发现重新创建了一个新的FirstActivity实例。

Exler

singleTask

singleTop模式下我们从SecondActivity返回FirstActivity是新建了一个实例,但在此模式下每次启动该活动是系统会首先检查返回栈中是否存在此活动,存在就调用,不存在就创建。
更改AndroidManifest.xml :

<activity
    android:name=".FirstActivity"
    android:launchMode="singleTask"
    android:label="This is FirstActivity">

Exler

当我们从SecondActivity返回FirstActivity时并没有创建新的实例,而是调用了返回栈中的FirstActivity,并且SecondActivity从返回栈中出栈。

Exler

singleInstance

指定为singleInstance模式的活动会启用一个新的返回栈来管理这个活动.(在这种模式下会有一个单独的返回栈来管理这个活动,不管是哪个应用来访问这个活动,都公用一个返回栈,也就解决了共享活动实例的问题。)

修改AndroidManifest.xml :

<activity android:name=".SecondActivity"
    android:launchMode="singleInstance"
    >
    <intent-filter>
        <action android:name="com.example.yezhou.activitytest.ACTION_START" />
        <category android:name="android.intent.category.DEFAULT" /> <!-- 只有<action><category>同时匹配上Intent中指定的action和category时这个活动才能响应该Intent -->
        <category android:name="com.example.yezhou.activitytest.MY_CATEGORY" />
    </intent-filter>
</activity>

FirstActiviy.java :

super.onCreate(savedInstanceState);
setContentView(R.layout.first_layout);    // 给当前活动加载一个布局
Log.d("FirstActivity","Task id is "+getTaskId());    // 打印当前返回栈的id
Button button1 = (Button) findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v){
        Intent intent = new Intent(FirstActivity.this,FirstActivity.class);    //活动的standard启动模式
        startActivity(intent);
    }
});
Button button2 = (Button) findViewById(R.id.button_2);
button2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
         startActivity(intent);
    }
});

SecondActivity.java :

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.second_layout);
    Log.d("SecondActivity","Task id is "+getTaskId());
    Button button2 = (Button)findViewById(R.id.button_3);
    button2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(SecondActivity.this,ThirdActivity.class);
            startActivity(intent);
            }
        });
    }

ThirdActivity.java :

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.third_layout);
        Log.d("ThirdActivity","Task id is " + getTaskId());    // 会返回FirstActivity(只会返回相同栈)只有当此栈为空时 才会返回在其他栈中的活动(SecondActivity在其他栈中)
}

具体的实现是点击FirstActivity中的button2,打开SecondActivity,再点击button3,打开ThirdActivity,按3次back键。

Exler
可以发现FirstActivity与ThirdActivity是在同一个返回栈中的,并且第一次back返回到了FirstActivity,再一次就返回到了SecondActivity,最后是退出程序。

Exler


知晓当前在哪一个活动

新建一个BaseActivity类,继承自AppCompatActivity。

public class BaseActivity extends AppCompatActivity {    //知晓当前是在哪一个活动
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity",getClass().getSimpleName());
    }
}

使所有的活动继承自BaseActivity。
运行,打开FirstActivity,SecondActivity,ThirdActivity

Exler
这样类名就被打印出来了。

随时随地推出程序

当我们想要推出一个程序多次按下back是一件很麻烦的事情。
用一个专门的集合类对所有的活动进行管理就可以了。
新建一个ActivityCollector类 :

public class ActivityCollector {
    public static List<Activity> activities = new ArrayList<>();
    public static void addActivity(Activity activity) {
        activities.add(activity);
    }

    public static void removeActivity(Activity activity) {
        activities.remove(activity);
    }

    public static void finishAll() {
        for (Activity activity : activities) {
            if (!activity.isFinishing()) {
                activity.finish();
            }
        }
    }
}

在活动管理器中创建一个List来暂存活动,有增加,移除,全部销毁的功能。
修改BaseActivity :

public class BaseActivity extends AppCompatActivity {    //知晓当前是在哪一个活动
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity",getClass().getSimpleName());
        ActivityCollector.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
    }
}

每当onCreate一个Activity实例就把它加到ActivityCollector的List里面,每当销毁一个活动就把它从List中移除。

在ThirdActivity中实现直接退出程序。

ThirdActivity.java :

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.third_layout);
    Button button3 = (Button)findViewById(R.id.Button_4);
    button3.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            ActivityCollector.finishAll();
            android.os.Process.killProcess(android.os.Process.myPid());    //杀掉当前程序的进程,确保程序完全退出
        }
    });
}

当在ThirdActivity时点击按钮button4,即可直接退出程序。

Exler


启动活动的最佳写法

在想要打开的活动中提供一个静态方法,

public static void actionStart(Context context, String data1, String data2) {    // 若打开SecondActivity需要传入两个参数的最佳写法  从FirstActivity调用
    Intent intent = new Intent(context,SecondActivity.class);
    intent.putExtra("param1",data1);
    intent.putExtra("param2",data2);
    context.startActivity(intent);
}

从上一个界面调用这个方法。

SecondActivity.actionStart(FirstActivity.this,"data1","data2");

这样写可以一目了然的了解到两个Activity之间的关系。


参考 :
示意图来源 :http://blog.csdn.net/acm_th/article/details/48058761


此博文为个人学习笔记,仅供个人学习使用,希望对大家有帮助。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值