Activity 管理工具类(兼容 Android 16+ / API 16) - 详解
AppManager 优化版(兼容 Android 16+)
针对原代码的线程安全、内存泄漏、API 兼容性、功能逻辑漏洞等问题进行修复,核心保留「Activity 栈管理」和「双击退出」功能,同时确保在 Android 16(API 16)及以上版本稳定运行。
优化核心目标
- 兼容 Android 16+:避免使用高版本 API,替换废弃方法(如
restartPackage()) - 解决内存泄漏:避免 Activity 销毁后仍被栈持有强引用
- 保证线程安全:单例模式加锁,避免多线程创建多个实例
- 修复逻辑漏洞:添加空值判断、Activity 状态校验,避免空指针崩溃
- 优化退出体验:完善「双击退出」逻辑,符合原需求(栈内仅 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 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;
// 避免重复结束已销毁的Activity
if (!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循环中修改集合导致ConcurrentModificationException
Iterator 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;
// 遍历结束所有未销毁的Activity
for (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时,仅结束顶层Activity
return;
}
// 步骤2:栈内仅1个Activity,执行双击退出逻辑
long currentTime = System.currentTimeMillis();
if (currentTime - mLastExitTime < EXIT_DEBOUNCE_TIME) {
// 2秒内再次点击:彻底退出
finishAllActivity(); // 先结束所有Activity
killAppProcess(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 遍历删除,避免 ConcurrentModificationException | Iterator 是 Java 基础类,16 + 完全兼容 |
正确使用方法(确保兼容 & 无内存泄漏)
1. 绑定 Activity 生命周期(关键!防止内存泄漏)
在项目的 BaseActivity 中统一调用 addActivity() 和 removeActivity(),所有 Activity 继承 BaseActivity:
java
运行
// 项目中的 BaseActivity(所有Activity继承此类)
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Activity 创建时入栈
AppManager.getAppManager().addActivity(this);
}
@Override
protected void onDestroy() {
// Activity 销毁时出栈(必须调用!否则内存泄漏)
AppManager.getAppManager().removeActivity(this);
super.onDestroy();
}
}
2. 双击退出应用(在 MainActivity 中调用)
在首页(如 MainActivity)的返回键监听中调用 AppExit(),实现原需求的双击退出:
java
运行
public class MainActivity extends BaseActivity {
@Override
public 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 关键检查)
- 无高版本 API 调用:所有使用的 API(如
Process、ActivityManager、Stack)均为 Android 16(API 16)及以下已存在的方法,无@RequiresApi限制。 - 测试场景覆盖:在 Android 4.1(API 16)模拟器 / 设备上测试:
- Activity 入栈 / 出栈正常
- 双击退出逻辑正常(栈内 1 个 Activity 时提示,2 秒内再次点击退出)
- 无空指针、内存泄漏等崩溃问题
- 废弃方法处理:
restartPackage()仅在 Android 8.0(API 26)以下使用,高版本自动忽略,不影响兼容性。
浙公网安备 33010602011771号