Android Jetpack系列之Lifecycle

简介: Android Jetpack系列之Lifecycle

前言

Lifecycle是Jetpack架构组件中用来感知生命周期的组件,使用Lifecycles可以帮助我们写出和生命周期相关更简洁更易维护的代码。

生命周期

生命周期这个简单而又重要的知识相信大家早已耳熟能详。假设我们现在有这样一个简单需求:

这个需求只是一个实例,在真实的开发中当然不可能有这样的需要:

在Activity 可见的时候,我们去做一个计数功能,每隔一秒 将计数加1 ,当Activity不可见的时候停止计数,当Activity被销毁的时候 将计数置为0

OK,So easy~ ,新建Main3Activity 编写代码如下所示:

public class Main3Activity extends AppCompatActivity {
    private static final String TAG = "Main3Activity";
    int count = 0;
    /**
     * 是否计数
     */
    private boolean whetherToCount = true;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
    }
    @Override
    protected void onResume() {
        super.onResume();
        whetherToCount = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (whetherToCount) {
                    try {
                        Thread.sleep(1000);
                        count++;
                        Log.d(TAG, "onResume: " + count);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: ----");
        whetherToCount = false;
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        whetherToCount = false;
        count = 0;
    }
}

image.gif

运行结果如下所示:

image.gif

符合我们的预期,你可能鄙视的看了我一眼,这样多臃肿啊,我可是学过面向对象的人,所以你把工作放在了一个名为WorkUtil的类中

public class WorkUtil {
    private static final String TAG = "WorkUtil";
    private boolean whetherToCount = true;
    private int count = 0;
    public void start() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (whetherToCount) {
                    try {
                        Thread.sleep(1000);
                        count++;
                        Log.d(TAG, "start: " + count);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
    public void onStop() {
        whetherToCount = false;
    }
    public void onDestory() {
        count = 0;
    }
}

image.gif

然后再activity中的生命周期中分别执行对应的方法,感觉美滋滋~

然而 ,这样还是不够解耦,如果方法过多的话 ,会让view中的代码越来越臃肿,那么 还有更好的方案吗?这就是今天所说的Lifecycle。我们待会回过头来再优化上面的代码。

使用Lifecycle管理生命周期

我们通过改写WorkUtil类来讲解如何使用Lifecycle,让WorkUtil类实现LifecycleObserver

我们通过OnLifecycleEvent注解来注明方法所执行的生命周期,如下所示:

public class WorkUtil implements LifecycleObserver {
    private static final String TAG = "WorkUtil";
    private boolean whetherToCount = true;
    private int count = 0;
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void start() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (whetherToCount) {
                    try {
                        Thread.sleep(1000);
                        count++;
                        Log.d(TAG, "start: " + count);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onStop() {
        whetherToCount = false;
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestory() {
        count = 0;
    }
}

image.gif

在Activity中注册即可:

getLifecycle().addObserver(new WorkUtil());

image.gif

image.gif

这样是不是简洁多了呢,那么我们为什么可以在Activity中直接使用getLifecycle().addObserver(new WorkUtil());呢,其实使用的是LifecycleOwner.getLifecycle, LifecycleOwner是单一方法接口,表示类具有 Lifecycle,而如果activity继承自AppcompatActivity或Fragment继承自androidx.fragment.app.Fragment他们本身就是一个LifecycleOwner的实例,这是AndroidX库帮我们自动完成的。

自定义LifecycleOwner

如果我们的Activity由于各种原因继承的不是AppcompatActivity而是Activity呢

image.gif

我们可以看到这个时候,就不能直接使用getLifecycle,而要自定义一个LifecycleOwner了,我们让Activity继承自LifecycleOwner,

使用LifecycleRegistry定义如下:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main3);
    lifecycleRegistry = new LifecycleRegistry(this);
    getLifecycle().addObserver(new WorkUtil());
}

image.gif

@NonNull
@Override
public Lifecycle getLifecycle() {
    return lifecycleRegistry;
}

image.gif

这样我们就实现了自定义LifecycleOwner了,不过大多数时候我们还是不需要自定义的。

优雅的检测应用程序前后台状态

很多业务中我们都需要监听应用前后台的状态 ,比如在前台的时候开始缓存任务,在后台的时候停止缓存任务,其实方法有很多,比如

使用我们上面所说的方法,监听BaseActivity,但是都不够优雅,如果我们想监听所有Activty的生命周期就要使用ActivityLifecycleCallbacks,我们新建ForegroundCallbacks类实现ActivityLifecycleCallbacks

public class ForegroundCallbacks implements Application.ActivityLifecycleCallbacks {
    private static final String TAG = "ForegroundCallbacks";
    @Override
    public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
        Log.d(TAG, "onActivityCreated: " + activity.getComponentName());
    }
    @Override
    public void onActivityStarted(@NonNull Activity activity) {
        Log.d(TAG, "onActivityStarted: "+ activity.getComponentName());
    }
    @Override
    public void onActivityResumed(@NonNull Activity activity) {
        Log.d(TAG, "onActivityResumed: "+ activity.getComponentName());
    }
    @Override
    public void onActivityPaused(@NonNull Activity activity) {
        Log.d(TAG, "onActivityPaused: "+ activity.getComponentName());
    }
    @Override
    public void onActivityStopped(@NonNull Activity activity) {
        Log.d(TAG, "onActivityStopped: "+ activity.getComponentName());
    }
    @Override
    public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
        Log.d(TAG, "onActivitySaveInstanceState: "+ activity.getComponentName());
    }
    @Override
    public void onActivityDestroyed(@NonNull Activity activity) {
        Log.d(TAG, "onActivityDestroyed: "+ activity.getComponentName());
    }
}

image.gif

添加一个初始化的方法:

/**
 * 初始化foregroundCallbacks
 *
 * @param appApplication application
 */
public static ForegroundCallbacks init(AppApplication appApplication) {
    instance = new ForegroundCallbacks();
    appApplication.registerActivityLifecycleCallbacks(instance);
    return instance;
}

image.gif

在Application中进行注册:

ForegroundCallbacks.init(this);

image.gif

运行项目日志如下:

image.gif

现在我们知道肯定要在onActivityResumed和onActivityPaused两个方法中进行判断,但是肯定不是说进入到了resumed就是在前台,进入到了paused就是后台,因为我们的应用会有多个activity,只有第一个activity在前台的时候我们才提示在前台,只有所有activity都不可见的时候才提示在后台,按照这种思路我们编写对应的处理

首先定义个接口 里面回调在前台或在后台的方法

public interface Listener {
    /**
     * 在前台
     */
    public void onBecameForeground();
    /**
     * 在后台
     */
    public void onBecameBackground();
}

image.gif

定义标记位

private Runnable runnable;
/**
 * 是否执行过onResumed
 */
private boolean onResumed = false;
/**
 * 是否执行过onPaused
 */
private boolean onPaused = true;

image.gif

@Override
public void onActivityResumed(@NonNull Activity activity) {
    Log.d(TAG, "onActivityResumed: " + activity.getComponentName());
    onPaused = false;
    if (runnable != null){
        handler.removeCallbacks(runnable);
    }
    handler.postDelayed(runnable = new Runnable() {
        @Override
        public void run() {
            if (!onResumed) {
                listener.onBecameForeground();
                onResumed = true;
            }
        }
    },600);
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
    Log.d(TAG, "onActivityPaused: " + activity.getComponentName());
    onPaused = true;
    if (runnable != null){
        handler.removeCallbacks(runnable);
    }
    handler.postDelayed(runnable = new Runnable() {
        @Override
        public void run() {
            if (onResumed && onPaused) {
                onResumed = false;
                listener.onBecameBackground();
            }
        }
    }, 600);
}

image.gif

在这里我们进行延迟0.6s的原因是为了避免启动新的activity 旧的activity页面不可见时误以为在后台,不过在真实的业务场景中还是需要按照细节进行优化,在applicaton添加事件回调

ForegroundCallbacks.init(this).addListener(new ForegroundCallbacks.Listener() {
    @Override
    public void onBecameForeground() {
        Log.d(TAG, "onBecameForeground: 在前台");
    }
    @Override
    public void onBecameBackground() {
        Log.d(TAG, "onBecameBackground: 在后台");
    }
});

image.gif

运行程序切换到后台 再切换回来 结果如下所示:

image.gif

如此 我们就可以优雅的监听应用前后台切换了。

是否感受到Lifecycle的强大了呢?

目录
相关文章
|
6月前
|
安全 Java Android开发
安卓开发中的新趋势:Kotlin与Jetpack的完美结合
【6月更文挑战第20天】在不断进化的移动应用开发领域,Android平台以其开放性和灵活性赢得了全球开发者的青睐。然而,随着技术的迭代,传统Java语言在Android开发中逐渐显露出局限性。Kotlin,一种现代的静态类型编程语言,以其简洁、安全和高效的特性成为了Android开发中的新宠。同时,Jetpack作为一套支持库、工具和指南,旨在帮助开发者更快地打造优秀的Android应用。本文将探讨Kotlin与Jetpack如何共同推动Android开发进入一个新的时代,以及这对开发者意味着什么。
|
2月前
|
测试技术 数据库 Android开发
深入解析Android架构组件——Jetpack的使用与实践
本文旨在探讨谷歌推出的Android架构组件——Jetpack,在现代Android开发中的应用。Jetpack作为一系列库和工具的集合,旨在帮助开发者更轻松地编写出健壮、可维护且性能优异的应用。通过详细解析各个组件如Lifecycle、ViewModel、LiveData等,我们将了解其原理和使用场景,并结合实例展示如何在实际项目中应用这些组件,提升开发效率和应用质量。
54 6
|
3月前
|
编译器 Android开发 开发者
带你了解Android Jetpack库中的依赖注入框架:Hilt
本文介绍了Hilt,这是Google为Android开发的依赖注入框架,基于Dagger构建,旨在简化依赖注入过程。Hilt通过自动化的组件和注解减少了DI的样板代码,提高了应用的可测试性和可维护性。文章详细讲解了Hilt的主要概念、基本用法及原理,帮助开发者更好地理解和应用Hilt。
96 8
|
3月前
|
安全 Java Android开发
探索安卓应用开发的新趋势:Kotlin和Jetpack Compose
在安卓应用开发领域,随着技术的不断进步,新的编程语言和框架层出不穷。Kotlin作为一种现代的编程语言,因其简洁性和高效性正逐渐取代Java成为安卓开发的首选语言。同时,Jetpack Compose作为一个新的UI工具包,提供了一种声明式的UI设计方法,使得界面编写更加直观和灵活。本文将深入探讨Kotlin和Jetpack Compose的特点、优势以及如何结合使用它们来构建现代化的安卓应用。
88 4
|
5月前
|
存储 数据库 Android开发
🔥Android Jetpack全解析!拥抱Google官方库,让你的开发之旅更加顺畅无阻!🚀
【7月更文挑战第28天】在Android开发中追求高效稳定的路径?Android Jetpack作为Google官方库集合,是你的理想选择。它包含多个独立又协同工作的库,覆盖UI到安全性等多个领域,旨在减少样板代码,提高开发效率与应用质量。Jetpack核心组件如LiveData、ViewModel、Room等简化了数据绑定、状态保存及数据库操作。引入Jetpack只需在`build.gradle`中添加依赖。例如,使用Room进行数据库操作变得异常简单,从定义实体到实现CRUD操作,一切尽在掌握之中。拥抱Jetpack,提升开发效率,构建高质量应用!
94 4
|
5月前
|
存储 移动开发 Android开发
使用kotlin Jetpack Compose框架开发安卓app, webview中h5如何访问手机存储上传文件
在Kotlin和Jetpack Compose中,集成WebView以支持HTML5页面访问手机存储及上传音频文件涉及关键步骤:1) 添加`READ_EXTERNAL_STORAGE`和`WRITE_EXTERNAL_STORAGE`权限,考虑Android 11的分区存储;2) 配置WebView允许JavaScript和文件访问,启用`javaScriptEnabled`、`allowFileAccess`等设置;3) HTML5页面使用`<input type="file">`让用户选择文件,利用File API;
|
6月前
|
JavaScript Java Android开发
kotlin安卓在Jetpack Compose 框架下跨组件通讯EventBus
**EventBus** 是一个Android事件总线库,简化组件间通信。要使用它,首先在Gradle中添加依赖`implementation &#39;org.greenrobot:eventbus:3.3.1&#39;`。然后,可选地定义事件类如`MessageEvent`。在活动或Fragment的`onCreate`中注册订阅者,在`onDestroy`中反注册。通过`@Subscribe`注解方法处理事件,如`onMessageEvent`。发送事件使用`EventBus.getDefault().post()`。
|
6月前
|
安全 JavaScript 前端开发
kotlin开发安卓app,JetPack Compose框架,给webview新增一个按钮,点击刷新网页
在Kotlin中开发Android应用,使用Jetpack Compose框架时,可以通过添加一个按钮到TopAppBar来实现WebView页面的刷新功能。按钮位于右上角,点击后调用`webViewState?.reload()`来刷新网页内容。以下是代码摘要:
|
6月前
|
Android开发
Jetpack Compose: Hello Android
Jetpack Compose: Hello Android
|
7月前
|
存储 安全 Android开发
构建高效的Android应用:Kotlin与Jetpack的结合
【5月更文挑战第31天】 在移动开发的世界中,Android 平台因其开放性和广泛的用户基础而备受开发者青睐。随着技术的进步和用户需求的不断升级,开发一个高效、流畅且易于维护的 Android 应用变得愈发重要。本文将探讨如何通过结合现代编程语言 Kotlin 和 Android Jetpack 组件来提升 Android 应用的性能和可维护性。我们将深入分析 Kotlin 语言的优势,探索 Jetpack 组件的核心功能,并通过实例演示如何在实际项目中应用这些技术。