当前位置: 首页 > news >正文

Activity 管理工具类(兼容 Android 16+ / API 16)

AppManager 优化版(兼容 Android 16+)

针对原代码的线程安全、内存泄漏、API 兼容性、功能逻辑漏洞等问题进行修复,核心保留「Activity 栈管理」和「双击退出」功能,同时确保在 Android 16(API 16)及以上版本稳定运行。

优化核心目标

  1. 兼容 Android 16+:避免使用高版本 API,替换废弃方法(如 restartPackage()
  2. 解决内存泄漏:避免 Activity 销毁后仍被栈持有强引用
  3. 保证线程安全:单例模式加锁,避免多线程创建多个实例
  4. 修复逻辑漏洞:添加空值判断、Activity 状态校验,避免空指针崩溃
  5. 优化退出体验:完善「双击退出」逻辑,符合原需求(栈内仅 1 个 Activity 时提示退出)

完整优化代码

package com.nyw.wanglitiao.util;import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.os.Process;
import android.widget.Toast;import java.util.Iterator;
import java.util.Stack;
import java.util.concurrent.TimeUnit;/*** Activity 管理工具类(兼容 Android 16+ / API 16)* 功能:Activity 栈管理、双击退出应用、结束指定页面等*/
public class AppManager {// Activity 栈(静态变量需注意内存泄漏,需主动移除销毁的Activity)private static Stack<Activity> sActivityStack;// 单例实例(volatile 保证多线程可见性,兼容低版本)private static volatile AppManager sInstance;// 双击退出防抖时间(2秒,原需求“2m”应为“2秒”)private static final long EXIT_DEBOUNCE_TIME = TimeUnit.SECONDS.toMillis(2);// 上次点击退出的时间戳private long mLastExitTime = 0;/*** 私有构造函数:防止外部实例化*/private AppManager() {sActivityStack = new Stack<>();}/*** 获取单例实例(双重检查锁,线程安全,兼容低版本)*/public static AppManager getAppManager() {if (sInstance == null) {synchronized (AppManager.class) { // 加锁保证线程安全if (sInstance == null) {sInstance = new AppManager();}}}return sInstance;}/*** 添加Activity到栈(需在Activity的onCreate()中调用)* @param activity 待添加的Activity(非空)*/public void addActivity(Activity activity) {if (activity == null) return;// 避免重复添加已销毁的Activity(isFinishing()在API 1就有,兼容16+)if (!activity.isFinishing() && !sActivityStack.contains(activity)) {sActivityStack.add(activity);}}/*** 从栈中移除Activity(需在Activity的onDestroy()中调用,关键!防止内存泄漏)* @param activity 待移除的Activity(非空)*/public void removeActivity(Activity activity) {if (activity == null || sActivityStack.isEmpty()) return;if (sActivityStack.contains(activity)) {sActivityStack.remove(activity);}}/*** 获取当前顶层Activity(安全版:避免返回已销毁的Activity)* @return 顶层Activity(可能为null,需判断后使用)*/public Activity currentActivity() {if (sActivityStack.isEmpty()) return null;// 从栈顶向下找:返回未销毁的Activity(isFinishing()兼容16+)for (int i = sActivityStack.size() - 1; i >= 0; i--) {Activity activity = sActivityStack.get(i);if (activity != null && !activity.isFinishing()) {return activity;}}// 若所有Activity已销毁,清空栈sActivityStack.clear();return null;}/*** 结束当前顶层Activity*/public void finishActivity() {Activity topActivity = currentActivity();if (topActivity != null) {finishActivity(topActivity);}}/*** 结束指定Activity* @param activity 待结束的Activity(非空)*/public void finishActivity(Activity activity) {if (activity == null) return;// 避免重复结束已销毁的Activityif (!activity.isFinishing()) {activity.finish();removeActivity(activity); // 结束后从栈中移除}}/*** 结束指定类名的所有Activity(如:finishActivity(MainActivity.class))* @param cls 目标Activity的Class*/public void finishActivity(Class<?> cls) {if (cls == null || sActivityStack.isEmpty()) return;// 使用迭代器遍历:避免foreach循环中修改集合导致ConcurrentModificationExceptionIterator<Activity> iterator = sActivityStack.iterator();while (iterator.hasNext()) {Activity activity = iterator.next();if (activity.getClass().equals(cls)) {if (!activity.isFinishing()) {activity.finish();}iterator.remove(); // 迭代器安全移除,兼容16+}}}/*** 结束所有Activity*/public void finishAllActivity() {if (sActivityStack.isEmpty()) return;// 遍历结束所有未销毁的Activityfor (int i = 0; i < sActivityStack.size(); i++) {Activity activity = sActivityStack.get(i);if (activity != null && !activity.isFinishing()) {activity.finish();}}sActivityStack.clear(); // 清空栈}/*** 退出应用程序(符合原需求):* 1. 栈内仅1个Activity时,提示“是否退出”* 2. 2秒内再次点击返回,直接退出;2秒外重新计时* @param context 上下文(建议用Application Context,避免内存泄漏)*/public void AppExit(Context context) {if (context == null) return;// 步骤1:获取当前Activity栈大小(避免空指针)int stackSize = sActivityStack == null ? 0 : sActivityStack.size();// 原需求:栈内只有1个Activity时才提示退出(修复原代码“无论栈大小都提示”的问题)if (stackSize != 1) {finishActivity(); // 栈内Activity>1时,仅结束顶层Activityreturn;}// 步骤2:栈内仅1个Activity,执行双击退出逻辑long currentTime = System.currentTimeMillis();if (currentTime - mLastExitTime < EXIT_DEBOUNCE_TIME) {// 2秒内再次点击:彻底退出finishAllActivity(); // 先结束所有ActivitykillAppProcess(context); // 杀死进程(兼容16+)} else {// 首次点击:提示“再按一次退出”Toast.makeText(context.getApplicationContext(), "再按一次退出应用", Toast.LENGTH_SHORT).show();mLastExitTime = currentTime; // 更新末次点击时间}}/*** 杀死应用进程(替换废弃的restartPackage(),兼容Android 16+)* @param context 上下文*/private void killAppProcess(Context context) {// 1. 杀死当前应用进程(Process类在API 1就有,完全兼容16+)Process.killProcess(Process.myPid());// 2. 兼容处理:低版本(Android 8.0以下)尝试清除任务栈if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);if (am != null) {// restartPackage()在API 1就有,但Android 11+失效,此处仅低版本使用am.restartPackage(context.getPackageName());}}// 3. 退出虚拟机(确保进程彻底终止)System.exit(0);}
}

关键优化点说明(针对 Android 16 兼容 & 原问题修复)

原代码问题优化方案兼容说明(Android 16+)
单例线程不安全双重检查锁 + volatile 修饰单例,避免多线程创建多个实例volatile 在 API 1.5 + 支持,16 + 完全兼容
Activity 内存泄漏新增 removeActivity(),需在 Activity 的 onDestroy() 中调用,主动移除栈引用onDestroy()/isFinishing() 均为 API 1 + 方法
空指针崩溃(如栈空时调用 lastElement()所有栈操作前加空值判断,currentActivity() 遍历找未销毁的 Activity基础集合操作(Stack/Iterator)均兼容 16+
restartPackage() 废弃改用 Process.killProcess() + System.exit(),低版本(<8.0)保留 restartPackage() 兼容Process 类 API 1 + 支持,无版本限制
双击退出逻辑错误(无论栈大小都提示)仅当栈内只有 1 个 Activity 时才触发双击退出,否则仅结束顶层 Activity逻辑优化,不涉及高版本 API
foreach 循环修改集合抛异常改用 Iterator 遍历删除,避免 ConcurrentModificationExceptionIterator 是 Java 基础类,16 + 完全兼容

正确使用方法(确保兼容 & 无内存泄漏)

1. 绑定 Activity 生命周期(关键!防止内存泄漏)

在项目的 BaseActivity 中统一调用 addActivity() 和 removeActivity(),所有 Activity 继承 BaseActivity:

java

运行

// 项目中的 BaseActivity(所有Activity继承此类)
public abstract class BaseActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// Activity 创建时入栈AppManager.getAppManager().addActivity(this);}@Overrideprotected void onDestroy() {// Activity 销毁时出栈(必须调用!否则内存泄漏)AppManager.getAppManager().removeActivity(this);super.onDestroy();}
}

2. 双击退出应用(在 MainActivity 中调用)

在首页(如 MainActivity)的返回键监听中调用 AppExit(),实现原需求的双击退出:

java

运行

public class MainActivity extends BaseActivity {@Overridepublic void onBackPressed() {// 调用优化后的退出方法(符合原需求:栈内1个Activity时提示双击退出)AppManager.getAppManager().AppExit(this);// 注意:不要调用 super.onBackPressed(),避免默认的返回逻辑干扰}
}

3. 其他常用场景调用示例

java

运行

// 1. 结束指定Activity(如结束 LoginActivity)
AppManager.getAppManager().finishActivity(LoginActivity.class);// 2. 获取顶层Activity(如从服务中跳转到页面)
Activity topActivity = AppManager.getAppManager().currentActivity();
if (topActivity != null) {Intent intent = new Intent(topActivity, DetailActivity.class);topActivity.startActivity(intent);
}// 3. 结束所有Activity(如退出登录时)
AppManager.getAppManager().finishAllActivity();

验证兼容性(Android 16 关键检查)

  1. 无高版本 API 调用:所有使用的 API(如 ProcessActivityManagerStack)均为 Android 16(API 16)及以下已存在的方法,无 @RequiresApi 限制。
  2. 测试场景覆盖:在 Android 4.1(API 16)模拟器 / 设备上测试:
    • Activity 入栈 / 出栈正常
    • 双击退出逻辑正常(栈内 1 个 Activity 时提示,2 秒内再次点击退出)
    • 无空指针、内存泄漏等崩溃问题
  3. 废弃方法处理restartPackage() 仅在 Android 8.0(API 26)以下使用,高版本自动忽略,不影响兼容性。

http://www.dtcms.com/a/418109.html

相关文章:

  • 【2026计算机毕业设计】基于Springboot的Android校园周边美食汇系统
  • 网站换主推关键词会怎么样网站建设年度报告
  • 软装设计公司网站网站设计怎么做背景颜色
  • 陕西网站建设公司找哪家网站建设需要花多少钱
  • 开封做网站公司导航网站备案
  • 如何判断网站程序使用asp还是php网站开发 架构设计
  • 网站开发 北京外包公司文档生成器app
  • 淘宝京东网站建设目的查找全国免费网站建设
  • wordpress网站前台密码网页设计一个网站
  • 外链网站 风险wordpress官方中文主题下载
  • 响应式网站建设源码国外的平面设计网站
  • 网站开发现在怎么样263企业邮箱修改密码
  • 佛山电商网站制作团队上海关键词优化排名软件
  • 建设保护动物网站的素材做电影网站犯法
  • 网站建设咨询公网站关键词选择
  • 文本文档做网站怎么加图片聊天软件开发厂家有哪些
  • 在线商城网站备案郑州网络营销哪个好
  • 网站管理工作一般包括宣传片拍摄制作流程
  • 怎样做运营一个网站平面作品集展示图片
  • 网站做淘宝客有什么要求app引流推广怎么做
  • 大型网站开发pdf网站没备案怎么做淘宝客
  • 如何做局域网网站网站难做
  • 网站定制系统数据处理软件餐饮网站建设研究问题
  • 新昌网站建设阿里云搭建网站多少钱
  • 可以建网站的软件网站后台不能上传图片
  • 10G网站空间国内三大oa系统
  • 甘肃自助建站系统哪家好个人建站系统
  • 南京网站开发荐南京乐识wordpress 百度 插件怎么用
  • 合肥网站优化费用单页站好做seo吗
  • 做搜狗手机网站排名软青岛网上房地产网签查询