Android-Activity

Android-Activity

Activity是学习Android首先要学习的知识点,同时也是一个很难弄清楚的知识点,之前已经学习过次Activity了,但是其中还是有些知识点是一知半解的状态。所以今天又来重温一次。

学习资料

《Android 开发艺术探索》

Activity漫谈

Activity是直接与我们用户进行交互的所以在Activity的翻译上有很多的歧义,有的直译为 活动 有的则稍微有些发散翻译为 界面 ,从我的角度来看,翻译成 界面 是更为合适的,不会造成意义的混淆。
Activity涉及到得知识点很多,大致如下:

  • 常规状态下的生命周期
  • 异常状态下的声明周期
  • Activity的启动模式
  • 隐式启动Activity

常规状态下的Activity的生命周期

下图的常规状态下的Activity的启动的方式.

图片.png | left | 570x753

方法详解:

  • onCreate: 表示Activity正在被创建,一般我们会在此方法中进行一些初始化操作,比如说,调用 setContentView 方法来加载布局资源。
  • onRestart: 表示Activity重新启动,当Activity从不可见状态转化到可见状态后会调用此声明周期方法,比如说按 __HOME __键后返回桌面,然后从新回到程序
  • onStart: 表示Activity正在被启动,此时Activity已将可见,但是还不能与用户交互,即已经可见,但是还没处于前台。如果要想查看这一状态,可以再 onStart 方法中让主线程睡眠一会,这是后看Activity是一片__白色__,布局与控件还未显示出来,但是Activity已经是处于可见状态了。
  • onResume: 表示Activity已经处于前台了,并且可以与用户交互。
  • onPause: 表示Activity正在停止,正常流程中紧着会执行 onStop 方法;但是,在极端的情况下会执行以下的流程: onPause-> onResume,当进入到一个新的Activity时快速地返回就有可能会出现这种情况,是属于小概率事件。在此声明中期方法中,可以进行一些缓存/存储数据等操作,但是注意不能太耗时。
  • onStop 表示Activity即将停止,可以做一些稍微重量级的回收工作。但是同样需要注意时间。
  • onDestroy: 表示Activity即将被销毁,如果需要我们可以在此方法中可以进行数据的缓存/存储,资源的释放等操作。

onStart-onResume/onPause-onStop的区别

虽然在实际的使用中没有太大的却别,但是我们还是要明白Android为什么要提供两个类似的回调:
划分 onStartonStop 的标准是是否可见,而划分 onResumeonPause 的标准是是否处于前台。

异常状态下的Activity声明周期

情况一,资源相关的系统配置发生改变导致Activity被杀死并重新创建

比如说如下情况,最简单的是图片资源,我们有一个图片imgA,我们把它放到【mipmap/drawable】目录下,同时为了兼容不同的设备我们可能会在不同分辨率的目录下防止不同的图片。当程序启动时,系统会通过根据当前设备的情况来选择不同的资源。如,手机横屏/竖屏会拿到不同的图片(landscape/portrait状态下的图片)。比如从竖屏状态转换到横屏状态,因为系统的配置发生了改变,在默认的情况下系统会被销毁并且重新创建。但是我们也可以通过设置来避免这种情况
其声明周期如下:

图片.png | left | 475x346

具体方法解析

  • onSaveInstanceState: 此方法在onStop生命周期方法之前执行,可能在onPause之前或者之后,次方法主要用来缓存view的 dfds,以便将来还原时使用。
  • onRestoreInstanceState: 此方法在onStart生命周期方法之前调用,用来还原缓存view 的数据。

PS: 这两个声明周期方法只有在异常终止的时候才会执行,正常情况下不会执行,所以我们可以利用这个特点来判断,Activity是不是恢复过。

当Activity需要销毁重建是,系统会为我们保存当前的视图结构,并且当需要重新创建的时候为我们还原,比如:输入框输入的数据,ListView的位置等等。每一个View都提供了 onSaveInstanceState onResotreInstanceState 两个方法的实现。如果我们想要知道它们都默认保存了那些数据和状态,我们可以看他们的源码来了解。

当Activity的onSaveInstanceState声明周期调用之后,Activity会委托 window 来保存数据,window又会委托他上面的顶级容器来保存状态,然后顶级容器再一一通知下属的子元素来保存数据。

我们来看一看TextView的源码,看看它保存了哪些状态:

@Override
public Parcelable onSaveInstanceState() {
    Parcelable superState = super.onSaveInstanceState();


    // Save state if we are forced to
    final boolean freezesText = getFreezesText();
    boolean hasSelection = false;
    int start = -1;
    int end = -1;


    if (mText != null) {
        start = getSelectionStart();
        end = getSelectionEnd();
        if (start >= 0 || end >= 0) {
            // Or save state if there is a selection
            hasSelection = true;
        }
    }


    if (freezesText || hasSelection) {
        SavedState ss = new SavedState(superState);


        if (freezesText) {
            if (mText instanceof Spanned) {
                final Spannable sp = new SpannableStringBuilder(mText);


                if (mEditor != null) {
                    removeMisspelledSpans(sp);
                    sp.removeSpan(mEditor.mSuggestionRangeSpan);
                }


                ss.text = sp;
            } else {
                ss.text = mText.toString();
            }
        }


        if (hasSelection) {
            // XXX Should also save the current scroll position!
            ss.selStart = start;
            ss.selEnd = end;
        }


        if (isFocused() && start >= 0 && end >= 0) {
            ss.frozenWithFocus = true;
        }


        ss.error = getError();


        if (mEditor != null) {
            ss.editorState = mEditor.saveInstanceState();
        }
        return ss;
    }


    return superState;
}

从上面的源码中我们可以清晰地看到TextView保存的数据。同样在onRestoreInstanceState方法中也会根据缓存的数据进行还原状态。

自定义缓存与恢复

图片.png | left | 517x395


import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onSaveInstanceState(outState: Bundle?) {
        super.onSaveInstanceState(outState)
        //将EditText的内容缓存
        if (outState != null) {
            outState.putString("testET_txt", testET.text.toString())
        }
    }

    override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
        super.onRestoreInstanceState(savedInstanceState)
        //将内容恢复
        var text = savedInstanceState?.getString("testET_txt")
        testET.setText(text)
    }
}

禁止销毁并重新创建

如果我们不想让Activity在某些系统配置改变的时候, 禁止销毁并重新创建,我们也是可以通过设置来办到的(通过为Activity设置configChanges属性,该属性可以通过|运算符进行多选操作),设置如下:

<activity
    android:name=".MainActivity"
    android:configChanges="orientation">

</activity>

configChange的常见设置如下:

情况二,内存不足导致优先级较低的Activity被杀死

这种情况下涉及到了Activity的优先级,其如下:
最高优先级: 正在与用户交互的Activity
中等优先级: 可见但处于后台的Activity,比如Activity弹出了一个对话框,这时候,Activity是可见的,但是是位于后台的。
最低优先级: 后台Activity,比如执行了 onStop 方法的Activity

当内存不足的时候,会按照上面的优先级的顺序依次杀死Activity并且缓存状态等待恢复,来保持更高优先级的Activity的运行。

原文地址:https://www.cnblogs.com/slyfox/p/6959417.html