Android--关闭某个指定activity

作者: 06fd4cf1f427 | 来源:发表于2019-04-03 21:49 被阅读60次

    最近项目中有这样的需要,在关闭当前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<BActivity> 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<Activity> 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<Activity> 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<Activity> 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<Activity> 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<WeakReference<Activity>> 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<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
                    WeakReference<Activity> 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<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
                    WeakReference<Activity> 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<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
                    WeakReference<Activity> 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<Activity> 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,故此种方式排除掉。

    方案五

    使用onActivityResult方式

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

    方案六

    使用Rxbus

    Rxbus也是可以实现的,根据自己的需求来决定吧
    要是项目中需要关闭Activity不多,不需要发送大量广播,可以使用方案一;方案二和方案三有异曲同工之处,首先推荐方案三;比较之下我在项目中用了方案三。

    【附】相关架构及资料

    加群 Android IOC架构设计领取获取往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。

    Android高级技术大纲

    领取方式:

    点赞+加群免费获取 Android IOC架构设计

    相关文章

      网友评论

        本文标题:Android--关闭某个指定activity

        本文链接:https://www.haomeiwen.com/subject/levtiqtx.html