Activity详解

Activity是Android四大组件之一,在Android系统中是以界面的形式进行体现

一、生命周期

Activity生命周期
生命周期方法解读
  • onCreate():Activity开始创建时调用(生命周期的第一个方法),做一些初始化的工作,比如setContentView()方法
  • onStart():Activity开始启动时调用(此时Activity还不可见,无法与用户进行交互)
  • onResume():当Activity第一次启动完成或者当前Activity被遮挡住一部分(进入了onPause())重新回到前台时调用,比如弹窗消失。当onResume()方法执行完毕之后Activity就进入了运行状态。
  • onPause():Activity停止但是当前Activity还是处于用户可见状态,比如出现弹窗;在onPause()方法中不能进行耗时操作(当前Activity通过Intent启动另一个Activity时,会先执行当前Activity的onPause()方法,再去执行另一个Activity的生命周期)
  • onStop():Activity完全被挡住不可见时调用(在onStop()中做一些回收资源的操作)
  • onDestroy():Activity被销毁时
  • onRestart():处于stop()状态也就是完全不可见的Activity重新回到前台时调用(重新回到前台不会调用onCreate()方法,因为此时Activity还未销毁)
  • Activity启动时:onCreate()--->onStart()--->onResume()--->运行状态
  • Activity被完全覆盖或者点击home键:onPause()--->onStop()--->onDestroy(),如果在Activity还未销毁之前重新回到了前台:onPause()--->onStop()--->onRestart()--->onStart()--->onResume()
其他注意事项
  • onStart()和onStop()从Activity是否完全可见的角度进行回调
  • onPause()和onResume()从Activity是否位于前台(UI最顶层)的角度进行回调

二、启动模式

任务栈

介绍启动模式之前要先介绍一下任务栈:

affinity属性:
affinity是Activity的一个属性,在Manifest中对应taskAffinity属性,拥有相同affinity属性的Activity属于同一个任务栈,任务栈也具有affinity这个属性,任务栈的这个属性由根Activity决定;
默认情况下,所有的Activity的affinity属性继承自Application,所以Application也具有这个属性,Application的默认affinity为包名。

应用程序在启动时就创建了一个任务栈(先近后出),用于存储当前应用的Activity实例,在默认情况下,所有的Activity都属于同一个任务栈;一个任务栈包含了一个Activity的集合,然后有序的选择一个Activity和用户进行交互,只有在栈顶的Activity才可以和用户进行交互;只有当任务栈中所有的Activity全部清除出栈时任务栈才会销毁,程序退出。

启动模式

在Manifest对应的Activity中通过android:launchMode属性进行设置

  • standard:默认的启动模式。不需要在Manifest对应的Activity中设置android:launchMode属性。
    每次启动Activity都会生成一个新的Activity实例置于任务栈栈顶,不管有没有已存在的实例都会进行创建。
  • singleTop:栈顶复用模式。Activity设置这个启动模式之后,在启动Activity时,会先判断当前任务栈的栈顶是否存在当前要启动的Activity的实例,如果存在则不创建实例,如果不存在就创建实例置于栈顶。
    场景:假如说一个app在通知栏推送了好几条消息,点击一条推送消息就会进入一个Activity,如果设置为默认模式的话,就会启动多个Activity,但是设置为singleTop模式的话只需要传入不同的数据就可以显示不同的页面。
  • singleTask:和singleTop这个启动模式类似,但是singleTop针对的是任务栈的栈顶,singleTask针对的是整个任务栈。启动一个新的Activity时,会判断任务栈中是否存在Activity实例,如果不存在的话就创建一个新的实例,如果存在就会将任务栈中此Activity之上的所有Activity清除出栈,是一种更为霸道的方式。
    场景:一般用于系统主界面(因为在主界面点击Back之后应该是退出APP)
    -singleInstance:单例模式。启动Activity时会为这个Activity分配一个新的affinity属性,并且创建一个新的任务栈,并且这个栈中只能存在这一个Activity,如果之前已经创建过则不会创建新的实例。
    场景:系统Launcher,来电界面

三、Activity状态保存和恢复

哪些状态需要保存状态

最简单的就是数据了。假如我们当前正在操作一些数据,但是数据还没有处理完成,碰到一些突发情况,这时就需要保存数据。

什么情况下需要保存状态

按照官方的说法就是在处理运行时配置变更的时候。
总结也就是如下几种情况:

  • 点击back键
  • 锁屏
  • 点击home键
  • 有其他App进入前台(比如来电)
  • 启动了新的Activity
  • 屏幕方向发生旋转
  • APP被系统kill掉
状态为什么会丢失

创建一个Activity,重写其生命周期的方法

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e(TAG, "onCreate: ");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "onDestroy: ");
    }
/**
     * 2022-02-19 18:27:21.839 19513-19513/com.example.myapplication E/MainActivity: onCreate: 
     * 2022-02-19 18:28:17.984 19513-19513/com.example.myapplication E/MainActivity: onDestroy: 
     * 2022-02-19 18:28:18.049 19513-19513/com.example.myapplication E/MainActivity: onCreate: 
     */

旋转一下屏幕,可以发现Activity被重新创建了

如何保存和恢复状态

在Activity中在重写另外两个方法

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e(TAG, "onCreate: ");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.e(TAG, "onStart: ");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "onDestroy: ");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.e(TAG, "onResume: ");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.e(TAG, "onStop: ");
    }

    @Override
    protected void onPause() {
        Log.e(TAG, "onPause: ");
        super.onPause();
    }

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.e(TAG, "onRestoreInstanceState: ");
    }
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.e(TAG, "onSaveInstanceState: ");
    }
    /**
     * 2022-02-19 19:07:16.052 20460-20460/com.example.myapplication E/MainActivity: onCreate: 
     * 2022-02-19 19:07:16.056 20460-20460/com.example.myapplication E/MainActivity: onStart: 
     * 2022-02-19 19:07:16.060 20460-20460/com.example.myapplication E/MainActivity: onResume: 
     * 2022-02-19 19:07:44.421 20460-20460/com.example.myapplication E/MainActivity: onPause: 
     * 2022-02-19 19:07:44.431 20460-20460/com.example.myapplication E/MainActivity: onStop: 
     * 2022-02-19 19:07:44.433 20460-20460/com.example.myapplication E/MainActivity: onSaveInstanceState: 
     * 2022-02-19 19:07:44.434 20460-20460/com.example.myapplication E/MainActivity: onDestroy: 
     * 2022-02-19 19:07:44.490 20460-20460/com.example.myapplication E/MainActivity: onCreate: 
     * 2022-02-19 19:07:44.497 20460-20460/com.example.myapplication E/MainActivity: onStart: 
     * 2022-02-19 19:07:44.498 20460-20460/com.example.myapplication E/MainActivity: onRestoreInstanceState: 
     * 2022-02-19 19:07:44.500 20460-20460/com.example.myapplication E/MainActivity: onResume: 
     */

在Activity创建成功之后,旋转屏幕,可以发现在Activity销毁时会在onDestroy()之前调用onSaveInstanceState方法,然后在销毁Activity,在onResume()之前调用onRestoreInstanceState方法。
onSaveInstanceState方法就是用来保存Activity中的数据的,而onRestoreInstanceState可以获取在onSaveInstanceState保存的数据。
然后发现这两个方法的参数都是Bundle类型的,所以说我们可以通过Bundle来保存和恢复数据

 @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        savedInstanceState.putString("data","bundle");
        Log.e(TAG, "onRestoreInstanceState: ");
    }
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        String data = outState.getString("data");
        Log.e(TAG, "onSaveInstanceState: ");
    }

四、Activity之间的通信方式

方式一:通过Intent传值
        Intent intent=new Intent(A.this,B.class);
        intent.putExtra("data",100);
        startActivity(intent);
        //Activity B中
        Intent intent=getIntent();
        intent.getIntExtra("data",0);
方式二:通过Bundle
       //Activity  A启动ActivityB
        Intent intent=new Intent(A.this,B.class);
        Bundle bundle=new Bundle();
        bundle.putString("data","data");
        intent.putExtra(bundle);
        startActivity(intent);
        //Activity B中
        Bundle bundle=getIntent().getExtras();
        String data=bundle.getString("data");
方式三:通过全局变量(Application)
  • 创建一个Application的子类,并且声明一个全局变量,同时在Manfest中引入当前Application
         //应用的全局变量
        public Map<String,Object> data = new HashMap<String, Object>();
  • 在Activity A合适的位置存储数据到HashMap中,在Activity B中通过map.get()取出数据
方式四:回传数据

假设一个场景,QQ或者微信我们在从相册选取一张图片作为头像时应该怎么传递数据
Activity A:通过startActivityForResult(intent requestcode);方法
Activity B:setResult(resultCode,intent);
Activity A:重写onActivityResult();

     public class MainActivity extends Activity {
                private ImageView iv;   
       @Override
     protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    iv = (ImageView) findViewById(R.id.iv);
  }  
  public void show(View v)
   {
    Intent intent = new Intent(MainActivity.this, InfoActivity.class);
    
    //带返回数据启动Activity
    startActivityForResult(intent, 110);
   }
   /**
  * 获取回传的数据
  * 
  * int requestCode  请求码
  * int resultCode   结果码
  * Intent data     意图(带着返回参数)
  */
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode==110 && resultCode == RESULT_OK)
    {
        //为图片控件设置内容
        
        int imageId = data.getIntExtra("imageId", R.drawable.ic_launcher);
        
        iv.setImageResource(imageId);
    }
  }    
  }
public class InfoActivity extends Activity {

private RadioGroup rg;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_info);
    
    rg = (RadioGroup) findViewById(R.id.rg);
}

//点击按钮后,将图片的ID 回传给MainActivity页面
public void submit(View v)
{
    //1, 得到当前选中的RadionButton的id
    int checkId = rg.getCheckedRadioButtonId();
    //图片的ID
    int imageId = R.drawable.ic_launcher;  
    switch (checkId) :
    case R.id.rb1:   
        imageId = R.drawable.img_31;      
        break;
    case R.id.rb2:
        imageId = R.drawable.img_32;  
        break;
       
    }
    
    
    /**
     * 通过startActivityForResult() 开启的界面, 需要有返回值,
     * 
     * 则必须要通过 setResult() 方法返回数据
     * 
     * resultCode  返回码
     * 
     * data        intent意图对象
     */
    Intent data = new Intent();
    data.putExtra("imageId", imageId);
    
    setResult(RESULT_OK, data);
    
    //关闭当前Activity页面
    finish();
}   
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 3.2 Activity详解 3.2.1 生命周期分析 典型情况下生命周期分析 一般情况下,当当前Activity...
    jianhuih阅读 1,121评论 0 0
  • 一、Activity简述 1、概念引入 [图片上传失败...(image-7fae63-1533296614201...
    测天测地测空气阅读 347评论 0 0
  • 一、Activity的生命周期 本节内容将生命周期的情况分为两部分介绍,第一部分先了解典型的生命周期的7个部分及A...
    jimjayce阅读 459评论 0 0
  • 一、Activity简述 1、概念引入 Activity作为Android的四大组件之一,Activity在And...
    王帅Alex阅读 3,917评论 32 42
  • 关于Activity 引用google官方文档,是这么说的: Activity是一个应用组件,用户可与其提供的屏幕...
    Cris_Ma阅读 377评论 0 0