【25】Android 四大组件 - 初探Acitivity

目录

前言

Activity 任务堆栈 

Activity 基本状态

Activity 生命周期

相关函数

验证

知晓当前活动

随时随地退出程序

Activity 的现场保存

锁定屏幕显示方向

自行处理变更

onSaveInstanceState()和onRestoreInstanceState()

全屏显示

参考鸣谢


前言

该篇续 初识Activity ,上一篇主要介绍了一些基础用法,该篇为进阶。

Activity 任务堆栈 

从上一篇的使用中,我们一定会有一个感性的认识,即Activity是可层层叠加的,启动一个 新的Activity 即覆盖在 原Activity 之上。那么在 Android 中是怎么管理这些 Activity 的呢?

答案是Task(任务),一个任务就是一组放在栈中的活动集合,这个栈也被称为“返回栈

堆栈中的 根Activity 就是应用程序的 主Activity。而堆栈中 最上方的Activity 则是当前运行的 / 用户正在操作的 UI Activity,每当我们启动一个 Activity 时,则该 Activity 入栈,按 Back 或人为销毁则出栈。

除了 最顶层的Activity 外,其它的 Activity 都有可能在系统内存不足时被回收,一个 Activity 的实例越是处在栈的底层,它被系统回收的可能性越大。系统 负责管理栈中 Activity 的实例,它根据 Activity 所处的状态来改变其在栈中的位置。

Activity 基本状态

除了中间状态,Activity 基本上以以下四种状态存在:

  • Resumed(继续/运行态)

Activity 位于屏幕前台并具有用户焦点。(有时也将此状态称作 “运行中”。)

  • Paused(暂停)

存在另一个 Activity 位于屏幕前台并具有用户焦点,但此 Activity 仍可见。也就是说,另一个 Activity 显示在 此 Activity 上方,并且该 Activity 部分透明或未覆盖整个屏幕;此时此 Activity处于暂停状态。暂停的 Activity 处于完全活动状态(Activity 对象保留在内存中,它保留了所有状态和成员信息,并与窗口管理器保持连接),但在内存极度不足的情况下,可能会被系统终止。

  • Stopped(停止)

Activity另一个 Activity 完全遮盖(该 Activity 目前位于 “后台”)。 已停止的 Activity 同样仍处于活动状态(Activity 对象保留在内存中,它保留了所有状态和成员信息,但未与窗口管理器连接)。不过,它对用户不再可见,在他处需要内存时可能会被系统终止。

  • Killed(销毁)

该活动被系统结束或未启动,系统会倾向于回收这种状态的活动,以保证手机内存的充足。

ps:如果 Activity 处于暂停或停止状态,系统可通过要求其结束(调用其 finish() 方法)或直接终止其进程,将其从内存中删除。(将其结束或终止后)再次打开 Activity 时,则必须重建。

Activity 生命周期

先上 Android Activity 的 生命周期图示

当一个 Activity 转入和转出上述不同状态时,系统会通过各种回调方法向其发出通知。 Activit类 中定义了 7 个回调方法,覆盖了活动生命周期的每一个环节。这些回调方法 onRestart()都是两两对立的,可分为 3 种生存期。

相关函数

下面我们简单过一下这些回调函数:

  • onCreate()

活动第一次创建时被调用,我们一般在此完成活动的初始化操作。

  • onStart()

在活动由不可见变为可见的时候调用。

  • onResume()

活动准备好和用户进行交互时调用,此时,该活动一定处于运行状态,位于栈顶。

  • onPause()

系统准备去启动或恢复另一个活动的时候调用。

  • onStop()

活动完全不可见时调用。

  • onDestroy()

活动销毁前调用,执行之后,活动的状态将变为销毁状态。

  • onRestart()

活动由停止状态变为运行状态之前调用。

验证

程序正常启动

onCreate ()->onStart ()->onResume ()

正常退出

onPause ()->onStop ()->onDestory ()

Activity1 启动另一个 Activity2

(以下皆为 Activity1 回调)

启动:onPause ()->onStop ()

再返回:onRestart ()->onStart ()->onResume ()

程序按 back 退出再进入

程序按 back 退出: onPause ()->onStop ()->onDestory ()

再进入:onCreate ()->onStart ()->onResume ()

程序按 home 退出再进入

程序按 home 退出: onPause ()->onStop ()

再进入:onRestart ()->onStart ()->onResume ()

屏幕翻转

onPause ()->onStop ()->onDestory ()->onCreate ()->onStart ()->onResume ()

知晓当前活动

        Log.i("MainActivity",getClass().getSimpleName());

//或

        Log.i("MainActivity",getClass().getName());

随时随地退出程序

为何要随时随地退出程序呢?

例如我进入多个ActivityActivity1  -->  Activity2  -->  Activity3...

此时如果我想退出程序,需要按 多次 Back,无疑这是非常影响体验的。

为此我们创建一个ActivityManager类,来 管理Activity

ActivityManager.java

package com.example.mytest;

import android.app.Activity;

import java.util.ArrayList;
import java.util.List;

/**
 * 静态方法,不需new,通过类名方法名即可调用
 */

public class ActivityManager {
    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){
            if (!activity.isFinishing()){
                activity.finish();
            }
        }
        activities.clear();
        //杀死当前程序进程的代码,保证程序彻底退出。
        android.os.Process.killProcess(android.os.Process.myPid());
    }
}

再创建一个继承自 AppCompatActivity BaseActivity,并从写onCreate()onDestory()

BaseActivity.java

package com.example.mytest;

import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ActivityManager.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityManager.removeActivity(this);
    }
}

MainActivity Item1 都需继承自这个 BaseActiivty,而不是其父类 AppCompatActivity

MainActivity-->Item1-->onClick退出

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ActivityManager.finishAll();
            }
        });

效果

Activity 的现场保存

通过前面生命周期的探究,我们知道在 屏幕翻转点击Home 时,Android 会重启正在运行的 Activity。重启行为旨在通过利用与新设备配置匹配的备用资源自动重新加载您的应用,来帮助它适应新配置。

Demo

Add_Button 点击事件使变量 a 增一,并显示到 TextView

屏幕翻转后,TextView 显示的值又归零了

假设此处是一调查问卷,当用户 有电话打入 或 需要暂时退出。 那么,之前所输入的信息就会全部清空。这也是非常影响体验的(吐槽一下前不久进行的志愿者注册就是这个亚子)。那么该如何解决这呢?

对于翻转屏幕造成的数据丢失,我们可以采用一个简单的策略:

锁定屏幕显示方向

AndroidManifest.xml 中添加 Activity 属性

//横屏锁定
android:screenOrientation="landscape"

//竖屏锁定
android:screenOrientation="portrait"

显然,这种方法并不是正解。

那么还有没有简单的方法呢?

自行处理变更

答案是 有,我们可以告诉系统 自己来处理变更

AndroidManifest.xml 中添加 Activity 属性

android:configChanges="orientation|keyboardHidden|screenSize"

效果图

上面讲的方法,只能虽然达到了现场保护的要求,并且简单易用,但是只能算前菜;下面才是主菜!

onSaveInstanceState()onRestoreInstanceState()

这里我们重写

onSaveInstanceState( Bundle outState)

onRestoreInstanceState(Bundle savedInstanceState)

并通过 Log 打印出来

可以发现:

Activity 开始停止时,系统会调用,onSaveInstanceState ( ) 以便我们的 Activity 可以使用一组键值对来保存状态信息。

当 Activity 在被销毁后重新创建时,系统会在onResume ( ) 前调用onRestoreInstanceState ( )方法,以便我们从 Bundle 系统恢复保存状态。

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);

        //保存数据
        outState.putString("number",textView.getText().toString());
        Log.i("MainActivity","onSaveInstanceState()");
    }


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

        //获取数据
        String s = savedInstanceState.getString("number");
        textView.setText(s);
        a = Integer.valueOf(s);

        Log.i("MainActivity","onRestoreInstanceState()");
    }

注意到:void onCreate(Bundle savedInstanceState) 中,也是 Bundle 参数。

实际上, onCreate ()onRestoreInstanceState () 都会收到 Bundle 包含实例状态信息。

自然,我们也可以直接在onCreate()取得保存状态

        if(null != savedInstanceState){
            String s = savedInstanceState.getString("number");
            textView.setText(s);
            a = Integer.valueOf(s);
        }

效果

PSonSaveInstanceState()仅适合保存临时数据,它 并非百分百调用(比如点击了 back 键)。显然一些永久性的数据,我们并不能在此中保存。

我们需关注另一个回调函数 onPause()

无论出现怎样的情况,比如程序突然死亡了,能保证的就是 onPause() 方法是一定会调用的;这个特性使得 onPause()是持久化相关数据的最后的可靠时机。当然 onPause()方法不能做大量的操作,否则会影响下一个 Activity 入栈。

全屏显示

onCreate()函数中加入以下代码

        // 设置全屏模式
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        // 若有标题栏,还需去除标题栏
        requestWindowFeature(Window.FEATURE_NO_TITLE);

效果

 

参考鸣谢

郭霖 - 第一行代码(第二版)

详解 Android 的 Activity 组件

Android 组件系列 ----Activity 组件详解

Android 初步之 Android 组件 Activity

随时随地退出程序详解

你应该知道的 Activity 状态的保存与恢复

Android中Activity数据的保存和恢复

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值