【问题标题】:how to check if activity is still in the stack?如何检查活动是否仍在堆栈中?
【发布时间】:2012-12-07 21:18:41
【问题描述】:

检查活动是否仍在堆栈中以便回调它的更好方法是什么?

Intent i = new Intent(getApplicationContext(),MyClass.class);
startActivity(i);

【问题讨论】:

  • 为什么要关心?这取决于 Android。
  • 因为我有一个活动需要参数才能从 xml 文件中检索数据,所以我想从堆栈中调用它以避免从文件中传递参数和获取数据,因为这会很痛苦让用户每次看到 ProgressDialog。

标签: android android-activity stack


【解决方案1】:

我很惊讶这种(某种)问题如此不受欢迎。

让我先从解决方案开始:
由于ActivityManager.getRunningTasks 自 API 21 起已弃用,
我们必须找到另一种方法来获取 backstack 中的哪些活动。我意识到我们实际上可以实现自己的“堆栈”!

我在 MyOwnApplication 中声明了一个 ArrayList:

private ArrayList<Class> runningActivities = new ArrayList<>();

并添加了访问和修改此列表的公共方法:

public void addThisActivityToRunningActivityies (Class cls) {
    if (!runningActivities.contains(cls)) runningActivities.add(cls);
}

public void removeThisActivityFromRunningActivities (Class cls) {
    if (runningActivities.contains(cls)) runningActivities.remove(cls);
}

public boolean isActivityInBackStack (Class cls) {
    return runningActivities.contains(cls);
}

在所有活动都扩展它的BaseActivity 中:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ((MyOwnApplication)getApplication()).addThisActivityToRunningActivityies(this.getClass());
    }

@Override
protected void onDestroy() {
    super.onDestroy();
    ((MyOwnApplication)getApplication()).removeThisActivityFromRunningActivities(this.getClass());
}

然后您就可以轻松使用isActivityInBackStack 进行检查了。

为什么需要这样做?

是的,当然,大多数情况下都可以通过使用 Intent Flags 和适当的导航来完成。
但是有这样一个用例,我认为应该很常见,我无法简单地通过使用意图标志找到解决方案。

假设我有一个应用程序,它几乎在每个活动中都有一个导航抽屉。
我从MainActivity 导航到ActivityA,然后从ActivityA 创建ChildActivityB。请注意ActivityA 不是ChildActivityB 的父级,因为ChildActivityB 可以从通知等其他活动中打开。

请注意,ChildActivityB 也有一个抽屉。我可以通过抽屉导航到ActivityA,而不是按向上或返回按钮。现在,假设您循环通过这样的过程: Activity A -> ChildActivity B -> Drawer -> Activity A -> ChildActivityB -> Drawer -> Activity A ..... 无限活动将在后台创建。
要修复这种行为,我们需要使用 Intent Flags:

(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);

到目前为止一切顺利。 但是,我使用overridePendingTransition() 自定义了活动过渡动画。我注意到,如果我将上述意图标志与overridePendingTransition() 放在一起,由于标志Intent.FLAG_ACTIVITY_CLEAR_TOP 导致活动在动画中间被破坏,因此动画会出现故障

现在,如果我能够检测到ActivityA 是否在后台堆栈中,那么行为将是完美的:

private void navigateToDrawerItems(Class cls) {
    drawerLayout.closeDrawer(GravityCompat.END);
    Intent intent = new Intent(this, cls);
    if (((MyOwnApplication)getApplication()).isActivityInBackStack(cls)) {
        intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
    } else {
        startActivity(intent);
        overridePendingTransition(R.anim.slide_right_in, R.anim.slide_left_out);
    }
}

【讨论】:

  • +1 用于提及导航用例。我要补充一点,虽然这是抽屉式导航的有效用例,但对于 Tab Bar 导航(又名 BottomNavigationView)来说更为重要。 Android 没有用于片段 backstack 的 FLAG_ACTIVITY_REORDER_TO_FRONT。因此,如果您想在选项卡之间切换时轻松保持状态并且不会耗尽内存,那么使用活动选项卡而不是片段选项卡是唯一的方法。
  • 此堆栈将仅包含进程死亡后最顶层的活动(内存不足),因此在生产代码中不可靠。
  • 两年半后重温,我现在明白为什么这种问题不受欢迎了。这是因为我上面给出的例子实际上并不是一个好的用户体验。在那个例子中,不应该允许孩子 B 有一个抽屉。相反,它应该可以被关闭,类似于弹出活动(iOS 中模式的概念)。如果你有我提到的相同的用户体验,试着说服你的设计师。
  • 但这并不处理多个实例。说 A -> B -> C -> A -> C ...我如何区分不同的实例?
【解决方案2】:

查看ActivityManager API

要获取 ActivityManager 的实例,请使用以下代码:

ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );

【讨论】:

  • 如果能详细了解我应该如何使用 ActivityManager 检查活动是否在堆栈上,那就太好了。仅“阅读此类文档”还不够 IMO。
  • 他指的是 ActivityManager.getRunningTasks,但它在棒棒糖中已被弃用。
【解决方案3】:

您可以将全局变量切换为特定类的 onCreate()onDestory() 内的指示器,或 ActivityLifecycleCallbacks 的 onActivityCreated()onActivityDestroyed() 内的指示器。

例如:

  registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

      @Override
      public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
          if (activity instanceof YourActivity) {
              myGlobalData.setActExist(true);
          } 
      }

      @Override
      public void onActivityDestroyed(Activity activity) {
          if (activity instanceof YourActivity) {
              myGlobalData.setActExist(false);
          }
      }
  });

【讨论】:

    猜你喜欢
    • 2014-01-30
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    • 2011-08-23
    • 1970-01-01
    • 1970-01-01
    • 2011-01-07
    • 2017-05-07
    相关资源
    最近更新 更多