java - 如何在后台堆栈中使用嵌入 fragment 的 Activity 之间保存应用程序状态?

标签 java android android-intent android-fragments android-asynctask

我发现了大量关于在使用 Activity 中嵌入的 Fragment 时恢复应用程序状态的正确方法的相互矛盾的信息。如果我的架构是问题所在,请告诉我,因为这是完全可能的。我的测试天气应用程序的架构如下。

主要 Activity “ReportsActivity”包含 fragment “ReportsFragment”(这是 future 10 天天气报告的列表) ReportsFragment 有一个 onItemClickListener,它启动一个新的 Activity “WeatherDetailActivity”并向它传递一个 Intent ,其中包含一些我用来填充天气详细信息 UI 的 JSON 数据。然后,此数据显示在 WeatherDetailActivity 管理的 fragment 上。

我的问题是,当用户按下后退按钮时,ReportsFragment 已被销毁,因此它会运行完整的生命周期。我已经尝试了一些我在网上找到的技术来从一个包中加载 Activity 的数据,但无论我到目前为止尝试了什么,Intents 的 Extras 在 ReportsActivity 的 onCreate 方法中都是空的。 (注意:我需要这样做的原因是为了避免每次打开从 Weather Underground 获取天气数据的主 Activity 时触发 API 调用)。

我正在努力确定什么是构建此应用程序的最佳方式:我是否应该有一个单独的 Activity 来推送和弹出它管理的 fragment ?还是多个 Activity 各自管理自己的 fragment 是标准做法?

目前我正在尝试将我的应用程序状态保存到 Intent 中。我正在尝试从我的 AsyncTask 中保存 onPostExecute 中的状态,所以在我从 API 调用中获取结果后我在主线程上:

 @Override
protected void onPostExecute(Report[] result){
    if (result != null){

        ArrayList<String>reportsArrayList = new ArrayList<String>();
        Gson jsonArray = new GsonBuilder().setPrettyPrinting().create();
        for (int x = 0; x < result.length; x++){

            reportsArrayList.add(jsonArray.toJson(result[x], Report.class));
        }

        mExtras.putStringArrayList(ReportsActivity.ReportsActivityState.KEY_ACTIVITY_REPORTS,reportsArrayList);
    }
}

然后我尝试从 ReportsActivity 的 onCreate 方法恢复状态:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_reports);

    if (savedInstanceState == null) {

        Intent intent = getIntent();

        mFragment = ReportsFragment.newInstance(intent
                .getStringArrayListExtra(ReportsActivityState.KEY_ACTIVITY_REPORTS));

        getFragmentManager().beginTransaction()
                .add(R.id.container, mFragment).commit();
    }
}

在所有情况下,我试图从 Intent 中获取的 StringArrayListExtra 返回 null。

这很可能是我试图以 iOS 的思维方式解决 Android 问题,但是否没有一种简单的方法可以将主要 Activity 恢复到我推送详细信息 View 之前的状态?

最佳答案

我认为 EventBus 值得您一试。

基本上您可以定义任何类型的对象持有者,例如:

class WeatherData {
    List<String> reports;
    public WeatherData(List<String> reports) {
        this.reports = reports;
    }
}

现在,在您希望记住状态的 Activity 或 Fragment 中,或将某些状态传递给另一个 Activity 或 Fragment 时,请执行以下操作:

// this removes all the hazzle of creating bundles etc
EventBus.getDefault().postSticky(new WeatherData(reports)); 

以及您希望在代码中的任何位置了解最新的 WeatherData:

WeatherData weatherData = EventBus.getDefault().getSticky(WeatherData.class);

EventBus 也有很好的事件处理方法(按钮点击、长时间运行的进程完成等)

图书馆可以在这里找到:https://github.com/greenrobot/EventBus

这里还有一些例子:http://awalkingcity.com/blog/2013/02/26/productive-android-eventbus/

不使用3.零件库的一些建议:

1) 在您的 fragment onCreate 方法中调用 setRetainInstance(true),这应该做的是在实例之间保留公共(public)变量。

虽然它似乎不适用于返回堆栈上的 fragment :Understanding Fragment's setRetainInstance(boolean)

2) 将 fragment 数据传递给您的 Activity,例如读取/更新 ((YourActivity)getActivity()).someFragmentBundle,可能将其保存在 Activity 的 onSaveInstanceState 中并在 onCreate 中检索它。也就是说,让您的 Activity 保存实例之间的数据。

3) 您还可以保留数据,将其保存到文件或使用 SharedPreferences http://developer.android.com/training/basics/data-storage/index.html

此方法的优点是即使在您的应用程序完全终止后也能恢复数据。

架构问题

免责声明:主观意见

我通常会说让 Activity 尽可能“ slim ”,包含一系列相关 fragment 。

因此,拥有多个 Activity 是可以的,但它们应该各自管理一组(或单个)与当前 Activity 相关的相关 fragment 。

关于java - 如何在后台堆栈中使用嵌入 fragment 的 Activity 之间保存应用程序状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25125856/

相关文章:

java - 文件名过滤器的使用

android - Flutter 应用程序未使用 Fiddler 代理

java - 带有单选按钮的 Android Action Down

android - Titanium android 对特定应用程序的外部 Intent

android - 从另一个页面获取值

java - Spring Data JPA 关系注释

java - spring-多任务延迟执行

Java JsonObject 数组值到键

android - Android Gradle构建失败

Android 覆盖显式 Intent