我有一个已经实现的应用程序。在这个应用程序中。用户可以从任何其他 Activity 开始任何 Activity 。

我想做的事:

如果要求启动的 Activity 已经存在于历史堆栈中。应该重新启动堆栈上的该 Activity ,并且应该完成堆栈中它之前存在的所有 Activity 。

例如:A->B->C->D->E->F
现在我们要开始 D. A B C D 应该完成并且应该开始 D 的新实例并保持在堆栈中 E->F->D

谢谢,

最佳答案

我还建议在此要求上使用 Fragment,但由于您的应用程序已经实现,您可以采用这种方法。

 all the activities that exists before it in the stack should be finished.
Android 不提供任何标志来清除所有下面的 Activities 就像使用 Activities 清除顶部 clearTop 一样。如果我们有 clearBottom 就很简单了 :)

好的。如果您的目标是 Android API version from 16 ,这种方法将以优化的方式提供帮助。对于其他较低版本,您需要单独完成每个 Activity

创建一个 BaseActivity ,它将所有 Activity 实例添加到 HashMap 中(类似于添加 Fragments to back Stack )。但这里只是记住堆栈中的 Activities。您还可以使用 Activities 检查堆栈中的 ActivityManager.RunningTaskInfo,但我不想让它变得更复杂。

声明一个静态变量。我更喜欢在我的 Application class 中做。
 public class MyApp extends Application {
    public static HashMap<String , CommonActivity > mBackStackActivities
                   = new HashMap<String, CommonActivity>();
  }

现在,当 Activity created 将其实例添加到 HashMap
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MyApp.mBackStackActivities.put(getComponentName().getClassName(), this);
}

并且,当 Activity destroy 时将其删除
@Override
protected void onDestroy(){
    MyApp.mBackStackActivities.remove(getComponentName().getClassName());
    super.onDestroy();
}

现在,Override startActivity 中的 base Activity class 方法,当 Activity 启动时 check if the Activity exists in HashMap . If exists finish all the below Activity using finishAffinity`。
 @Override
public void startActivity(Intent intent) {
    if(MyApp.mBackStackActivities
        .containsKey(intent.getComponent().getClassName())){
        if(android.os.Build.VERSION.SDK_INT >= 16) {
            Activity activity = MyApp.mBackStackActivities.get(intent.getComponent().getClassName());
            // finish the activity as well as all the below Activities.
            activity.finishAffinity(); // supported from API 16
        }else {
            // loop through all the below activity and finish it
        }
    }
    super.startActivity(intent);
}

最后,如果您需要在 list 中为所需的 android:taskAffinity 设置 Activities ,默认情况下所有 Activities 将具有相同的 Affinity 名称(包名称)。如果您希望涵盖所有 Activities,则可以保留此选项。
    <activity
        android:name="com.example.app.activities.MainActivity"
        android:label="@string/title_activity_common"
        android:taskAffinity="@string/task_affinity_name">
    </activity>

在字符串 xml 中
<string name="task_affinity_name">com.example.app.affinity</string>

注意:如上对于低版本,您需要单独完成每个Activity`

在这里找到完整的源代码 https://gist.github.com/androidbensin/7d9261fd148c15575dd1

10-07 19:22
查看更多