Android 全局工具类 AppHolder:高效管理 Application 和 Activity

  1. 引言

    • 介绍 AppHolder 的作用:全局管理 ApplicationActivity,简化开发。
    • 适用场景:需要全局上下文和生命周期管理的场景。
  2. 功能特性

    • 全局上下文管理。
    • Activity 生命周期监听。
    • Fragment 生命周期监听(可选)。
    • 应用状态判断(是否在前台)。
    • Activity 操作(关闭指定 Activity、关闭所有 Activity 等)。
    • 完全退出应用。

AppHolder

package cn.wandersnail.commons.base;import android.app.Activity;
import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;/*** AppHolder - 全局 Application 和 Activity 管理工具类** 功能:* 1. 全局持有 Application 上下文。* 2. 管理所有 Activity 的生命周期。* 3. 支持 Fragment 生命周期监听。* 4. 提供应用状态判断、Activity 操作等功能。** 使用方式:* 1. 在 Application 中初始化:AppHolder.initialize(this);* 2. 通过 AppHolder.getInstance() 获取单例对象。*/
public class AppHolder extends FragmentManager.FragmentLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {// 单例实例private static final class Holder {private static final AppHolder INSTANCE = new AppHolder();}// 正在运行的 Activity 信息private static class RunningActivity {String name; // Activity 类名WeakReference<Activity> weakActivity; // Activity 弱引用RunningActivity(String name, WeakReference<Activity> weakActivity) {this.name = name;this.weakActivity = weakActivity;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (!(o instanceof RunningActivity)) return false;RunningActivity that = (RunningActivity) o;return name.equals(that.name);}@Overridepublic int hashCode() {return Objects.hash(name);}}// 成员变量private final Map<String, RunningActivity> runningActivities = new ConcurrentHashMap<>(); // 正在运行的 Activityprivate final Map<String, WeakReference<Fragment>> runningFragments = new ConcurrentHashMap<>(); // 正在运行的 Fragmentprivate boolean isCompleteExit = false; // 是否完全退出private Application application; // Application 实例private Looper mainLooper; // 主线程 Looperprivate RunningActivity topActivity; // 栈顶 Activity// 私有构造方法private AppHolder() {mainLooper = Looper.getMainLooper();}/*** 获取 AppHolder 单例实例*/@NonNullpublic static AppHolder getInstance() {return Holder.INSTANCE;}/*** 初始化 AppHolder** @param application Application 实例*/public static void initialize(@NonNull Application application) {Objects.requireNonNull(application, "Application cannot be null");Holder.INSTANCE.application = application;application.registerActivityLifecycleCallbacks(Holder.INSTANCE);}/*** 获取全局上下文*/@NonNullpublic Context getContext() {if (application == null) {throw new IllegalStateException("AppHolder has not been initialized. Call AppHolder.initialize(app) first.");}return application;}/*** 判断当前是否在主线程*/public boolean isMainThread() {return Looper.myLooper() == mainLooper;}/*** 获取主线程 Looper*/@NonNullpublic Looper getMainLooper() {return mainLooper;}/*** 判断应用是否在前台*/public boolean isAppOnForeground() {ActivityManager am = (ActivityManager) application.getSystemService(Context.ACTIVITY_SERVICE);if (am != null) {List<ActivityManager.RunningAppProcessInfo> processes = am.getRunningAppProcesses();if (processes != null) {for (ActivityManager.RunningAppProcessInfo process : processes) {if (application.getPackageName().equals(process.processName)) {return process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;}}}}return false;}/*** 获取栈顶 Activity*/@Nullablepublic Activity getTopActivity() {return topActivity == null ? null : topActivity.weakActivity.get();}/*** 获取所有正在运行的 Activity*/@NonNullpublic List<Activity> getAllActivities() {List<Activity> activities = new ArrayList<>();for (RunningActivity runningActivity : runningActivities.values()) {Activity activity = runningActivity.weakActivity.get();if (activity != null) {activities.add(activity);}}return activities;}/*** 关闭指定 Activity** @param className  目标 Activity 类名* @param classNames 其他目标 Activity 类名(可选)*/public void finish(@NonNull String className, @Nullable String... classNames) {for (RunningActivity runningActivity : runningActivities.values()) {Activity activity = runningActivity.weakActivity.get();if (activity != null && (activity.getClass().getName().equals(className) || contains(classNames, activity.getClass().getName()))) {activity.finish();}}}/*** 关闭所有 Activity*/public void finishAll() {for (RunningActivity runningActivity : runningActivities.values()) {Activity activity = runningActivity.weakActivity.get();if (activity != null) {activity.finish();}}}/*** 完全退出应用*/public void completeExit() {isCompleteExit = true;finishAll();if (runningActivities.isEmpty()) {android.os.Process.killProcess(android.os.Process.myPid());System.exit(0);}}// Activity 生命周期回调@Overridepublic void onActivityCreated(@NonNull Activity activity, Bundle savedInstanceState) {RunningActivity runningActivity = new RunningActivity(activity.getClass().getName(), new WeakReference<>(activity));runningActivities.put(activity.getClass().getName(), runningActivity);topActivity = runningActivity;}@Overridepublic void onActivityDestroyed(@NonNull Activity activity) {runningActivities.remove(activity.getClass().getName());if (isCompleteExit && runningActivities.isEmpty()) {android.os.Process.killProcess(android.os.Process.myPid());System.exit(0);}}// 其他生命周期方法(略)@Overridepublic void onActivityStarted(@NonNull Activity activity) {}@Overridepublic void onActivityResumed(@NonNull Activity activity) {}@Overridepublic void onActivityPaused(@NonNull Activity activity) {}@Overridepublic void onActivityStopped(@NonNull Activity activity) {}@Overridepublic void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {}// Fragment 生命周期回调(略)@Overridepublic void onFragmentCreated(@NonNull FragmentManager fm, @NonNull Fragment f, @Nullable Bundle savedInstanceState) {runningFragments.put(f.getClass().getName(), new WeakReference<>(f));}@Overridepublic void onFragmentDestroyed(@NonNull FragmentManager fm, @NonNull Fragment f) {runningFragments.remove(f.getClass().getName());}// 工具方法:判断数组是否包含某元素private boolean contains(String[] array, String value) {if (array != null) {for (String item : array) {if (item.equals(value)) {return true;}}}return false;}
}
使用示例
// 在 Application 中初始化
public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();AppHolder.initialize(this);}
}// 获取全局上下文
Context context = AppHolder.getInstance().getContext();// 关闭所有 Activity
AppHolder.getInstance().finishAll();// 判断应用是否在前台
boolean isForeground = AppHolder.getInstance().isAppOnForeground();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/72395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyTorch 深度学习实战(14):Deep Deterministic Policy Gradient (DDPG) 算法

在上一篇文章中&#xff0c;我们介绍了 Proximal Policy Optimization (PPO) 算法&#xff0c;并使用它解决了 CartPole 问题。本文将深入探讨 Deep Deterministic Policy Gradient (DDPG) 算法&#xff0c;这是一种用于连续动作空间的强化学习算法。我们将使用 PyTorch 实现 D…

【深度学习与大模型基础】第5章-线性相关与生成子空间

线性相关是指一组向量中&#xff0c;至少有一个向量可以表示为其他向量的线性组合。具体来说&#xff0c;对于向量组 v1,v2,…,vn&#xff0c;如果存在不全为零的标量 c1,c2,…,cn使得&#xff1a; c1v1c2v2…cnvn0 则称这些向量线性相关。否则&#xff0c;它们线性无关。 举…

【Agent实战】货物上架位置推荐助手(RAG方式+结构化prompt(CoT)+API工具结合ChatGPT4o能力Agent项目实践)

本文原创作者:姚瑞南 AI-agent 大模型运营专家,先后任职于美团、猎聘等中大厂AI训练专家和智能运营专家岗;多年人工智能行业智能产品运营及大模型落地经验,拥有AI外呼方向国家专利与PMP项目管理证书。(转载需经授权) 目录 结论 效果图示 1.prompt 2. API工具封…

Go语言入门基础详解

一、语言历史背景 Go语言由Google工程师Robert Griesemer、Rob Pike和Ken Thompson于2007年设计&#xff0c;2009年正式开源。设计目标&#xff1a; 兼具Python的开发效率与C的执行性能内置并发支持&#xff08;goroutine/channel&#xff09;简洁的类型系统现代化的包管理跨…

HarmonyOS NEXT开发进阶(十二):build-profile.json5 文件解析

文章目录 一、前言二、Hvigor脚本文件三、任务与任务依赖图四、多模块管理4.1 静态配置模块 五、分模块编译六、配置多目标产物七、配置APP多目标构建产物八、定义 product 中包含的 target九、拓展阅读 一、前言 编译构建工具DevEco Hvigor&#xff08;以下简称Hvigor&#x…

基于SSM + JSP 的图书商城系统

基于SSM的图书商城 网上书城、图书销售系统、图书销售平台 &#xff5c;Java&#xff5c;SSM&#xff5c;HTML&#xff5c;JSP&#xff5c; 项目采用技术&#xff1a; ①&#xff1a;开发环境&#xff1a;IDEA、JDK1.8、Maven、Tomcat ②&#xff1a;技术栈&#xff1a;Java、…

色板在数据可视化中的创新应用

色板在数据可视化中的创新应用&#xff1a;基于色彩感知理论的优化实践 引言 在数据可视化领域&#xff0c;色彩编码系统的设计已成为决定信息传递效能的核心要素。根据《Nature》期刊2024年发布的视觉认知研究&#xff0c;人类大脑对色彩的识别速度比形状快40%&#xff0c;色…

K8S学习之基础二十七:k8s中daemonset控制器

k8s中DaemonSet控制器 ​ DaemonSet控制器确保k8s集群中&#xff0c;所有节点都运行一个相同的pod&#xff0c;当node节点增加时&#xff0c;新节点也会自动创建一个pod&#xff0c;当node节点从集群移除&#xff0c;对应的pod也会自动删除。删除DaemonSet也会删除创建的pod。…

PyTorch 系列教程:使用CNN实现图像分类

图像分类是计算机视觉领域的一项基本任务&#xff0c;也是深度学习技术的一个常见应用。近年来&#xff0c;卷积神经网络&#xff08;cnn&#xff09;和PyTorch库的结合由于其易用性和鲁棒性已经成为执行图像分类的流行选择。 理解卷积神经网络&#xff08;cnn&#xff09; 卷…

Spring Cloud Stream - 构建高可靠消息驱动与事件溯源架构

一、引言 在分布式系统中&#xff0c;传统的 REST 调用模式往往导致耦合&#xff0c;难以满足高并发和异步解耦的需求。消息驱动架构&#xff08;EDA, Event-Driven Architecture&#xff09;通过异步通信、事件溯源等模式&#xff0c;提高了系统的扩展性与可观测性。 作为 S…

王者荣耀道具页面爬虫(json格式数据)

首先这个和英雄页面是不一样的&#xff0c;英雄页面的图片链接是直接放在源代码里面的&#xff0c;直接就可以请求到&#xff0c;但是这个源代码里面是没有的 虽然在检查页面能够搜索到&#xff0c;但是应该是动态加载的&#xff0c;源码中搜不到该链接 然后就去看看是不是某…

【一起来学kubernetes】12、k8s中的Endpoint详解

一、Endpoint的定义与作用二、Endpoint的创建与管理三、Endpoint的查看与组成四、EndpointSlice五、Endpoint的使用场景六、Endpoint与Service的关系1、定义与功能2、创建与管理3、关系与交互4、使用场景与特点 七、Endpoint的kubectl命令1. 查看Endpoint2. 创建Endpoint3. 编辑…

结构型模式之桥接模式:解耦抽象和实现

在面向对象设计中&#xff0c;我们经常遇到需要扩展某些功能&#xff0c;但又不能修改现有代码的情况。为了避免继承带来的复杂性和维护难度&#xff0c;桥接模式&#xff08;Bridge Pattern&#xff09;应运而生。桥接模式是一种结构型设计模式&#xff0c;旨在解耦抽象部分和…

如何用Java将实体类转换为JSON并输出到控制台?

在软件开发的过程中&#xff0c;Java是一种广泛使用的编程语言&#xff0c;而在众多应用中&#xff0c;数据的传输和存储经常需要使用JSON格式。JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人类阅读和编写&#xff0c;…

Vue3 开发的 VSCode 插件

1. Volar Vue3 正式版发布&#xff0c;Vue 团队官方推荐 Volar 插件来代替 Vetur 插件&#xff0c;不仅支持 Vue3 语言高亮、语法检测&#xff0c;还支持 TypeScript 和基于 vue-tsc 的类型检查功能。 2. Vue VSCode Snippets 为开发者提供最简单快速的生成 Vue 代码片段的方…

C# Enumerable类 之 集合操作

总目录 前言 在 C# 中&#xff0c;System.Linq.Enumerable 类是 LINQ&#xff08;Language Integrated Query&#xff09;的核心组成部分&#xff0c;它提供了一系列静态方法&#xff0c;用于操作实现了 IEnumerable 接口的集合。通过这些方法&#xff0c;我们可以轻松地对集合…

51c自动驾驶~合集54

我自己的原文哦~ https://blog.51cto.com/whaosoft/13517811 #Chameleon 快慢双系统&#xff01;清华&博世最新&#xff1a;无需训练即可解决复杂道路拓扑 在自动驾驶技术中&#xff0c;车道拓扑提取是实现无地图导航的核心任务之一。它要求系统不仅能检测出车道和交…

Spring Cloud Eureka - 高可用服务注册与发现解决方案

在微服务架构中&#xff0c;服务注册与发现是确保系统动态扩展和高效通信的关键。Eureka 作为 Spring Cloud 生态的核心组件&#xff0c;不仅提供去中心化的服务治理能力&#xff0c;还通过自我保护、健康检查等机制提升系统的稳定性&#xff0c;使其成为微服务架构中的重要支撑…

Unity屏幕适配——立项时设置

项目类型&#xff1a;2D游戏、竖屏、URP 其他类型&#xff0c;部分原理类似。 1、确定设计分辨率&#xff1a;750*1334 为什么是它&#xff1f; 因为它是 iphone8 的尺寸&#xff0c;宽高比适中。 方便后续适配到真机的 “更长屏” 或 “更宽屏” 2、在场景…

深度学习中LayerNorm与RMSNorm对比

LayerNorm不同于BatchNorm&#xff0c;其与batch大小无关&#xff0c;均值和方差 在 每个样本的特征维度 C 内计算&#xff0c; 适用于 变长输入&#xff08;如 NLP 任务中的 Transformer&#xff09; 详细的BatchNorm在之前的一篇文章进行了详细的介绍&#xff1a;深度学习中B…