gpt4 book ai didi

android - 当方向改变时使用选项卡重新加载 Activity 时, fragment 被初始化两次

转载 作者:IT老高 更新时间:2023-10-28 23:25:34 25 4
gpt4 key购买 nike

当我更改设备的方向时,我在重新加载带有选项卡和 fragment 的 Activity 时遇到问题。

情况如下:

我有一个在操作栏中有 3 个选项卡的 Activity 。每个选项卡在 FrameLayout 中加载不同的 fragment 在主视图中。如果我不改变设备的方向,一切正常。但是当我这样做时,Android 会尝试初始化当前选择的 fragment 两次,这会产生以下错误:

E/AndroidRuntime(2022): Caused by: android.view.InflateException: Binary XML file line #39: Error inflating class fragment

以下是产生错误的步骤顺序:

  1. 我加载 Activity,选择 tab nr 2. 并更改设备的方向。
  2. Android 销毁 Activity 和 tab nr 2 加载的 Fragment 实例(从现在开始,“Fragment 2”)。然后它继续创建 Activity 和 Fragment 的新实例。
  3. 内部 Activity.onCreate()我将第一个选项卡添加到操作栏。当我这样做时,此选项卡会自动选择。它可能代表 future 的问题,但我现在不介意。 onTabSelected被调用并创建并加载第一个 fragment 的新实例(参见下面的代码)。
  4. 我添加了所有其他选项卡而没有触发任何事件,这很好。
  5. 我调用 ActionBar.selectTab(myTab)选择 Tab nr 2。
  6. onTabUnselected()调用第一个选项卡,然后调用 onTabSelected()对于第二个选项卡。此序列替换 fragment 2 实例的当前 fragment (参见下面的代码)。
  7. 接下来,Fragment.onCreateView()在 Fragment 2 实例上调用,并且 Fragment 布局变得膨胀。
  8. 这就是问题所在。安卓通话 onCreate()然后 onCreateView()在 fragment 实例 ONCE AGAIN 上,当我尝试膨胀(第二次)布局时会产生异常。

显然问题是 Android 两次初始化 fragment ,但我不知道为什么。

我尝试在重新加载 Activity 时不选择第二个选项卡,但第二个 fragment 无论如何都会被初始化并且它没有显示(因为我没有选择它的选项卡)。

我发现了这个问题:Android Fragments recreated on orientation change

用户问的问题基本上和我一样,但我不喜欢选择的答案(这只是一种解决方法)。必须有某种方法可以在没有 android:configChanges 的情况下使其正常工作。把戏。

如果不清楚,我想知道如何阻止 fragment 的重新创建或避免 fragment 的双重初始化。很高兴知道为什么会发生这种情况。 :P

以下是相关代码:

public class MyActivity extends Activity  implements ActionBar.TabListener {

private static final String TAG_FRAGMENT_1 = "frag1";
private static final String TAG_FRAGMENT_2 = "frag2";
private static final String TAG_FRAGMENT_3 = "frag3";

Fragment frag1;
Fragment frag2;
Fragment frag3;

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

// my_layout contains a FragmentLayout inside
setContentView(R.layout.my_layout);

// Get a reference to the fragments created automatically by Android
// when reloading the activity
FragmentManager fm = getFragmentManager();
this.frag1 = fm.findFragmentByTag(MyActivity.TAG_FRAGMENT_1);
this.frag2 = fm.findFragmentByTag(MyActivity.TAG_FRAGMENT_2);
this.frag3 = fm.findFragmentByTag(MyActivity.TAG_FRAGMENT_3)


ActionBar actionBar = getActionBar();

// snip...

// This triggers onTabSelected for the first tab
actionBar.addTab(actionBar.newTab()
.setText("Tab1").setTabListener(this)
.setTag(MyActivity.TAG_FRAGMENT_1));

actionBar.addTab(actionBar.newTab()
.setText("Tab2").setTabListener(this)
.setTag(MyActivity.TAG_FRAGMENT_2));
actionBar.addTab(actionBar.newTab()
.setText("Tab3").setTabListener(this)
.setTag(MyActivity.TAG_FRAGMENT_3));

Tab t = null;
// here I get a reference to the tab that must be selected
// snip...

// This triggers onTabUnselected/onTabSelected
ab.selectTab(t);

}

@Override
protected void onDestroy() {
// Not sure if this is necessary
this.frag1 = null;
this.frag2 = null;
this.frag3 = null;
super.onDestroy();
}

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {

Fragment curFrag = getFragmentInstanceForTag(tab.getTag().toString());
if (curFrag == null) {
curFrag = createFragmentInstanceForTag(tab.getTag().toString());
if(curFrag == null) {
// snip...
return;
}
}
ft.replace(R.id.fragment_container, curFrag, tab.getTag().toString());
}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft)
{
Fragment curFrag = getFragmentInstanceForTag(tab.getTag().toString());
if (curFrag == null) {
// snip...
return;
}

ft.remove(curFrag);
}

private Fragment getFragmentInstanceForTag(String tag)
{
// Returns this.frag1, this.frag2 or this.frag3
// depending on which tag was passed as parameter
}

private Fragment createFragmentInstanceForTag(String tag)
{
// Returns a new instance of the fragment requested by tag
// and assigns it to this.frag1, this.frag2 or this.frag3
}
}

fragment 的代码无关紧要,它只是返回 onCreateView() 上的膨胀 View 方法覆盖。

最佳答案

我得到了一个简单的答案:

只需将 setRetainInstance(true); 添加到 Fragment 的 onAttach(Activity activity)onActivityCreated(Bundle savedInstanceState) 即可。这两个是 Fragment 类中的回调。

所以基本上,setRetainInstance(true) 所做的是:当它通过时,它会保持 fragment 的状态:

  • onPause();
  • onStop();

无论 Activity 经历什么,它都会维护 Fragment 的实例。它的问题可能是,如果 fragment 太多,可能会给系统带来压力。

希望对你有帮助。

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);

setRetainInstance(true);

}

Open for Correction as always. Regards, Edward Quixote.

关于android - 当方向改变时使用选项卡重新加载 Activity 时, fragment 被初始化两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11192928/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com