【问题标题】:Storing and restoring activity states存储和恢复活动状态
【发布时间】:2016-06-09 13:52:32
【问题描述】:

在调用另一个activity时,能否确定我存储在当前activity中的变量在返回时会存在?

new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapter, View item, int pos, long id)  {
        Intent i = new Intent(Activity1.this, Activity2.class);
        i.putExtra("position", pos); // 1
        position = pos; // 2
        startActivityForResult(i, REQUEST_CODE); // brings up the edit item activity
    }
});

对于上面的代码,我可以通过存储在当前活动实例字段中来使用 (2),还是应该使用 (1) 传递值,然后在 onActivityResult() 中使用 getIntExtra() 来恢复该值?

【问题讨论】:

  • new Intent(Activity1.this 可能是new Intent(item.getContext()

标签: android android-activity activity-state


【解决方案1】:

理想情况下,您只需将状态保存在 Activity1 中。这样你就不必通过Activity2 传递变量,然后将结果(这不完全是Activity2 中所做的任何事情的结果)传回Activity1。要将position 的值保存在Activity1 中,您应该在Activity 中执行以下操作:

    private static final String KEY_ARG_POSITION = "KEY_ARG_POSITION";

    private int position;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Do whatever you are doing in onCreate already...

        if (savedInstanceState != null) {
            position = savedInstanceState.getInt(KEY_ARG_POSITION);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putInt(KEY_ARG_POSITION, position);
    }

如果您不想在屏幕方向更改或操作系统终止并重新启动您的活动时丢失该值,这也是相关的。

最后,只是为了让你的代码有条理,除非你需要在Activity2 中使用position 的值,否则我建议不要将Activity2 暴露给它不需要管理的任何数据。如果您正在开发一个大型应用程序,这些事情可能会加起来很快就会变得一团糟。

【讨论】:

  • 我读到onSaveInstanceState() 需要与onRestoreInstanceState() 平衡,而它不是活动生命周期的一部分,例如onPause() 甚至不会调用它。
  • @JohnDifool onSaveInstanceState() 如果 Activity 被杀死,将被调用。 onCreate() 在 Activity 恢复时被调用。如果正在恢复 Activity,onCreate() 中的 savedInstanceState 将不等于 null,这意味着您可以尝试恢复保存到其中的任何变量。我经常使用这种模式,没有任何问题。你有机会尝试一下吗?
【解决方案2】:

是的,它会在您返回 Activity1 时出现,因此无需使用getIntExtra。只需将您的位置存储在 Activity1 的全局变量中即可。

【讨论】:

    【解决方案3】:

    使用 startActivityForResult...时,您将提供一个请求代码,该代码将在您的 onActivityResult 方法中返回。在那里,您将获得请求代码以及结果代码(成功、失败等,以及您可以从您开始的活动中设置的 Intent 数据。

    所以你可以这样做:

    Intent i = new Intent(Activity1.this, Activity2.class);
    i.putExtra("position", pos);
    startActivityForResult(i, REQUEST_CODE);
    

    然后在你的 Activity2 类中

    Intent intent = new Intent();
    intent.putExtras(getIntent().getExtra("position"));
    setResult(RESULT_OK, intent);
    finish();
    

    在您的第一个 Activity 中将调用:

     onActivityResult(int requestCode, int resultCode, Intent data) {
    //Check it's your requestCode,
    //Check resultCode == RESULT_OK or whatever you need
    //Grab your position from the data intent
    }
    

    更多信息请见https://developer.android.com/training/basics/intents/result.html

    【讨论】:

    • 这假设每次我切换到另一个活动时,我都必须保存我无法从原始活动重新创建的所有非易失性字段,并在我回调时将其传回,对吧?
    【解决方案4】:

    我的建议:在Intent 中传递足够的信息来唯一标识感兴趣的数据项。不要只传递一个位置,因为如果项目的顺序发生变化或其他项目从列表中添加/删除,位置可能会发生变化。想象一个场景,您将位置 2 传递给 Activity2,但当 Activity2 启动时,Activity1 重新加载其数据,而位置 2 现在是其他项目。

    另外,我不会依赖调用 Activity 的实例成员(即代码中的 position = pos 行)。您的Activity1 可能被杀死,而另一个活动是直接的前台活动。在那种情况下,当结果返回Activity1时会重新创建,但它会是Activity1的一个新实例,所以你的实例成员position不会有你之前设置的数据。

    【讨论】:

    • 但是什么是合理的保存呢?如果我按照你的推理,我需要序列化并将整个数组传递给第二个活动,对吗?
    • @JohnDifool 取决于你在做什么。为什么需要项目的位置而不是标识项目本身的东西?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 2020-05-22
    • 2019-01-03
    相关资源
    最近更新 更多