Android 活动和片段中的自动UI配置更改处理有时会失败
我现在已经写了很长时间的android应用程序,但现在我面临着一个我从未想过的问题。它是关于与配置更改相关的Android 活动和片段中的自动UI配置更改处理有时会失败,android,android-fragments,android-activity,android-lifecycle,Android,Android Fragments,Android Activity,Android Lifecycle,我现在已经写了很长时间的android应用程序,但现在我面临着一个我从未想过的问题。它是关于与配置更改相关的活动和片段的android生命周期。为此,我创建了一个带有以下必要代码的小应用程序: public class MainActivity extends FragmentActivity { private final String TAG = "TestFragment"; private TestFragment fragment; @Override
活动和片段的android生命周期。为此,我创建了一个带有以下必要代码的小应用程序:
public class MainActivity extends FragmentActivity {
private final String TAG = "TestFragment";
private TestFragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
fragment = (TestFragment) fm.findFragmentByTag(TAG);
if (fragment == null) {
fragment = new TestFragment();
fm.beginTransaction().add(R.id.fragment_container, fragment, TAG).commit();
}
}
}
这是我的TestFragment
代码。请注意,我正在调用setRetainInstance(true)在onCreate
方法中使用code>,以便在配置更改后不会重新创建片段
public class TestFragment extends Fragment implements View.OnClickListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater li, ViewGroup parent, Bundle bundle) {
View rootView = li.inflate(R.layout.fragment_test, parent, false);
Button button = (Button) rootView.findViewById(R.id.toggleButton);
button.setOnClickListener(this);
return rootView;
}
@Override
public void onClick(View v) {
Button button = (Button) v;
String enable = getString(R.string.enable);
if(button.getText().toString().equals(enable)) {
button.setText(getString(R.string.disable));
} else {
button.setText(enable);
}
}
}
下面是我的片段使用的布局:
<LinearLayout
...>
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/toggleButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/enable"/>
</LinearLayout>
我的问题是,如果我旋转设备,按钮的文本将变回默认值。当然,片段
的视图
是新创建和膨胀的,但是保存的视图实例应该恢复。我的布局中还有一个EditText
,在旋转后,文本和其他属性仍保留在那里。那么,为什么默认情况下按钮不能从捆绑包中恢复?我在网上看到:
默认情况下,系统使用Bundle实例状态保存有关活动布局中每个视图对象的信息(例如输入到EditText对象中的文本值)。因此,如果您的活动实例被销毁并重新创建,则布局的状态将恢复到其以前的状态,而不需要任何代码
在过去的几天里,我也读了很多答案,但我不知道它们有多真实。请不要在android:configChanges=…
上留下评论或回答这是非常糟糕的做法。我希望有人能解释我的理解不足。您应该在onSaveInstanceState(Bundle outState)
中保存片段的状态,并在onViewCreated(View-View,Bundle-savedState)
方法中恢复它。这样,用户界面将与配置更改前一样。在操作反馈后编辑
public class TestFragment extends Fragment implements View.OnClickListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater li, ViewGroup parent, Bundle bundle) {
View rootView = li.inflate(R.layout.fragment_test, parent, false);
Button button = (Button) rootView.findViewById(R.id.toggleButton);
button.setOnClickListener(this);
return rootView;
}
@Override
public void onClick(View v) {
Button button = (Button) v;
String enable = getString(R.string.enable);
if(button.getText().toString().equals(enable)) {
button.setText(getString(R.string.disable));
} else {
button.setText(enable);
}
}
}
虽然这并不能回答这个问题,但在与OP协商后,我决定把它留在这里,作为登陆这里的人们关于这个话题的参考信息。希望对您有所帮助
尝试将您的setRetainInstance
放入onCreateView
中。看
当片段的活动已创建且
片段的视图层次结构已实例化。它可以用来做期末考试
在这些片段就位后初始化,例如检索
视图或恢复状态。对于使用
setRetainInstance(布尔值)以保留其实例,如下所示
回调告诉片段它何时与新代码完全关联
活动实例。这是在onCreateView(LayoutInflater,
视图组、捆绑)和onViewStateRestored(捆绑)之前
控制是否跨活动保留片段实例
重新创建(例如从配置更改)。这只能是
与不在后堆栈中的片段一起使用。如果设置了,则为片段
重新创建活动时,生命周期将略有不同:
不会调用onDestroy()(但仍然会调用onDetach(),因为
正在从当前活动中分离片段)。
onCreate(Bundle)将不会被调用,因为该片段未被调用
重新创建。
onAttach(活动)和onActivityCreated(捆绑)将
还是叫
摘自:
onCreate:在片段的初始创建时调用它。是吗
这里是您的非图形初始化。它甚至在比赛结束之前就结束了
布局膨胀,碎片可见
onCreateView:调用它来膨胀片段的布局,即
图形初始化通常在这里进行。它总是被称为
有时在onCreate方法之后
onActivityCreated:如果视图是静态的,则将任何代码移动到
onActivityCreated方法不是必需的。但是当你为
例如,从适配器中填写一些列表,然后您应该在
onActivityCreated方法,以及在
setRetainInstance用于执行此操作。还可以访问的视图层次结构
父活动必须在onActivityCreated中完成,而不是更早
让我知道这是否有帮助。TextView
子类默认情况下不保存文本。您需要在布局中启用freezesText=“true”
,或在运行时启用setFreezesText(true)
,以便保存其状态。根据文档,视图应在不使用setRetainInstance(true)
的情况下保持其状态。尝试在创建时将其从中删除,这将强制在屏幕旋转时重新创建片段,因此所有视图都应在旋转前保存,并在旋转后恢复。此堆栈溢出应回答您的问题:
setRetainInstance
会告诉片段保存其所有数据,对于用户已操作状态(EditText、ScrollView、ListView等)的ui元素,状态会恢复。也就是说,普通的只读UI组件在onCreateView
中从头开始重新膨胀,必须重新设置-我猜它们的属性不被视为需要保留和恢复的“数据”-谷歌可能出于性能原因而这样做。因此,如果普通按钮、ImageView或TextView的内容与XML中的初始状态不同,则需要在对其重新充气时手动设置这些内容。(TextView的android:freezesText
基本上将TextView置于一种使用实现来保存和恢复其状态的模式)
PS:根据这个堆栈溢出,您可以在按钮上设置android:freezesText
,让它保留您看到的文本