118

Android知识点回顾之Activity基础

 6 years ago
source link: https://juejin.im/post/5a1108216fb9a0452207176d
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Android知识点回顾之Activity基础

2017年11月19日 05:45 ·  阅读 2410

Activity生命周期

Activity的生命周期包括onCreate(),onRestart(),onStart(),onResume(),onPause(),onStop(),onDestroy()。其相互转化的过程如下图所示。左边的图是单个Activity的生命周期回调情况。右边的是当前Activity跳转到另外一个Activity时,两者相关生命周期回调先后顺序的情形。

图1:Activity生命周期
图1:Activity生命周期

onCreate()

表示Activity正在被创建

此方法在整个生命周期中只会被调用一次。可以在这里做一些初始化的操作。

参数savedInstanceState保存Activity因为异常情况而被销毁前的状态,可以利用此参数做一些数据恢复的操作。

onStart()

表示Activity正在被启动。此时Activity已经可见,即将进入前台界面,但是还不能喝用户进行交互。

onResume()

表示Activity已经启动完成,进入到了前台,可以同用户进行交互了。需要注意的是此方法在Activity的整个生命周期中可能会被多次调用到。

onPause()

表示Activity正在被停止。

可以在这里释放系统资源,动画的停止

不宜在此做耗时操作,因为此方法结束后会调用新Activity的onCreate(),onStart(),onResume(),耗时操作会影响到新Activity的显示

onStop()

当Activity不可见的时候回调此方法。

需要在这里释放全部用户使用不到的资源。

可以做较重量级的工作,如对注册广播的解注册,对一些状态数据的存储

此时Activity还不会被销毁掉,而是保持在内存中,但随时都会被回收。

onDestroy()

Activity即将被销毁。

此时会释放掉所有占用的资源。

onCreate()和onDestroy()成对存在

onStart()和onStop()成对存在

onResume()和onPause()成对存在

Activity状态的保存和恢复

状态的保存

当Activity 非正常退到后台时,就会调用onSaveInstanceState()方法。非正常的情况包括:有新的Activity启动,灭屏,未设置保存状态的横竖屏切换,按home键到桌面,切换到最近任务列表。正常情况是用户点击返回键,程序调用finish()方法,此时不会回调onSaveInstanceState()方法。

调用的次序为:onPause()->onSaveInstanceState()->onStop()

可对一些状态进行保存,

static final String STATE_LISTVIEW_CURRENT_POSITION = "list_view_current_position";
...


@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // 保存当前ListView的位置
    savedInstanceState.putInt(STATE_LISTVIEW_CURRENT_POSITION , mCurrentPosition);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}复制代码

系统会为View自动保存相关的状态,前提是View要在布局文件里设置唯一的id值,即android:id属性。

由于onSaveInstanceState()方法不能保证百分百调用到,所以只能做一些临时状态信息的存储,如果要做持久化的操作,需要在onStop()里进行。

状态的恢复

当Activity在被销毁后重新创建时,可以从onCreate(Bundle savedInstanceState)方法中的savedInstanceState参数恢复之前保存的状态,也可以从onRestoreInstanceState(Bundle savedInstanceState)方法中恢复。两种方法的效果都是一样的,只是前者需要判空操作,后者不需要

onCreate(Bundle savedInstanceState)的恢复:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); 

   //如果不为空的话,则说明有可恢复的状态
    if (savedInstanceState != null) {        
        mCurrentPosition= savedInstanceState.getInt(STATE_LISTVIEW_CURRENT_POSITION );
    } else {
        //初始化
    }
    ...
}复制代码

onRestoreInstanceState(Bundle savedInstanceState)的恢复:

//调用此方法,savedInstanceState参数必不为空
public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    mCurrentPosition= savedInstanceState.getInt(STATE_LISTVIEW_CURRENT_POSITION );
}复制代码

Activity启动模式

四种启动模式

Activity的启动模式可以允许你的Activity拥有多少个实例。

有两种方法可以设置:1、在manifest文件中设置。2、用Intent的flag标识设置

manifest方式

在minifest中对应的Activity设置如下四个中的一个值。

...
<activity 
  ...
   android:launchMode=["standard" | "singleTop" | "singleTask" | "singleInstance"]
  ...
/>
...复制代码

standard

默认值,多实例模式。

每启动一次,都会创建一个新的Activity实例。

并且新实例可以在不同的任务栈上创建,相同的任务栈可以创建多个实例。

启动的生命周期为:onCreate()->onStart()->onResume()

需要注意的是,此模式下启动的实例所在的任务栈,为启动它的那个Activity所属的任务栈。比如A属于task1,A启动了B,B的模式为standard,则B所在的任务栈为task1

singleTop

栈顶复用模式

如果任务栈顶已经存在需要启动的目标Activity,则直接启动,并会回调onNewIntent()方法,生命周期顺序为:
onPause() ->onNewIntent()->onResume()

如果任务栈上顶没有需要启动的目标Activity,则创建新的实例,此时生命周期顺序为:
onCreate()->onStart()->onResume()

两种情况如下图,从图中可以看出,此模式下还是会出现多实例,只要启动的目标Activity不在栈顶的话。

singleTop启动模式,A为standard模式,B为singleTop模式
singleTop启动模式,A为standard模式,B为singleTop模式

singleTask

栈内复用模式,一个任务栈只能有一个实例。

有几种情况:

  • 当启动的Activity目标任务栈不存在时,则以此启动Activity为根Activity创建目标任务栈,并切换到前面

    D为singleTask模式
    D为singleTask模式
  • 当启动的Activity目标任务栈存在,启动的Activity不存在时,则直接在目标任务栈上创建Activity

    D的启动模式为singleTask,并且taskAffinity为task2
    D的启动模式为singleTask,并且taskAffinity为task2
  • 当启动的Activity存在时,则会直接切换到Activity所在的任务栈,并且任务栈中在Activity上面的所有其他Activity都出栈(调用destroy()),此时启动的Activity位于任务栈顶,并且会回调onNewIntent()方法。

    左边的DtaskAffinity为task2的情况,右边D的taskAffinity为task1的情况
    左边的DtaskAffinity为task2的情况,右边D的taskAffinity为task1的情况

singleInstance

和singleTask模式类似,只不过独占其所在的任务栈,比如A为singleInstance模式,其所需的任务栈为task1,则task1只有A一个Activity,由A启动的Activity会另起一个task。而后续启动此Activity,都不会再创建新的Activity。

Intent的方式

除了可以在manifest中设置Activity的启动模式,也可以通过设置Intent的flag标识来设定Activity的启动模式。

常用的有:FLAG_ACTIVITY_NEW_TASK,FLAG_ACTIVITY_SINGLE_TOP,FLAG_ACTIVITY_CLEAR_TOP

FLAG_ACTIVITY_NEW_TASK

启动Activity时,如果不存在Activity的实例,则会以此Activity为根Activity创建新的任务栈,如果存在的话则直接切换到对应的Activity实例,并回调onNewIntent()方法。相当于“singleTask”启动模式。

FLAG_ACTIVITY_SINGLE_TOP

相当于“singleTop”模式

FLAG_ACTIVITY_CLEAR_TOP

设置此标识的Activity在启动时,如果当前的任务栈内存在此Activity实例,则跳转到此实例,并清除掉在此实例上面的所有Activity实例,此时此Activity实例位于任务栈的栈顶

Activity间的数据传递

Activity直接的数据传递,一般使用Intent就够了。

可以使用Intent.putExtra()方法

把值传给待启动的Activity

//MianActivity
 Intent intent = new Intent(this, SecondActivity.class);
 intent.putExtra("data_key", "abcd");

 Bundle data = new Bundle();
 data.putString("key1","value1");
 intent.putExtra("data",data);
...
 startActivity(intent);

...
//SecondActivity
...
protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity_layout);
        Intent intent = getIntent();
        Toast.makeText(this,intent.getStringExtra("data_key"),Toast.LENGTH_LONG).show();

        Bundle data = intent.getBundleExtra("data");
        String key1 = data.getString("key1");
        Toast.makeText(this,key1,Toast.LENGTH_LONG).show();
 }
...复制代码

把值返回给启动它的Activity

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

 startActivityForResult(intent, REQUEST_CODE);

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 super.onActivityResult(requestCode, resultCode, data);
 String str = data.getStringExtra("data");
 if(REQUEST_CODE == requestCode){
    if(SecondActivity.RESULT_CODE == resultCode){
      ...
    }
 }

 ...
}
...
//SecondActivity
...
 Intent intent = new Intent();
 intent.putExtra("data", "result_value");
 setResult(RESULT_CODE, intent);
 finish();
...复制代码

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK