035-Acticity详解-基础&进阶

731 阅读4分钟

【代码是最好得老师】

1.概要

Activity 是四大组件之首

2.Activity生命周期

  • 典型情况下的生命周期:

是指在有用户参与的情况下,Activity所经过的生命周期的改变;

  • 异常情况下的生命周期:

是指Activity 被系统回收 或者由于当前设备的 Configuration发生改变 从而导致Activity被销毁重建

2.1典型生命周期

  • 当用户按back键回退时,回调如下:onPause -> onStop -> onDestroy

2.2异常生命周期

  • 如果突然旋转屏幕,由于系统配置发生了改变,在默认情况下,Activity就会被销毁并且重新创建
  • Activity是在异常情况下终止的,系统会调用onSaveInstanceState来保存当前Activity的状态
  • Activity被意外终止时,Activity会调用onSaveInstanceState去保存数据,然后Activity会委托Window去保存数据,接着Window再委托它上面的顶级容器去保存数据。顶层容器是一个ViewGroup,一般来说它很可能是DecorView。最后顶层容器再去一一通知它的子元素来保存数据,这样整个数据保存过程就完成了
  • onRestoreInstanceState一旦被调用,其参数Bundle savedInstanceState一定是有值的,我们不用额外地判断是否为空;但是onCreate不行,onCreate如果是正常启动的话,其参数Bundle savedInstanceState为null,所以必须要额外判断

2.3 configChanges

不想让Activity在屏幕旋转的时候重新创建,就可以给configChanges属性添加orientation这个值

android:configChanges="orientation"
android:configChanges="orientation|screenSize"
android:configChanges="orientation|keyboardHidden"

Activity的确没有重新创建,并且也没有调用onSaveInstanceState和onRestoreInstanceState来存储和恢复数据,取而代之的是系统调用了Activity的onConfigurationChanged方法

上面表格中的项目很多,但是我们常用的只有locale、orientation和keyboardHidden这三个选项

3.Activity的启动过程

  1. 启动Activity的请求会交由Instrumentation处理
  2. Instrumentation通过Binder向AMS发送请求
  3. AMS(Activity Manager Service)内部维护着一个ActivityStack,并负责同步栈内Activity的状态
  4. AMS通过ActivityThread去同步Activity状态,完成生命周期方法调用

4.Activity 启动模式

  • addFlags的优先级要高于xml方式
  • clearTaskOnLaunch设置该属性后,每次返回该Activity时,都将该Activity之上的所有Activity清除
  • TaskAffinity:标识了一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名
  • singleTop & singleInstance 这两种启动模式,,使用startActivityForResult()方法启动另一个Activity ,那么系统更直接返回 Activity.RESULT_CANCELED,不会等待返回,因为android在Framework层做了对这两启动模式的限制

    根本: 不同Task栈,不能进行数据数据,如果一定要,只能通过Intent来绑定数据

4.1标准模式-standard

  1. 系统默认的启动模式
  2. 每次启动创建一个新的实例activity
  3. 谁启动了该activity实例,该activity就在其栈中
  4. 当我们用ApplicationContext去启动standard模式的Activity的时候会报错
    原因:standard模式的Activity默认会进入启动它的Activity所属的任务栈;applicationContext没有任务栈;
    解决: 启动Activity指定**intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)**标记位,singleTask模式

4.2栈顶复用模式-singleTop

  1. 如果目标activity实例位于栈顶,activity不会重新创建,同时onNewIntent()方法会被调用,不会调用onCreate()、onStart()
  2. 如果栈顶无目标实例,则重新创建activity

4.3栈内复用模式-singleTask【AndroidManifest的clearTop】

  1. 可以理解为栈内单例模式的activity,只要栈内存在,就不会重新创建,且onNewIntent()方法会被调用,不会调用onCreate()、onStart()
  2. 启动时,会先查找activity的目标栈,不存在则创建栈,然后创建实例
  3. 如果目标栈存在,查找栈内是否存在目标activity,不存在则创建。
  4. 如果目标栈存在目标activity,且不在栈顶,则会将activity之上的实例出栈,将activity置栈顶

4.4单实例模式-singleInstance

  1. 加强版的singleTask模式,即activity独立运行在单独栈中

4.5 Intent的Flags

  1. FLAG_ACTIVITY_NEW_TASK:为activity指定【singleTask】启动模式
  2. FLAG_ACTIVITY_SINGLE_TOP:指定【singleTop】
  3. FLAG_ACTIVITY_CLEAR_TOP:与FLAG_ACTIVITY_NEW_TASK配合使用,效果同【singleTask】
  4. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:Activity不会出现在历史Activity的列表中,一次性activity

5.Activity数据传递

5.1携带数据

step1:Activity1发送数据

String data = "hello world";
Intent intent = new Intent(MainActivity.this,FirstActivity.class);
intent.putExtra("mydata",data);
startActivity(intent);

step2:Activity2接受数据

Intent intent = getIntent();
String data = intent.getStringExtra("mydata");
Toast.makeText(this, "传递过来的值是" + data, Toast.LENGTH_SHORT).show();

5.2返回数据

step1:activity1启动方式:要求返回数据

Intent intent = new Intent(MainActivity.this, FirstActivity.class);
startActivityForResult(intent, 1);

step2:activity2设置返回数据

Intent intent = new Intent();
intent.putExtra("data_return","hello");
setResult(RESULT_OK,intent);
finish();

step3:activity1接收返回的数据

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode){
            case 1:
                if (resultCode == RESULT_OK){
                    String returnedData = data.getStringExtra("data_return");
                    Log.e("MainActivity",returnedData);
                }
        }
    }

6.activity全局管理

仅提供思路,实际开发按需更换为软引用方式

step1:Activity管理类

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){
                  activity.finish();
            }
     }
}

step2:BaseActivity

public class BaseActivity extends AppCompatActivity{
     @Override
     protected void onCreate( Bundle savedInstanceState ){
          super.onCreate( savedInstanceState );
          Log.d( "BaseActivity" , getClass().getSimpleName() );
          ActivityCollector.addActivity(this);
     }

      @Override
      public void onDestory(){
           super.onDestory();
           ActivityCollector.removeActivity(this);
      }
}

step3:XxxActivity

public class XxxActivity extends BaseActivity{
    //....
    private void exitApp(){
        ActivityCollector.finishAll();
        //or force exit
        //android.os.Process.killProcess(android.os.Process.myPid());
    }
    //...
}