【安卓笔记】—— 感知生命周期 Lifecycles

教程来源

致谢B站良心Up主,教程地址戳这里

这次的例子我们将使用 “计时器” 控件来演示,先来了解一下计时器的用法。

计时器

计时器是属于 TextView 的子类,来到 Text 界面,直接将 TextView 改为 Chronometer 。
在这里插入图片描述
修改过后,界面便会出现一个时间,前面为分,后面是秒。我们将 id 改为 meter 。
在这里插入图片描述

计时器的常见方法

chronometer.setBase(SystemClock.elapsedRealtime()); //设置基准时间,并从该时间开始计数
// System.currentTimeMillis(); //(UNIX时间 自1970 1-1 到现在的毫秒数)
// SystemClock.elapsedRealtime(); //(系统启动到现在的时间,包含设备深度休眠的时间)
// SystemClock.uptimeMillis(); //(自系统启动时开始计数,毫秒为单位。从系统启动到现在,这个过程中的处于非休眠期的时间。当系统进入深度睡眠时(CPU关闭,设备变黑,等待外部输入装置)该时钟会停止)

chronometer.getBase(); //获取当前设置的基准时间

chronometer.setFormat("计时:%s"); //设置用于显示的格式化字符串(计时器将根据这个字符串来显示,替换字符串中第一个“%s”为当前"MM:SS"或 "H:MM:SS"格式的时间显示。)

chronometer.setCountDown(true); //设置为倒计时模式

chronometer.start(); //计时开始

chronometer.stop(); //停止刷新计时UI更新

前台计时,后台暂停的计时器

来到 MainActivity.java:
一般我们都将系统基准时间设为 SystemClock.elapsedRealtime(),这个时间是手机从上一次启动到现在经过的毫秒数,它只与系统启动有关,较为可靠,并且不设置的话,默认就是用它。

如果我们直接设置了基准时间(setBase)后,就开始计时(start),那么即使软件进入了后台,计时器不会停止,依旧在计时

如果我们想要达到软件在前台计时,后台暂停的效果要怎么做呢?

生命周期中,当软件进入后台会默认调用 onPause(),
在这里,我们用变量 elapsedTime 保存下来了一个时间:
recordingTime = SystemClock.elapsedRealtime() - chronometer.getBase();
// 当前系统时间 - 启动计时器的时间 = 上次计时的持续时间
我们在进入后台前,保存了上次计时的持续时间。
那么在我们再次回到前台时,会调用 onResume(),
此时,我们重新设置了基准时间:
chronometer.setBase(SystemClock.elapsedRealtime() - recordingTime );
// 本该是从0开始,我们跳过已经记录的时间,达到继续计时的效果。

public class MainActivity extends AppCompatActivity {
    Chronometer chronometer;
    private long recordingTime ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        chronometer = findViewById(R.id.meter);

        chronometer.setBase(SystemClock.elapsedRealtime()); // 手机从上一次启动到现在,经过时间的毫秒数,比较可靠,只与系统启动有关,不写就默认为此

    }

    @Override
    protected void onPause() {
        super.onPause();
        recordingTime = SystemClock.elapsedRealtime() - chronometer.getBase(); // 当前系统时间 - 启动时设定的起点时间 = 上次持续计数经过总时间
        chronometer.stop();
    }

    @Override
    protected void onResume() {
        super.onResume();
        chronometer.setBase(SystemClock.elapsedRealtime() - recordingTime );
        chronometer.start(); // 开始计数
    }
}

运行效果:
此时我们已经达到了前台计时,后台停止计时的计时器效果。
在这里插入图片描述

LifeCycles

上面我们虽然实现了计时器功能,但不是很好。我们将代码都放到了 MainActivity.java 中的生命周期中,如果对象少还好,如果对象多,大家都需要处理生命周期相关的行为,那么将会塞下很多代码,十分臃肿。并且这个代码的移植性几乎没有,为了优化这些问题,我们将使用 LifeCycles ,将这些功能放到 LifeCycles 中实现。

首先,创建一个 MyChronometer.java 文件,继承于 android.widget.Chronometer
在这里插入图片描述
创建完成后,默认报错,我们点击小灯泡,Create constructor matching super
在这里插入图片描述
由于我们要将这个对象放到 xml 界面做编辑,我们需要 attrs 属性参数,如下选择,
在这里插入图片描述
MyChronometer.java :我们还需要让他实现一个接口,实现生命周期的观察。

public class MyChronometer extends Chronometer implements LifecycleObserver {
    public MyChronometer(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

以上为 MyChronometer.java 的初始代码,接下来我们要将之前实现的前台计数,后台暂停的计数器功能在这里实现:

实现逻辑与之前一样,在进入后台前,将已经记录的时间保存下来,下次进入前台时,跳过已经记录的时间,实现了继续计时。

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) 是 LifecycleObserver 的特有写法,相当于在 MainActivity.java 中的 onPause() 代码块中写代码。由此可见,在实现了 LifecycleObserver 接口后,我们便可以在另一个类中自由的操纵生命周期了,增强了代码的移植性,并且减少了使得 MainActivity.java 中的代码更加简洁。

public class MyChronometer extends Chronometer implements LifecycleObserver {
    private long recordingTime;
    public MyChronometer(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) // LifecycleObserver 特有写法
    private void pauseMeter(){
        recordingTime = SystemClock.elapsedRealtime() - getBase();
        stop(); // 不写也可以
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    private void resumeMeter(){
        setBase(SystemClock.elapsedRealtime() - recordingTime);
        start();
    }
    
}

在实现了计时器的生命周期后,我们需要去界面布局的 Text 中,将原本的 Chronometer 改为 MyChronometer。
在这里插入图片描述
然后来到 MainActivity.java,这里的代码将会变得十分简洁,关于生命周期的代码我们都不需要在这里实现了。我们在 MyChronometer 中实现了计时器的生命周期,在这里我们需要添加一句观察生命周期的代码:getLifecycle().addObserver(chronometer);

public class MainActivity extends AppCompatActivity {
    MyChronometer chronometer;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        chronometer = findViewById(R.id.meter);
        getLifecycle().addObserver(chronometer);
    }

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萌宅鹿同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值