Android oncreateview 调用了两次

Android oncreateview called twice(Android oncreateview 调用了两次)

本文介绍了Android oncreateview 调用了两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不止一次地看到这个问题在这里被问到,但我不知道如何解决我的问题.

I have see this question asked here more than one time but I can't figure it out how to solve for my case.

我有一个用户这样做的应用:

I have an app that the user does this:

1 - 打开navigationDrawer并选择一个选项(创建一个片段)(我这里选择第二个选项);

1 - Open the navigationDrawer and selects one option (a fragment is created) (I'm here selecting the second option);

public void selectItem(int position) {
        Fragment fragment = null;
        switch (position) {
            case FRAGMENT_OPTION1:
                ...
                break;
            case FRAGMENT_OPTION2:
                fragment = ControlPanelFragment.newInstance();
                break;
            ...
            case FRAGMENT_OPTIONN:
                ...
                return;
            default:
                break;
        }
        if (fragment != null) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            fragmentManager.beginTransaction().replace(R.id.fragment_container, fragment).commitAllowingStateLoss();
        }
}

2 - 选定的选项 (ControlPanelFragment) 被加载:2.1 - 控制面板有标签和图标页面.对于每个寻呼机页面和每个选项卡,都会创建一个新片段.我有 3 个标签和 3 个页面,因此创建了 9 个片段;

2 - The selected option (ControlPanelFragment) gets loaded: 2.1 - Control panel has tabs and an iconpager. For each pager page and for each tab a new fragment is created. I have 3 tabs and 3 pages so 9 fragments are created;

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    if (savedInstanceState != null) {
        currentControlPanelOption = savedInstanceState.getInt("currentControlPanelOption", currentControlPanelOption);
        currentControlPanelTab = savedInstanceState.getInt("currentControlPanelTab", currentControlPanelTab);
    }
    setControlPanelTabs();
    setIconPager();
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("currentControlPanelOption", pager.getCurrentItem());
    outState.putInt("currentControlPanelTab", mTabHost.getCurrentTab());
}

3 - 在 setIconPager(); 我有这个代码:

3 - In the setIconPager(); I have this code:

pager = (ViewPager) view.findViewById(R.id.pager);
cPanelPagerAdapter = new ControlPanelPagerAdapter(getChildFragmentManager());
pager.setOffscreenPageLimit(2);
pager.setAdapter(cPanelPagerAdapter);

其中 ControlPanelPagerAdapter 有这个代码:

public Fragment getItem(int index) {
    Fragment fragment;
    switch (index) {
        case 1:
            fragment = FragmentA.newInstance();
            break;
        case 2:
            fragment = FragmentB.newInstance();
            break;
        case 3:
            fragment = FragmentC.newInstance();
            break;
        default:
            fragment = null;
            break;
    }
    ...
    return fragment;
}

4 - FragmentAFragmentBFragmentC 的代码几乎相同:

4 - FragmentA, FragmentB and FragmentC have almost the same code:

public static FragmentA newInstance() {
    return new FragmentA();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_placeholder, container, false);
    return view;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    if (savedInstanceState == null) {
        fragmentA_Data = new FragmentADetail[3];
        createTabInstance(0);
    } else {
        fragmentA_Data = (FragmentADetail[]) savedInstanceState.getSerializable("Data");
        return;
    }
}
private void createTabInstance(int tab) {
    new FragmentADetail();
    fragment = FragmentADetail.newInstance(tab);

    Bundle args = new Bundle();
    args.putInt("tab", tab);
    fragment.setArguments(args);

    fragmentA_Data[tab] = fragment;
    FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.fragment_placeholder, fragmentA_Data[tab]);
    fragmentTransaction.commitAllowingStateLoss();
}
public void getTabData(int tab) {
    if (fragmentA_Data[tab] == null) {
        createStoreTimePeriodInstance(tab);
    } else {
        if (fragmentA_Data[tab].getArguments() == null) {
            Bundle args = new Bundle();
            args.putInt("tab", tab);
            fragmentA_Data[tab].setArguments(args);
        }
        FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.fragment_placeholder, fragmentA_Data[tab]);
        fragmentTransaction.commitAllowingStateLoss();
    }
}
@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putSerializable("data", fragmentA_Data);
}

5 - 最后,FragmentADetail 有这个代码:

5 - Finally, FragmentADetail has this code:

public static FragmentADetail newInstance(int tab) {
    selectedTab = tab;
    return new FragmentADetail();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.details_fragment, container, false);
    ...
    if (savedInstanceState != null) {
        selectedTab = savedInstanceState.getInt("selectedTab");
    }
    ...
}

public void getTabData(int tab) {
    //This is where I'm getting the data that populates the layout
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("selectedTab", selectedTab);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Bundle args = getArguments();
    if (args != null) {
       getTabData(args.getInt("tab"));
    }
}

现在,假设我在 FragmentA 上选择了第三个选项卡.如果我旋转屏幕,我会有以下事件序列:

Now, imagine I'm on FragmentA with the third tab selected. If I rotate the screen I have this sequence of events:

  1. ControlPanelFragment onSaveInstanceState 保存当前选项卡和当前片段
  2. FragmentA onSaveInstanceState 保存分页器的标签片段
  3. navigationDrawer 第二个选项再次被调用 fragment = ControlPanelFragment.newInstance();
  4. ControlPanelFragment onViewCreated 被调用,我可以获取保存的数据信息并创建一个新的分页器和选项卡
  5. FragmentA onViewCreated 被调用,我可以提取保存的数据
  6. FragmentADetail onActivityCreated 获取保存的数据并正确加载数据(至少我认为)并且从现在开始第二次调用第二组方法,并且之前保存的数据被重置,因此现在显示错误数据
  7. ControlPanelFragment onSaveInstanceState 但现在 savedInstanceState 为空
  8. ControlPanelPagerAdapter getItem 被称为实例化 3 个片段
  9. FragmentA onSaveInstanceState 现在调用它但 savedInstanceState 为空
  10. FragmentADetail onActivityCreated 被调用,但现在 tab = 0
  1. ControlPanelFragment onSaveInstanceState saves the current tab and current fragment
  2. FragmentA onSaveInstanceState saves the tabs fragments for the pager
  3. navigationDrawer second option gets again called fragment = ControlPanelFragment.newInstance();
  4. ControlPanelFragment onViewCreated is called and I can get the saved data information and a new pager and tabs are created
  5. FragmentA onViewCreated is called and I can extract the saved data
  6. FragmentADetail onActivityCreated gets the saved data and loads the data correctelly (at least I think) And from now a second set of methods is called the second time and the data that was previously saved is reseted and so it now displays wrong data
  7. ControlPanelFragment onSaveInstanceState but now the savedInstanceState is null
  8. ControlPanelPagerAdapter getItem is called instantiating the 3 fragments
  9. FragmentA onSaveInstanceState its now called but savedInstanceState is null
  10. FragmentADetail onActivityCreated is called but now the tab = 0

谁能解释一下,我怎样才能阻止步骤 7 到 10 的发生?

Can someone explain-me how can I stop steps 7 to 10 from happening?

推荐答案

我知道我的问题是什么.

I figure out what was my problem.

当我在做的时候:

case FRAGMENT_OPTION2:
    fragment = ControlPanelFragment.newInstance();
break;

我正在创建一个片段,当我旋转屏幕时 selectItem(int position) 再次被调用,因此创建了同一对象的新实例,因此步骤 7和以下.解决方案是检查片段是否已经创建并使用他而不是创建新片段.我已经用标签保存了初始片段,他们正在寻找那个标签.如果标签存在,则使用该片段,否则创建一个新片段.

I was creating a fragment and when I rotated the screen selectItem(int position) was again called so a new instance of the same object was created thus the steps 7 and following. The solution was to check if the fragment was already created and use him instead of creating a new one. I've saved the initial fragment with a tag and them looked for that tag. If the tag existed, use that fragment otherwise create a new one.

public void selectItem(int position) {
        Fragment fragment = null;
        switch (position) {
            case FRAGMENT_OPTION1:
                ...
                break;
            case FRAGMENT_OPTION2:
                fragment = getSupportFragmentManager().findFragmentByTag(String.valueOf(position));
                if (fragment == null) {
                    fragment = ControlPanelFragment.newInstance();
                }
                break;
            ...
            case FRAGMENT_OPTIONN:
                ...
                return;
            default:
                break;
        }
        if (fragment != null) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            fragmentManager.beginTransaction().replace(R.id.fragment_container, fragment, 
                    String.valueOf(position)).commitAllowingStateLoss();
        }
}

这篇关于Android oncreateview 调用了两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:Android oncreateview 调用了两次

基础教程推荐