Android中一个Activity关闭另一个Activity或者在一个Activity中关闭多个Activity

  • 前言最近项目中涉及需要在一个Activity中关闭另一个Activity或者在一个Activity中关闭多个Activity的需求,不涉及到应用的退出。自己首先想了一些方案,同时也查了一些方案,就各个方案比较下优劣。方案一广播的方式这个是最容易想到的,同时也是网上提供最多的。由于多个Activity要使用,关闭页面的广播最好写在基类BaseActivity中,也可以在各个子页面单独写,但是代码量就增加了。publicclassBaseActivityextendsActivi


  • 前言 

    最近项目中涉及需要在一个Activity中关闭另一个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<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被static之后,里面包裹的引用会被影响吗?查了一下WeakReference以及JVM相关,虽然WeakReference被static了,生命周期变长了,但是WeakReference关联的对象不受影响的,依然遵循WeakReference在gc时候的规则。

     

    优劣:
    优点:代码简单直观,引入WeakReference,解决了内存泄漏问题。
    缺点:在每个activity中都要添加,代码量多。(不知是否可抽取到积累中,以后尝试)


    方案三 

    使用集合或者栈的方式

     

    这种方式网上很多,但是。。。。。。


    public class FinishActivityManager extends BaseActivity { 
    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 extends BaseActivity { 
    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使用才能达到效果,所以局限性很大。


    总结 

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值