你知道吗(Android里如何关闭某个指定activity)

最近项目中有这样的需要,在关闭当前Activity同时关闭前面两个Activity,不涉及到应用的退出。自己想了一些方案,也查了一些资料,做个笔记吧。
方案一 广播的方式
这个是最容易想到的,同时也是网上提供最多的。 由于多个Activity要使用,关闭页面的广播最好写在基类BaseActivity中,也可以在各个子页面单独写,但是代码量就增加了。

public class BaseActivity extends Activity { //根据需求定义自己需要关闭页面的action public static final String RECEIVER_ACTION_FINISH_A = "receiver_action_finish_a"; public static final String RECEIVER_ACTION_FINISH_B = "receiver_action_finish_b"; public static final String RECEIVER_ACTION_FINISH_C = "receiver_action_finish_c"; public static final String RECEIVER_ACTION_FINISH_D = "receiver_action_finish_d"; private FinishActivityRecevier mRecevier; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mRecevier = new FinishActivityRecevier(); registerFinishReciver(); } private void registerFinishReciver() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(RECEIVER_ACTION_FINISH_A); intentFilter.addAction(RECEIVER_ACTION_FINISH_B); intentFilter.addAction(RECEIVER_ACTION_FINISH_C); intentFilter.addAction(RECEIVER_ACTION_FINISH_D); registerReceiver(mRecevier, intentFilter); } private class FinishActivityRecevier extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //根据需求添加自己需要关闭页面的action if (RECEIVER_ACTION_FINISH_A.equals(intent.getAction()) || RECEIVER_ACTION_FINISH_B.equals(intent.getAction()) || RECEIVER_ACTION_FINISH_C.equals(intent.getAction()) || RECEIVER_ACTION_FINISH_D.equals(intent.getAction())) { BaseActivity.this.finish(); } } } @Override protected void onDestroy() { if (mRecevier != null) { unregisterReceiver(mRecevier); } super.onDestroy(); } }

发送广播就需要在各个需求子Activity中进行了,这里使用工具类,方便以后多次或者拓展使用,只需要在需求子Activity中直接调用就行。
public class BroadcastUtils { /** * 发送finish页面的广播 * action可以自己根据需要添加 * @param context */ public static void sendFinishActivityBroadcast(Context context) { Intent intent = new Intent(BaseActivity.RECEIVER_ACTION_FINISH_B); context.sendBroadcast(intent); intent = new Intent(BaseActivity.RECEIVER_ACTION_FINISH_C); context.sendBroadcast(intent); } }

优劣:
优点:最常规使用,不会出现内存泄漏,在基类中操作,代码量不多。
缺点:项目中若是需要关闭页面多的话,需要发送大量广播,会降低性能。
方案二 直接static activity方式
这是网上提供的,代码一看就明显的内存泄漏。但是。。。。。。
private static AActivity sInstance; public static AActivity getInstance() { if (sInstance != null) { return sInstance; } return null; } public static void finishActivity() { if (sInstance != null) { sInstance.finish(); } }

内存泄漏明显,之所以有但是,那是因为这种方式让我想到加入弱引用WeakReference的方式。
public class BActivity extends BaseActivity { private static WeakReference sActivityRef; public static void finishActivity() { if (sActivityRef != null && sActivityRef.get() != null) { sActivityRef.get().finish(); } } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_b); sActivityRef = new WeakReference<>(this); Button btnB = (Button) findViewById(R.id.btn_b); btnB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(BActivity.this, CActivity.class)); } }); } }

WeakReference以及JVM相关,虽然WeakReference被static了,生命周期变长了,但是WeakReference关联的对象不受影响的,依然遵循WeakReference在gc时候的规则。
优劣: 优点:代码简单直观,引入WeakReference,解决了内存泄漏问题。 缺点:在每个activity中都要添加,代码量多。(不知是否可抽取到基类中,以后尝试)
方案三 使用集合或者栈的方式
public class FinishActivityManager { private FinishActivityManager() { } private static FinishActivityManager sManager; private List activityList; public static FinishActivityManager getManager() { if (sManager == null) { synchronized (FinishActivityManager.class) { if (sManager == null) { sManager = new FinishActivityManager(); } } } return sManager; } /** * 添加Activity到集合中 */ public void addActivity(Activity activity) { if (activityList == null) { activityList = new LinkedList<>(); } activityList.add(activity); } /** * 关闭指定的Activity */ public void finishActivity(Activity activity) { if (activityList != null && activity != null && activityList.contains(activity)) { //使用迭代器安全删除 for (Iterator it = activityList.iterator(); it.hasNext(); ) { Activity temp = it.next(); // 清理掉已经释放的activity if (temp == null) { it.remove(); continue; } if (temp == activity) { it.remove(); } } activity.finish(); } } /** * 关闭指定类名的Activity */ public void finishActivity(Class cls) { if (activityList != null) { // 使用迭代器安全删除 for (Iterator it = activityList.iterator(); it.hasNext(); ) { Activity activity = it.next(); // 清理掉已经释放的activity if (activity == null) { it.remove(); continue; } if (activity.getClass().equals(cls)) { it.remove(); activity.finish(); } } } } /** * 关闭所有的Activity */ public void finishAllActivity() { if (activityList != null) { for (Iterator it = activityList.iterator(); it.hasNext(); ) { Activity activity = it.next(); if (activity != null) { activity.finish(); } } activityList.clear(); } } /** * 退出应用程序 */ public void exitApp() { try { finishAllActivity(); // 退出JVM,释放所占内存资源,0表示正常退出 System.exit(0); // 从系统中kill掉应用程序 android.os.Process.killProcess(android.os.Process.myPid()); } catch (Exception e) { e.printStackTrace(); } } }

这种方式注意在删除的时候使用迭代器,否则会出现并发修改异常。 那就来说说但是,应用中要是不使用这种封装的方式去finish掉Activity的时候,封装的manager并不知道,没有断开并释放掉其引用,会引起内存泄漏。所以WeakReference又要出场了。
public class FinishActivityManager { private FinishActivityManager() { } private static FinishActivityManager sManager; private Stack mActivityStack; public static FinishActivityManager getManager() { if (sManager == null) { synchronized (FinishActivityManager.class) { if (sManager == null) { sManager = new FinishActivityManager(); } } } return sManager; } /** * 添加Activity到栈 * @param activity */ public void addActivity(Activity activity) { if (mActivityStack == null) { mActivityStack = new Stack<>(); } mActivityStack.add(new WeakReference<>(activity)); } /** * 检查弱引用是否释放,若释放,则从栈中清理掉该元素 */ public void checkWeakReference() { if (mActivityStack != null) { // 使用迭代器进行安全删除 for (Iterator it = mActivityStack.iterator(); it.hasNext(); ) { WeakReference activityReference = it.next(); Activity temp = activityReference.get(); if (temp == null) { it.remove(); } } } } /** * 获取当前Activity(栈中最后一个压入的) * @return */ public Activity currentActivity() { checkWeakReference(); if (mActivityStack != null && !mActivityStack.isEmpty()) { return mActivityStack.lastElement().get(); } return null; } /** * 关闭当前Activity(栈中最后一个压入的) */ public void finishActivity() { Activity activity = currentActivity(); if (activity != null) { finishActivity(activity); } } /** * 关闭指定的Activity * @param activity */ public void finishActivity(Activity activity) { if (activity != null && mActivityStack != null) { // 使用迭代器进行安全删除 for (Iterator it = mActivityStack.iterator(); it.hasNext(); ) { WeakReference activityReference = it.next(); Activity temp = activityReference.get(); // 清理掉已经释放的activity if (temp == null) { it.remove(); continue; } if (temp == activity) { it.remove(); } } activity.finish(); } } /** * 关闭指定类名的所有Activity * @param cls */ public void finishActivity(Class cls) { if (mActivityStack != null) { // 使用迭代器进行安全删除 for (Iterator it = mActivityStack.iterator(); it.hasNext(); ) { WeakReference activityReference = it.next(); Activity activity = activityReference.get(); // 清理掉已经释放的activity if (activity == null) { it.remove(); continue; } if (activity.getClass().equals(cls)) { it.remove(); activity.finish(); } } } } /** * 结束所有Activity */ public void finishAllActivity() { if (mActivityStack != null) { for (WeakReference activityReference : mActivityStack) { Activity activity = activityReference.get(); if (activity != null) { activity.finish(); } } mActivityStack.clear(); } } /** * 退出应用程序 */ public void exitApp() { try { finishAllActivity(); // 退出JVM,释放所占内存资源,0表示正常退出 System.exit(0); // 从系统中kill掉应用程序 android.os.Process.killProcess(android.os.Process.myPid()); } catch (Exception e) { e.printStackTrace(); } } }

代码一目了然,之所以改成**Stack,**是因为要模仿Activity的任务栈的方式,关闭最后打开的Activity更加方便。 使用的话,在BaseActivity中onCreate()中addActivity,在onDestroy()中finishActivity(),其他功能在各个子Activity中根据需要添加。
优劣:
优点:一劳永逸,一次封装,方便后续使用。
缺点:暂无。
方案四 使用Activity的launchMode
根据Android启动模式,standard和singleTop并不能实现项目需求,故排除。
singleTask和singleInstance在使用的时候会和onActivityResult()有点关系: Android 5.0以上的版本能正常使用,没有冲突; Android 5.0以下的版本有个bug,在调用了startActivityForResult之后立马就会调用onActivityResult,不会等到打开的Activity返回的时候才调用。 项目中很多Activity种都有startActivityForResult,故此种方式排除掉。
方案五 【你知道吗(Android里如何关闭某个指定activity)】使用onActivityResult方式
根据方案四,此方式需要配合launchMode的standard和singleTop使用才能达到效果,所以局限性很大。
方案六 使用Rxbus
Rxbus也是可以实现的,根据自己的需求来决定吧
要是项目中需要关闭Activity不多,不需要发送大量广播,可以使用方案一;方案二和方案三有异曲同工之处,首先推荐方案三;比较之下我在项目中用了方案三。

    推荐阅读