Android的oncreateview叫了两声叫了、两声、Android、oncreateview

2023-09-07 09:11:28 作者:我姓王却忘不了你的样子

我已经看到这个问题在这里提出一个以上的时间,但我无法弄清楚如何解决我的情况。

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 - 选定的选项(Con​​trolPanelFragment)被加载:     2.1 - 控制面板上有标签和iconpager。对于每一个寻呼机页面并创建一个新片段每个选项卡。我有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(); 我有这个code:

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 有这个code:

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 - 碎裂 FragmentB FragmentC 有几乎是相同的code:

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 有这个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"));
    }
}

现在,想象我在碎裂的第三个选项卡中选择。如果我旋转屏幕我有这一系列事件:

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

ControlPanelFragment 的onSaveInstanceState 保存当前选项卡和当前片段 碎裂的onSaveInstanceState 保存选项卡碎片寻呼机 navigationDrawer第二个选项被再次调用片段= ControlPanelFragment.newInstance(); ControlPanelFragment onViewCreated 叫,我可以得到保存的数据信息和新的寻呼机和标签创建 碎裂 onViewCreated 被调用,我可以提取保存的数据 FragmentADetail onActivityCreated 获取已保存的数据和correctelly加载数据(至少我认为) 而从现在开始第二组的方法称为第二次,那是previously保存的reseted,所以它现在显示错误的数据的数据 ControlPanelFragment 的onSaveInstanceState 但现在的savedInstanceState为null ControlPanelPagerAdapter 的getItem 被称为实例化3个片段 碎裂的onSaveInstanceState 它现在叫,但是savedInstanceState为null FragmentADetail onActivityCreated 的调用,但现在的标签= 0 ControlPanelFragment onSaveInstanceState saves the current tab and current fragment FragmentA onSaveInstanceState saves the tabs fragments for the pager navigationDrawer second option gets again called fragment = ControlPanelFragment.newInstance(); ControlPanelFragment onViewCreated is called and I can get the saved data information and a new pager and tabs are created FragmentA onViewCreated is called and I can extract the saved data 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 ControlPanelFragment onSaveInstanceState but now the savedInstanceState is null ControlPanelPagerAdapter getItem is called instantiating the 3 fragments FragmentA onSaveInstanceState its now called but savedInstanceState is null 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;

我创建一个片段,当我旋转屏幕选择信息(INT位置)又被称为所以同一个对象的新实例,因此而产生的步骤 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();
        }
}