Android开发:关闭某个指定activity

转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0629/8124.html

前言

最近项目中涉及需要在一个Activity中关闭另一个Activity或者在一个Activity中关闭多个Activity的需求,不涉及到应用的退出。自己首先想了一些方案,同时也查了一些方案,就各个方案比较下优劣。

方案一:广播

这个是最容易想到的,同时也是网上提供最多的。 由于多个Activity要使用,关闭页面的广播最好写在基类BaseActivity中,也可以在各个子页面单独写,但是代码量就增加了。

 
  1. public class BaseActivity extends Activity {

  2. //根据需求定义自己需要关闭页面的action

  3. public static final String RECEIVER_ACTION_FINISH_A = "receiver_action_finish_a";

  4. public static final String RECEIVER_ACTION_FINISH_B = "receiver_action_finish_b";

  5. public static final String RECEIVER_ACTION_FINISH_C = "receiver_action_finish_c";

  6. public static final String RECEIVER_ACTION_FINISH_D = "receiver_action_finish_d";

  7. private FinishActivityRecevier mRecevier;

  8. @Override

  9. protected void onCreate(@Nullable Bundle savedInstanceState) {

  10. super.onCreate(savedInstanceState);

  11. mRecevier = new FinishActivityRecevier();

  12. registerFinishReciver();

  13. }

  14. private void registerFinishReciver() {

  15. IntentFilter intentFilter = new IntentFilter();

  16. intentFilter.addAction(RECEIVER_ACTION_FINISH_A);

  17. intentFilter.addAction(RECEIVER_ACTION_FINISH_B);

  18. intentFilter.addAction(RECEIVER_ACTION_FINISH_C);

  19. intentFilter.addAction(RECEIVER_ACTION_FINISH_D);

  20. registerReceiver(mRecevier, intentFilter);

  21. }

  22. private class FinishActivityRecevier extends BroadcastReceiver {

  23. @Override

  24. public void onReceive(Context context, Intent intent) {

  25. //根据需求添加自己需要关闭页面的action

  26. if (RECEIVER_ACTION_FINISH_A.equals(intent.getAction()) ||

  27. RECEIVER_ACTION_FINISH_B.equals(intent.getAction()) ||

  28. RECEIVER_ACTION_FINISH_C.equals(intent.getAction()) ||

  29. RECEIVER_ACTION_FINISH_D.equals(intent.getAction())) {

  30. BaseActivity.this.finish();

  31. }

  32. }

  33. }

  34. @Override

  35. protected void onDestroy() {

  36. if (mRecevier != null) {

  37. unregisterReceiver(mRecevier);

  38. }

  39. super.onDestroy();

  40. }

  41. }

发送广播就需要在各个需求子Activity中进行了,这里使用工具类,方便以后多次或者拓展使用,只需要在需求子Activity中直接调用就行。

 
  1. public class BroadcastUtils {

  2. /**

  3. * 发送finish页面的广播

  4. * action可以自己根据需要添加

  5. * @param context

  6. */

  7. public static void sendFinishActivityBroadcast(Context context) {

  8. Intent intent = new Intent(BaseActivity.RECEIVER_ACTION_FINISH_B);

  9. context.sendBroadcast(intent);

  10. intent = new Intent(BaseActivity.RECEIVER_ACTION_FINISH_C);

  11. context.sendBroadcast(intent);

  12. }

  13. }

优劣: 有点:最常规使用,不会出现内存泄漏,在基类中操作,代码量不多。 缺点:项目中若是需要关闭页面多的话,需要发送大量广播,会降低性能。

方案二:static activity

 
  1. private static AActivity sInstance;

  2. public static AActivity getInstance() {

  3. if (sInstance != null) {

  4. return sInstance;

  5. }

  6. return null;

  7. }

  8. public static void finishActivity() {

  9. if (sInstance != null) {

  10. sInstance.finish();

  11. }

  12. }

缺点明显:内存泄漏。可以改进为弱引用

 
  1. public class BActivity extends BaseActivity {

  2. private static WeakReference<BActivity> sActivityRef;

  3. public static void finishActivity() {

  4. if (sActivityRef != null && sActivityRef.get() != null) {

  5. sActivityRef.get().finish();

  6. }

  7. }

  8. @Override

  9. protected void onCreate(@Nullable Bundle savedInstanceState) {

  10. super.onCreate(savedInstanceState);

  11. setContentView(R.layout.activity_b);

  12. sActivityRef = new WeakReference<>(this);

  13. Button btnB = (Button) findViewById(R.id.btn_b);

  14. btnB.setOnClickListener(new View.OnClickListener() {

  15. @Override

  16. public void onClick(View v) {

  17. startActivity(new Intent(BActivity.this, CActivity.class));

  18. }

  19. });

  20. }

  21. }

纠结点在于,WeakReference被static之后,里面包裹的引用会被影响吗?查了一下WeakReference以及JVM相关,虽然WeakReference被static了,生命周期变长了,但是WeakReference关联的对象不受影响的,依然遵循WeakReference在gc时候的规则。

优劣: 优点:代码简单直观,引入WeakReference,解决了内存泄漏问题。 缺点:在每个activity中都要添加,代码量多。

方案三:集合或栈

 
  1. public class FinishActivityManager extends BaseActivity {

  2. private FinishActivityManager() {

  3. }

  4. private static FinishActivityManager sManager;

  5. private List<Activity> activityList;

  6. public static FinishActivityManager getManager() {

  7. if (sManager == null) {

  8. synchronized (FinishActivityManager.class) {

  9. if (sManager == null) {

  10. sManager = new FinishActivityManager();

  11. }

  12. }

  13. }

  14. return sManager;

  15. }

  16. /**

  17. * 添加Activity到集合中

  18. */

  19. public void addActivity(Activity activity) {

  20. if (activityList == null) {

  21. activityList = new LinkedList<>();

  22. }

  23. activityList.add(activity);

  24. }

  25. /**

  26. * 关闭指定的Activity

  27. */

  28. public void finishActivity(Activity activity) {

  29. if (activityList != null && activity != null && activityList.contains(activity)) {

  30. //使用迭代器安全删除

  31. for (Iterator<Activity> it = activityList.iterator(); it.hasNext(); ) {

  32. Activity temp = it.next();

  33. // 清理掉已经释放的activity

  34. if (temp == null) {

  35. it.remove();

  36. continue;

  37. }

  38. if (temp == activity) {

  39. it.remove();

  40. }

  41. }

  42. activity.finish();

  43. }

  44. }

  45. /**

  46. * 关闭指定类名的Activity

  47. */

  48. public void finishActivity(Class<?> cls) {

  49. if (activityList != null) {

  50. // 使用迭代器安全删除

  51. for (Iterator<Activity> it = activityList.iterator(); it.hasNext(); ) {

  52. Activity activity = it.next();

  53. // 清理掉已经释放的activity

  54. if (activity == null) {

  55. it.remove();

  56. continue;

  57. }

  58. if (activity.getClass().equals(cls)) {

  59. it.remove();

  60. activity.finish();

  61. }

  62. }

  63. }

  64. }

  65. /**

  66. * 关闭所有的Activity

  67. */

  68. public void finishAllActivity() {

  69. if (activityList != null) {

  70. for (Iterator<Activity> it = activityList.iterator(); it.hasNext(); ) {

  71. Activity activity = it.next();

  72. if (activity != null) {

  73. activity.finish();

  74. }

  75. }

  76. activityList.clear();

  77. }

  78. }

  79. /**

  80. * 退出应用程序

  81. */

  82. public void exitApp() {

  83. try {

  84. finishAllActivity();

  85. // 退出JVM,释放所占内存资源,0表示正常退出

  86. System.exit(0);

  87. // 从系统中kill掉应用程序

  88. android.os.Process.killProcess(android.os.Process.myPid());

  89. } catch (Exception e) {

  90. e.printStackTrace();

  91. }

  92. }

  93. }

这种方式网上很多,但注意在删除的时候使用迭代器,否则会出现并发修改异常。应用中要是不使用这种封装的方式去finish掉Activity的时候,封装的manager并不知道,没有断开并释放掉其引用,会引起内存泄漏。继续用WeakReference改进。

 
  1. public class FinishActivityManager extends BaseActivity {

  2. private FinishActivityManager() {

  3. }

  4. private static FinishActivityManager sManager;

  5. private Stack<WeakReference<Activity>> mActivityStack;

  6. public static FinishActivityManager getManager() {

  7. if (sManager == null) {

  8. synchronized (FinishActivityManager.class) {

  9. if (sManager == null) {

  10. sManager = new FinishActivityManager();

  11. }

  12. }

  13. }

  14. return sManager;

  15. }

  16. /**

  17. * 添加Activity到栈

  18. * @param activity

  19. */

  20. public void addActivity(Activity activity) {

  21. if (mActivityStack == null) {

  22. mActivityStack = new Stack<>();

  23. }

  24. mActivityStack.add(new WeakReference<>(activity));

  25. }

  26. /**

  27. * 检查弱引用是否释放,若释放,则从栈中清理掉该元素

  28. */

  29. public void checkWeakReference() {

  30. if (mActivityStack != null) {

  31. // 使用迭代器进行安全删除

  32. for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {

  33. WeakReference<Activity> activityReference = it.next();

  34. Activity temp = activityReference.get();

  35. if (temp == null) {

  36. it.remove();

  37. }

  38. }

  39. }

  40. }

  41. /**

  42. * 获取当前Activity(栈中最后一个压入的)

  43. * @return

  44. */

  45. public Activity currentActivity() {

  46. checkWeakReference();

  47. if (mActivityStack != null && !mActivityStack.isEmpty()) {

  48. return mActivityStack.lastElement().get();

  49. }

  50. return null;

  51. }

  52. /**

  53. * 关闭当前Activity(栈中最后一个压入的)

  54. */

  55. public void finishActivity() {

  56. Activity activity = currentActivity();

  57. if (activity != null) {

  58. finishActivity(activity);

  59. }

  60. }

  61. /**

  62. * 关闭指定的Activity

  63. * @param activity

  64. */

  65. public void finishActivity(Activity activity) {

  66. if (activity != null && mActivityStack != null) {

  67. // 使用迭代器进行安全删除

  68. for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {

  69. WeakReference<Activity> activityReference = it.next();

  70. Activity temp = activityReference.get();

  71. // 清理掉已经释放的activity

  72. if (temp == null) {

  73. it.remove();

  74. continue;

  75. }

  76. if (temp == activity) {

  77. it.remove();

  78. }

  79. }

  80. activity.finish();

  81. }

  82. }

  83. /**

  84. * 关闭指定类名的所有Activity

  85. * @param cls

  86. */

  87. public void finishActivity(Class<?> cls) {

  88. if (mActivityStack != null) {

  89. // 使用迭代器进行安全删除

  90. for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {

  91. WeakReference<Activity> activityReference = it.next();

  92. Activity activity = activityReference.get();

  93. // 清理掉已经释放的activity

  94. if (activity == null) {

  95. it.remove();

  96. continue;

  97. }

  98. if (activity.getClass().equals(cls)) {

  99. it.remove();

  100. activity.finish();

  101. }

  102. }

  103. }

  104. }

  105. /**

  106. * 结束所有Activity

  107. */

  108. public void finishAllActivity() {

  109. if (mActivityStack != null) {

  110. for (WeakReference<Activity> activityReference : mActivityStack) {

  111. Activity activity = activityReference.get();

  112. if (activity != null) {

  113. activity.finish();

  114. }

  115. }

  116. mActivityStack.clear();

  117. }

  118. }

  119. /**

  120. * 退出应用程序

  121. */

  122. public void exitApp() {

  123. try {

  124. finishAllActivity();

  125. // 退出JVM,释放所占内存资源,0表示正常退出

  126. System.exit(0);

  127. // 从系统中kill掉应用程序

  128. android.os.Process.killProcess(android.os.Process.myPid());

  129. } catch (Exception e) {

  130. e.printStackTrace();

  131. }

  132. }

  133. }

代码一目了然,之所以改成Stack,是因为要模仿Activity的任务栈的方式,关闭最后打开的Activity更加方便。 使用的话,在BaseActivity中onCreate()中addActivity,在onDestroy()中finishActivity(),其他功能在各个子Activity中根据需要添加。

优劣: 优点:一劳永逸,一次封装,方便后续使用。 缺点:暂无。

方案四:launchMode

根据Android启动模式,standard和singleTop并不能实现项目需求,故排除。

singleTask和singleInstance在使用的时候会和onActivityResult()有点关系: Android 5.0以上的版本能正常使用,没有冲突; Android 5.0以下的版本有个bug,在调用了startActivityForResult之后立马就会调用onActivityResult,不会等到打开的Activity返回的时候才调用。 项目中很多Activity种都有startActivityForResult,故此种方式排除掉。

方案五:onActivityResult

根据方案四,此方式需要配合launchMode的standard和singleTop使用才能达到效果,所以局限性很大。

总结

以上就是几种方案的对比,要是项目中需要关闭Activity不多,不需要发送大量广播,可以使用方案一;方案二和方案三有异曲同工之处,首先推荐方案三。

能力有限,有不对之处,欢迎指出。

参考资料: 《深入理解Java虚拟机:JVM高级特性与最佳实践》

http://blog.csdn.net/weiwozhiyi/article/details/50791416 

http://blog.csdn.net/lengguoxing/article/details/42145641

http://blog.csdn.net/u012815217/article/details/49280937

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值