Android APK开发基础—— 四大组件之Activity

Activity的启动模式

启动模式的设置

方式一:AndroidMenifest中设置:

            android:name=".TestActivity" Activity类名  

            android:allowTaskReparenting="true" 允许应用外的请求启动此Activity  

            android:configChanges="screenSize" 设置屏幕的一些参数,例如取消横竖屏切换  

            android:launchMode="singleTask" Activity启动模式  

            android:taskAffinity="com.abc.task" /> 设置Activity所属栈名

方式二:代码中进行设置:

Intent intent = new Intent();  

        intent.setClass(this,TestActivity.class);  

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  

        startActivity(intent);  

 

四种启动模式

Activity的任务栈

按照是否可见分:前台任务栈、后台任务栈

 

检测Activity任务栈

出现界面跳转异常时,可以导出activity任务栈。

adb shell dumpsys activity activities >e:1

 结果如下:

 ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
  Stack #1: 前台任务栈
  。。。。

    Running activities (most recent first):
      TaskRecord{b020cad #2036 A=com.zxcn.imai.smart U=0 StackId=1 sz=5}
        Run #6: ActivityRecord{fee230c u0 com.zxcn.imai.smart/.activity.ecg.EcgResultActivity t2036}
        Run #5: ActivityRecord{a0938c8 u0 com.zxcn.imai.smart/.activity.ecg.EcgMainActivity t2036}
        Run #4: ActivityRecord{8dfaaa2 u0 com.zxcn.imai.smart/.activity.common.FunctionChoseActivity t2036}
        Run #3: ActivityRecord{f8265ec u0 com.zxcn.imai.smart/.activity.common.RoleChoseActivity t2036}
        Run #2: ActivityRecord{a8a4be2 u0 com.zxcn.imai.smart/.activity.common.MainActivity t2036}
      TaskRecord{feb4ae4 #1911 A=com.huawei.appmarket U=0 StackId=1 sz=2}
        Run #1: ActivityRecord{7447718 u0 com.huawei.appmarket/.service.search.view.SearchActivity t1911}
        Run #0: ActivityRecord{5ed9d62 u0 com.huawei.appmarket/.MarketActivity t1911}

    mResumedActivity: ActivityRecord{fee230c u0 com.zxcn.imai.smart/.activity.ecg.EcgResultActivity t2036}
    mLastPausedActivity: ActivityRecord{a0938c8 u0 com.zxcn.imai.smart/.activity.ecg.EcgMainActivity t2036}

  Stack #0:  后台任务栈
  。。。

    Running activities (most recent first):
      TaskRecord{823308a #1857 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
        Run #1: ActivityRecord{481e6fb u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1857}
      TaskRecord{5433a2b #1910 A=com.android.systemui U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{19b0e88 u0 com.android.systemui/.recents.RecentsActivity t1910}

 

四种启动模式

表现:

前台任务栈 :TaskRecord是否增加,TaskRecord的出栈入栈

1.standard模式

standard是Activity默认的启动模式,在不指定Activity启动模式的情况下,所有Activity使用的都是standard模式。

在standard模式下,每当启动一个新的Activity,它就会进入前台任务栈,并处于栈顶的位置,对于使用standard模式的Activity,系统不会判断该Activity在栈中是否存在,每次启动都会创建一个新的实例。下图所示的是standard启动模式下Activity在栈中的存放情况:

Android APK开发基础—— 四大组件之Activity_第1张图片

从图中我们可以看出,在standard启动模式下Activity01最先进栈,其次是Activity02,最后是Activity03;出栈时,Activity03最先出栈,其次是Activity02,最后是Activity01,满足“先进后出”的原则。

2.singleTop模式

singleTop模式与standard类似,不同的是,当启动的Activity已经位于栈顶时,则直接使用它不创建新的实例。如果启动的Activity没有位于栈顶时,则创建一个新的实例位于栈顶。下图所示的是singleTop模式下Activity在栈中的存放情况:

Android APK开发基础—— 四大组件之Activity_第2张图片

从图中我们可以看出,当前栈顶中的元素是Activity03,如果再次启动的界面还是Activity03,则复用当前栈顶的Activity实例,如果再次启动的界面没有位于栈顶,则会重新创建一个实例。

3.singleTask模式

如果希望Activity在整个应用程序中只存在一个实例,可以使用singleTask模式,当Activity的启动模式指定为 singleTask,每次启动该Activity时,系统首先会检查栈中是否存在该Activity的实例,如果发现已经存在则直接使用该实例,并将当前Activity之上的所有Activity出栈,如果没有发现则创建一个新的实例。下图所示的是singleTask模式下的Activity在栈中的存放情况:

Android APK开发基础—— 四大组件之Activity_第3张图片

从图中可以看出,当再次启动Activity02时,并没有创建新的实例,而是将Activity03实例移除,复用Activity02 实例,这就是singleTask模式,让某个Activity在当前栈中只存在一个实例。

4.singleInstance模式

在程序开发过程中,如果需要Activity在整个系统中都只有一个实例,这时就需要用到singleInstance模式。不同于以上介绍的三种模式,指定为singleInstance模式的Activity会启动一个新的任务栈来管理这个Activity。

singleInstance模式加载Activity时,无论从哪个任务栈中启动该Activity,只会创建一个Activity实例,并且会使用一个全新的任务栈来装载该Activity实例。采用这种模式启动Activity会费为一下两种情况:

Android APK开发基础—— 四大组件之Activity_第4张图片

第一种:如果要启动的Activity不存在,系统会创建一个新的任务栈,在创建该Activity的实例,并把该Activity加入栈顶,如下图所示:

第二种::如果要启动的Activity已经存在,无论位于哪个应用程序或者哪个任务栈中,系统都会把该Activity所在的任务栈转到前台,从而使该Activity显示出来。

至此,Activity的四种启动模式已经讲解完成,在实际开发中,需要根据实际情况来选择合适的启动模式。

 

Example

 以下是ExampleActivity分别跳转到Activity21,Activity22,Activity22,Activity24的前台任务栈的情况:








Stack #1:
Running activities (most recent first):
      TaskRecord{15e9dd7 #2552 A=com.zxcn.test U=0 StackId=1 sz=2}
        Run #1: ActivityRecord{f6cf2a8 u0 com.zxcn.test/com.hy.base.androidbase.component.activity.ExampleActivity t2552}
        Run #0: ActivityRecord{4aae6c4 u0 com.zxcn.test/com.hy.app.activity.MainActivity t2552}

Running activities (most recent first):
      TaskRecord{15e9dd7 #2552 A=com.zxcn.test U=0 StackId=1 sz=3}
        Run #2: ActivityRecord{dc87d76 u0 com.zxcn.test/com.hy.base.androidbase.component.activity.Activity21 t2552}
        Run #1: ActivityRecord{f6cf2a8 u0 com.zxcn.test/com.hy.base.androidbase.component.activity.ExampleActivity t2552}
        Run #0: ActivityRecord{4aae6c4 u0 com.zxcn.test/com.hy.app.activity.MainActivity t2552}

Running activities (most recent first):
      TaskRecord{e4e8a8b #2553 A=com.zxcn.test U=0 StackId=1 sz=1}
        Run #2: ActivityRecord{8298768 u0 com.zxcn.test/com.hy.base.androidbase.component.activity.Activity22 t2553}
      TaskRecord{15e9dd7 #2552 A=com.zxcn.test U=0 StackId=1 sz=2}
        Run #1: ActivityRecord{f6cf2a8 u0 com.zxcn.test/com.hy.base.androidbase.component.activity.ExampleActivity t2552}
        Run #0: ActivityRecord{4aae6c4 u0 com.zxcn.test/com.hy.app.activity.MainActivity t2552}


Running activities (most recent first):
      TaskRecord{15e9dd7 #2552 A=com.zxcn.test U=0 StackId=1 sz=3}
        Run #2: ActivityRecord{d33eed6 u0 com.zxcn.test/com.hy.base.androidbase.component.activity.Activity23 t2552}
        Run #1: ActivityRecord{f6cf2a8 u0 com.zxcn.test/com.hy.base.androidbase.component.activity.ExampleActivity t2552}
        Run #0: ActivityRecord{4aae6c4 u0 com.zxcn.test/com.hy.app.activity.MainActivity t2552}

Running activities (most recent first):
      TaskRecord{15e9dd7 #2552 A=com.zxcn.test U=0 StackId=1 sz=3}
        Run #2: ActivityRecord{349ca74 u0 com.zxcn.test/com.hy.base.androidbase.component.activity.Activity24 t2552}
        Run #1: ActivityRecord{f6cf2a8 u0 com.zxcn.test/com.hy.base.androidbase.component.activity.ExampleActivity t2552}
        Run #0: ActivityRecord{4aae6c4 u0 com.zxcn.test/com.hy.app.activity.MainActivity t2552}

 

Activity的生命周期的管理

典型情况下的生命周期

package com.hy.base.androidbase.component.activity;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.hy.app.base1.BaseActivity;
import com.hy.app.component.R;


public class ExampleActivity extends BaseActivity {
    int code = 1;

    /**
     * **********************************************************************
     * 典型情况下的生命周期
     * **********************************************************************
     * */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);

        Log.v("060" ,"ExampleActivity onCreate");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.v("060" ,"ExampleActivity onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.v("060" ,"ExampleActivity onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.v("060" ,"ExampleActivity onPause");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.v("060" ,"ExampleActivity onRestart");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.v("060" ,"ExampleActivity onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.v("060" ,"ExampleActivity onDestroy");
    }
 
}

 

非典型情况下的生命周期

情况1:资源相关的系统配置发生改变导致Acitivity被杀死并重新创建。

Caution: 你的Activity会在每次旋转屏幕时被destroyed与recreated。当屏幕改变方向时,系统会Destory与Recreate前台的activity,因为屏幕配置被改变,你的Activity可能需要加载另一些替代的资源(例如layout).

情况2:系统内存不足导致低优先级的Activity被杀死

   /**
     * **********************************************************************
     * 非典型情况下的生命周期
     * **********************************************************************
     * */
    //保证一定在活动被回收之前调用,保存该活动的数据。
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        String string = "activity 被系统回收了怎么办?";
        outState.putString("Activity", string);
    }

    //恢复onSaveInstanceState保存的数据,官方建议采用该方案
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);

        String tempData = savedInstanceState.getString("Activity");
        Toast.makeText(ExampleActivity.this,tempData,Toast.LENGTH_SHORT).show();
    }

 AndroidManifest.xml

android:name="com.hy.base.androidbase.component.activity.ExampleActivity" android:theme="@style/AppTheme" android:configChanges="orientation|screenSize"/>

 

Activity切换

1、切换时数据传递

1.1 使用Intent的putExtra传递

第一个Activity中

//创建意图对象

 Intent intent = new Intent(this,TwoActivity.class);

 //设置传递键值对

 intent.putExtra("data",str);

 //激活意图

 startActivity(intent);

 

第二个Activity中

// 获取意图对象

 Intent intent = getIntent();

 //获取传递的值

 String str =intent.getStringExtra("data");

 //设置值

 tv.setText(str);

 

1.2 使用Intent的Bundle传递

第一个Activity中

//创建意图对象

 Intent intent = newIntent(MainActivity.this,TwoActivity.class);

 //用数据捆传递数据

 Bundle bundle = new Bundle();

 bundle.putString("data", str);

 //把数据捆设置改意图

 intent.putExtra("bun", bundle);

 //激活意图

 startActivity(intent);

 

第二个Activity

//获取Bundle

 Intent intent = getIntent();

 Bundle bundle =intent.getBundleExtra("bun");

 String str =bundle.getString("data");

 tv.setText(str);

 

1.3 使用Activity销毁时传递数据

第一个Activity中

 Intent intent = new Intent(MainActivity.this,TwoActivity.class);

  //用一种特殊方式开启Activity

 startActivityForResult(intent, 11);

//设置数据

protected void onActivityResult(intrequestCode, int resultCode, Intent data) {

 super.onActivityResult(requestCode,resultCode, data);

 String str =data.getStringExtra("data");

 tvOne.setText(str);

}

 

第二个activity中

//设置返回的数据

 Intent intent = new Intent();

 intent.putExtra("data",edtOne.getText().toString().trim());

 setResult(3, intent);

 //关闭当前activity

 finish();

 

1.4 * SharedPreferences传递数据

第一个Activity中

SharedPreferences sp = this.getSharedPreferences("info",1);

 //获取sp编辑器

 Editor edit = sp.edit();

 edit.putString("data", str);

 edit.commit();

 //创建意图对象

 Intent intent = newIntent(MainActivity.this,TwoActivity.class);

 //激活意图

 startActivity(intent);

 

第二个Activity中

SharedPreferences sp =this.getSharedPreferences("info", 1);

 //设置数据

 tv.setText(sp.getString("data",""));

 

实际中,创建一个SharedPreferencesUtils类

 publicclass SharedPreferencesUtils {

   static SharedPreferencesUtils instance;

   private SharedPreferences mSharedPreferences;

   public SharedPreferencesUtils() {

       mSharedPreferences =SmartApplication.getContext().getSharedPreferences(SpConstant.SP_NAME,Activity.MODE_PRIVATE);

    }

 

   // 单例模式

   public static synchronized SharedPreferencesUtils getInstance() {

       if (instance == null) {

           instance = new SharedPreferencesUtils();

       }

       return instance;

    }

 

   public void putString(String key, String value) {

       SharedPreferences.Editor editor = mSharedPreferences.edit();

       editor.putString(key, value);

       editor.commit();

    }

 

   public String getString(String key) {

       return mSharedPreferences.getString(key, "");

    }

 

   public void putInt(String key, int value) {

       SharedPreferences.Editor editor = mSharedPreferences.edit();

       editor.putInt(key, value);

       editor.commit();

    }

 

   public int getInt(String key) {

       return mSharedPreferences.getInt(key, 0);

    }

 

    publicvoid putBoolean(String key, boolean value) {

       SharedPreferences.Editor editor = mSharedPreferences.edit();

       editor.putBoolean(key, value);

       editor.commit();

    }

 

   public Boolean getBoolean(String key) {

       return mSharedPreferences.getBoolean(key, false);

    }

 

   public Boolean getTuisong(String key)

    {

       return mSharedPreferences.getBoolean(key, true);

    }

 

   public void remove(String key) {

       SharedPreferences.Editor editor = mSharedPreferences.edit();

       editor.remove(key);

       editor.commit();

    }

 

   public void putLong(String key, long value) {

       SharedPreferences.Editor editor = mSharedPreferences.edit();

       editor.putLong(key, value);

       editor.commit();

    }

 

   public int getLong(String key) {

       return (int) mSharedPreferences.getLong(key, (long)0);

    }

}

1.5 使用序列化对象Seriazable

工具类

import java.io.Serializable;

class DataBean implements Serializable {

 private String name;

 private String sex;

 public String getName() {

 return name;

 }

 public void setName(String name) {

 this.name = name;

 }

 public String getSex() {

 return sex;

 }

 public void setSex(String sex) {

 this.sex = sex;

 }

}

 

第一个Activity

//创建意图

 Intent intent = new Intent(MainActivity.this,TwoActivity.class);

 DataBean bean = new DataBean();

 //通过set方法把数据保存到DataBean对象中

 bean.setName("啦啦");

 bean.setSex("男");

 intent.putExtra("key", bean);

 startActivity(intent);

 

第二个Activity

Intent intent = getIntent();

 //反序列化数据对象

 Serializable se =intent.getSerializableExtra("key");

 if(se instanceof DataBean){

  //获取到携带数据的DataBean对象db

 DataBean db = (DataBean) se;

 tv.setText(db.getName()+"==="+db.getSex());

 }

 

1.6 使用静态变量传递数据

第一个Activity

Intent intent = newIntent(MainActivity.this,TwoActivity.class);

 TwoActivity.name="牛逼";

 TwoActivity.str="你说";

 startActivity(intent);

 

第二个Activity

//静态变量

protected static String name;

protected static String str;

tv.setText(str+name);

 

2、activity切换动画效果

一般启动一个新的Activity都默认有切换的动画效果,比如界面从右至左的移动。退出一个Activity都默认有切换的动画效果,比如界面从左至右的移动。

启动的默认切换效果,与lauchmode有关系。

2.1 activity切换无动画效果的实现

启动:

Intent intent = new Intent(ExampleActivity.this,Activity22.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
Bundle bundle = new Bundle();
bundle.putString("data", str);
intent.putExtra("bun", bundle);
startActivity(intent);

退出:

@Override
public void onBackPressed() {
   
super.onBackPressed();
   
overridePendingTransition(0,0);
}

 

或者

finish();

overridePendingTransition(0,0);
 

 

2.2 activity切换自定义动画效果的实现

Android Activity切换动画常用实现方式

https://www.jianshu.com/p/6878d556c9cd

 

 

 

 

 

你可能感兴趣的:(Android APK开发基础—— 四大组件之Activity)