Android中应用前后台切换监听的实现详解
作者:TAKWOLF 发布时间:2021-12-28 17:59:36
前言
最近在工作中遇到了这么一个需求:如何实现 Android 应用前后台切换的监听?下面来一起看看详细的介绍:
iOS 内边是可以实现的,AppDelegate 给了一个回调监听:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
}
我保留了系统注释。一个iOS应用周期,大概的流程是这样的。
应用从前台进入到后台:
applicationWillResignActive() -> applicationDidEnterBackground()
应用从后台恢复到前台:
applicationWillEnterForeground() -> applicationDidBecomeActive()
Android 中也存在 Application,但是并没有提供前后台切换的监听。
倒不如说,在 Android 中,压根就没有应用前后台的概念。
Android 中基本页面单位是 Activity。
Activity 有自己的生命周期,但是 Application 却没有一个整体的生命周期。
我们可以通过监听 Activity 的生命周期,来模拟实现一个 Application 的生命周期。
Activity 的生命周期不在阐述,写过 Android 的都应该知道。
我们假设现在有两个 Activity 分别是 A 和 B,A 是启动页面,那么生命周期回调是这样的:(我们忽略掉一些不关心的回调)
A 被启动或者 A 进入前台
A.onStart()
A.onResume()
从 A 跳转到 B:
A.onPause()
B.onStart()
B.onResume()
A.onStop()
从 B 返回 A:
B.onPause()
A.onStart()
A.onResume()
B.onStop()
A 被关闭或者 A 进入后台
A.onPause()
A.onStop()
注意上面两个页面回调的启动顺序。
onResume 和 onPause 是一组,两个页面之间是顺序调用。
onStart 和 onStop 是一组,两个页面之间是交叉调用。
也就是说,A 启动到 B,会先调用 B.onStart()
,然后再调用 A.onStop()
;而 B 返回 A 则是相反的,会先调用 A.onStart()
,然后再调用 B.onStop()
。
利用这个特性,我们可以做一个全局计数器,来记录前台页面的数量,在所有 Activity.onStart()
中计数器 +1,在所有 Activity.onStop()
中计数器 -1。计数器数目大于0,说明应用在前台;计数器数目等于0,说明应用在后台。计数器从1变成0,说明应用从前台进入后台;计数器从0变成1,说明应用从后台进入前台。
有了思路,我们来实现。
Application 提供了一个 * 用于监听整个应用中 Activity 声明周期:Application.ActivityLifecycleCallbacks
。
这个 * 要求 API >= 14。对应 API < 14 的情况,可以通过编写一个 BaseActivity,然后让所有的 Activity 都集成这个类来实现整个应用 Activity 声明周期的监听,效果是相同的。
API >= 14,实现如下:
public class ApplicationListener implements Application.ActivityLifecycleCallbacks {
private int foregroundCount = 0; // 位于前台的 Activity 的数目
@Override
public void onActivityStarted(final Activity activity) {
if (foregroundCount <= 0) {
// TODO 这里处理从后台恢复到前台的逻辑
}
foregroundCount++;
}
@Override
public void onActivityStopped(Activity activity) {
foregroundCount--;
if (foregroundCount <= 0) {
// TODO 这里处理从前台进入到后台的逻辑
}
}
/*
* 下面回调,我们都不需要
*/
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
@Override
public void onActivityResumed(Activity activity) {}
@Override
public void onActivityPaused(Activity activity) {}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
@Override
public void onActivityDestroyed(Activity activity) {}
}
我们在 Application 中注册这个 * 来发挥效果:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ApplicationListener());
}
}
对于 API < 14 的情况,BaseActivity 实现如下:
public class BaseActivity extends AppCompatActivity {
private static int foregroundCount = 0; // 注意是个静态变量
@Override
protected void onStart() {
super.onStart();
if (foregroundCount <= 0) {
// TODO 这里处理从后台恢复到前台的逻辑
}
foregroundCount++;
}
@Override
protected void onStop() {
foregroundCount--;
if (foregroundCount <= 0) {
// TODO 这里处理从前台进入到后台的逻辑
}
super.onStop();
}
}
来源:http://blog.takwolf.com/2017/06/29/android-application-foreground-and-background-switch-listener/
猜你喜欢
- 1、返回字符串,Model传输数据/** * 返回String * @param m
- private void deletefileOrDic(System.IO.DirectoryInfo path)
- 对象POJO和JSON互转public class JsonUtil { /** * JSON 转 POJO &n
- 二维码是越来越流行了,很多地方都有可能是使用到。如果是静态的二维码还是比较好处理的,通过在线工具就可以直接生成一张二维码图片,比如:草料二维
- 我本地的springboot版本是2.5.1,后面的分析都是基于这个版本 <parent> &nbs
- 前言之前做的几个微信小程序项目,大部分客户都有要在微信小程序前端提现的需求。提现功能的实现,自然使用企业付款接口,不过这个功能开通比较麻烦,
- 这篇文章主要介绍了Spring框架实现AOP添加日志记录功能过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习
- 声明式事务回顾事务事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!事务管理是企业级应用程序开发中必备技术,用来确保数据的完整
- hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它为我们的编程提供便利的同时也带来了很多危险.这篇文章我们
- 实践过程效果代码public partial class Form1 : Form{ public Form1()
- 本文章向大家介绍JAVA爬取天天基金网数据,主要包括JAVA爬取天天基金网数据使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参
- 简介Quartz是一款功能强大的任务调度器,可以实现较为复杂的调度功能,如每月一号执行、每天凌晨执行、每周五执行等等,还支持分布式调度。本文
- 建议缓存放到 service 层,你可以自定义自己的 BaseServiceImpl 重写注解父类方法,继承自己的实现。为了方便,这里我们将
- 本文实例讲述了Java Lambda表达式与匿名内部类的联系和区别。分享给大家供大家参考,具体如下:一 点睛Lambda表达式与匿名内部类存
- 一、创建web项目1、打开idea软件,点击界面上的Create New Project2、进入如下界面。选中 java Enterpris
- 声明:作者是根据 Hongyang的博客自己实践之后,根据自己的理解写的,有什么不对的地方还望指正。 先放两张效果图 一、准备由于Andro
- 本文实例为大家分享了java绘制五子棋棋盘的具体代码,供大家参考,具体内容如下源码:import javax.imageio.ImageIO
- 微信支付流程都是我自己工作中开发的,亲测可用,不喜勿喷。controller中我是这么写的,你们需要根据自己的业务需求改动。Response
- 图1如图1,我们工作过程中,无论平台网站还是企业官网,总少不了新闻展示。如某天产品经理跟我们说,推广人员想要抓取百度新闻中热点要闻版块提高站
- LRU简介LRU是Least Recently Used 近期最少使用算法,它就可以将长时间没有被利用的数据进行删除。实现最近面了阿里的外包