【问题标题】:Fragment state loss?片段状态丢失?
【发布时间】:2014-11-06 18:38:07
【问题描述】:

究竟什么是“状态损失”情况?你能演示一个完整的场景(包括一些代码)会导致它吗? 我已经阅读了许多关于该主题的教程(官方和非官方)、博客、stackoverflow 问题/答案,但从来没有一个会导致实际状态丢失以及状态丢失发生后实际发生的示例。

我不知道要执行哪些完整步骤才能导致状态丢失。 我试图做的是:

  1. 具有包含框架布局的布局的 Activity。
  2. 在一些 TextView 中具有带有“hello”文本的布局的 Fragment。
  3. 片段通过片段事务添加到上述框架布局。
  4. 用户按下主页按钮,然后使用 commitAllowingStateLoss() 方法提交的片段事务发生的场景。

然后我尝试进行配置更改,但一切正常。 然后我试图从后台恢复,但一切都很好。 然后我尝试将片段添加到后堆栈并执行 commitAllowingStateLoss() 然后是上面的步骤,但是当配置发生变化或者当我从后台返回时,然后我按下了确实删除了事务的返回按钮,这意味着从返回堆栈中删除了片段,这意味着没有发生状态丢失。

那么“状态损失”到底是什么?它如何影响用户在屏幕上看到的内容。 你能展示一个完整的状态丢失场景吗?

编辑:放一些测试代码:

活动代码:

package com.example.statelosstest;

import android.app.Activity;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.os.Handler;

public class MainActivity extends Activity {

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

@Override
protected void onStop() {
    super.onStop();

    //Just for test
    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {

        @Override
        public void run() {
            addDummyFragment();             
        }
    }, 5000);
}

/**
 * Invoke this method after onSaveInstanceState has been called,
 * for example after user press android home button.
 */
private void addDummyFragment(){
    DummyFragment frag = new DummyFragment();
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.add(R.id.fragment_frame, frag, frag.getClass().getName());

    // tried this also
    // transaction.addToBackStack(frag.getClass().getName());

    transaction.commitAllowingStateLoss();
}

}

编辑:仍然没有答案 -
我试图模拟我认为会导致状态丢失并且我会在 UI 中看到状态丢失但无法模拟或导致任何状态丢失情况的事物。请有人展示一个发生状态丢失并且可以在 UI 中看到的场景,这意味着状态丢失确实发生了意外行为。

【问题讨论】:

  • 很棒的文章,但我之前已经读过(不止一次)。没有真实状态丢失的示例以及发生状态丢失时实际发生的情况。我只是无法想象为什么使用 commitAllowingStateLoss() 很危险?我无法想象它会真正影响我的代码的情况。你能展示一个代码和一个场景,因为 commitAllowingStateLoss() 会导致 UI 奇怪的行为,当然会在调用 onSaveInstanceState() 之后使用
  • @Alex Lockwood 你是我最后的希望 ;) 解决这个问题。
  • 是什么让这不是状态丢失的情况?当您期望提交时(在现实世界中),提交将被丢弃。提交 UI 片段时的预期行为是什么?
  • 我不懂你。当我使用 commitAllowingStateLoss 提交它时,例如我正在更改配置,然后提交就在那里,这意味着我添加的片段在那里,这意味着实际上没有发生状态丢失。

标签: android android-fragments


【解决方案1】:

一些状态损失示例:

1.假设你有一个按钮和一个文本视图。在代码中,你已经定义了整数 i,初始值为 0,通过点击按钮递增 1,其值显示在文本视图中。假设你已经按下按钮 5 次,那么 textview 将被设置为 0。那是 Integer 在屏幕变化时失去了它的价值

解决方案: 覆盖 onSaveInstanceState 并放入整数值。然后在 onResume 或 onCreate 方法中保留该整数的值。

2. 考虑你有一个待办事项列表视图。用户动态添加到该列表视图中的 dos。假设用户添加了 3 个项目,然后在屏幕旋转时(或者如果应用重新启动),列表视图将变为空。

解决方案: 再次在 onSaveInstanceState 中,放入 ArrayList。 (列表可以实现为“Serializabe”或“Parcelable”,可以作为一个整体存储。你不需要存储listview的每一项)。然后在 onResume 或 onCreate 方法中,获取该列表视图。

3.屏幕旋转时,屏幕中的所有edittexts都将变为空。

我对状态丢失的简单理解是,每当配置更改(屏幕旋转或应用重启)时,都会调用 Activity 的整个生命周期。所以,没有保存的东西都会丢失。

这让我想起了任天堂的退出屏幕消息,“任何未保存的内容都会丢失”。

【讨论】:

  • 你描述的很好,但我已经知道了。我的问题是关于片段状态丢失,特别是关于在调用 onSaveInstanceState 后可能发生的事务。例如:发送一个 http 请求并在等待响应时,用户单击主页按钮,然后响应到达并发生片段事务。我已经提出了一些问题。
  • 如果我做对了,你想要的是在 onSaveInstanceState 中做一些事情(在用户离开时接收 http 请求)。我可能错了,但我的逻辑是在 onSaveInstanceState、onPause、onDestroys 方法被调用之后。因此,已暂停(或销毁或分离)的片段无法执行任何操作。你可以使用 asynctask 在后台做一些事情
  • 关于backstack,并不意味着fragment在后台是活跃的。即使你已经使用 backstack 在片段之间进行交易,它的 onPause 和所有这些方法都会被调用。这仅意味着您可以通过从下一个片段(或任何其他片段。这取决于您如何使用返回按钮)按返回按钮返回到该片段
  • 也许我不清楚。我发送 http 请求的部分代码在后台线程中运行。 on destroy 将不会被调用(可能),因为用户只按下了主页按钮。正如我对@Alex Lockwood 所说:我无法想象为什么使用 commitAllowingStateLoss() 很危险?我无法想象状态丢失会真正影响我的代码的情况。你能展示一个代码和一个场景,因为 commitAllowingStateLoss() 会导致 UI 奇怪的行为,当然会在调用 onSaveInstanceState() 之后使用
  • 啊……好吧……我现在明白了。你想知道使用 commitAllowingStateLoss() 的偶然性。嗯,我的脑海中也没有任何这样的场景。当我遇到这种情况时,我会告诉你的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-31
相关资源
最近更新 更多