在popBackStack之后,ViewPager中的碎片没有被恢复
问题
从另一个片段返回后,片段不会重新连接到其托pipe的ViewPager。
情况
一个活动托pipe一个片段,其布局包含一个ViewPager(下面的例子中的PageListFragment)。 ViewPager由FragmentStateViewPagerAdapter填充。 分页器(下面的例子中的PageFragment
中的单个碎片可以打开包含一组新页面的子页面列表。
行为
只要后退button没有按下,所有工作正常。 只要用户closures其中一个子页面列表,就会重新创build之前的列表,但是没有之前显示的页面。 浏览父页面列表上的其他页面仍然有效。
码
示例应用程序可以在github上find:
活动
public class MainActivity extends FragmentActivity { private static final String CURRENT_FRAGMENT = MainActivity.class.getCanonicalName() + ".CURRENT_FRAGMENT"; public static final String ARG_PARENTS = "Parents"; public void goInto(String mHostingLevel, String mPosition) { Fragment hostingFragment = newHostingFragment(mHostingLevel, mPosition); addFragment(hostingFragment); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); addBaseFragment(); } private void addBaseFragment() { Fragment hostingFragment = newHostingFragment("", ""); addFragment(hostingFragment); } private Fragment newHostingFragment(String mHostingLevel, String oldPosition) { Fragment hostingFragment = new PageListFragment(); Bundle args = new Bundle(); args.putString(ARG_PARENTS, mHostingLevel + oldPosition +" > "); hostingFragment.setArguments(args); return hostingFragment; } private void addFragment(Fragment hostingFragment) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragmentSpace, hostingFragment, CURRENT_FRAGMENT); transaction.addToBackStack(null); transaction.commit(); } }
PageListFragment
public class PageListFragment extends Fragment { private String mParentString; public PageListFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_hosting, container, false); } @Override public void onResume() { mParentString = getArguments().getString(MainActivity.ARG_PARENTS); ViewPager viewPager = (ViewPager) getView().findViewById(R.id.viewPager); viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getFragmentManager(),mParentString)); super.onResume(); } private static class SimpleFragmentStatePagerAdapter extends FragmentStatePagerAdapter { private String mHostingLevel; public SimpleFragmentStatePagerAdapter(FragmentManager fm, String hostingLevel) { super(fm); this.mHostingLevel = hostingLevel; } @Override public android.support.v4.app.Fragment getItem(int position) { PageFragment pageFragment = new PageFragment(); Bundle args = new Bundle(); args.putString(MainActivity.ARG_PARENTS, mHostingLevel); args.putInt(PageFragment.ARG_POSITION, position); pageFragment.setArguments(args); return pageFragment; } @Override public int getCount() { return 5; } } }
PageFragment
public class PageFragment extends Fragment { public static final String ARG_POSITION = "Position"; private String mHostingLevel; private int mPosition; public PageFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View contentView = inflater.inflate(R.layout.fragment_page, container, false); setupTextView(contentView); setupButton(contentView); return contentView; } private void setupTextView(View contentView) { mPosition = getArguments().getInt(ARG_POSITION); mHostingLevel = getArguments().getString(MainActivity.ARG_PARENTS); TextView text = (TextView) contentView.findViewById(R.id.textView); text.setText("Parent Fragments " + mHostingLevel + " \n\nCurrent Fragment "+ mPosition); } private void setupButton(View contentView) { Button button = (Button) contentView.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { openNewLevel(); } }); } protected void openNewLevel() { MainActivity activity = (MainActivity) getActivity(); activity.goInto(mHostingLevel, Integer.toString(mPosition)); } }
经过漫长的调查后发现片段pipe理器存在问题。
当使用像上面那样的构造时,片段事务将片段重新附加到页面列表中将被静静地丢弃。 这基本上是同样的问题,导致一个
java.lang.IllegalStateException: Recursive entry to executePendingTransactions
当试图改变FragmentPager内的片段。
同样的解决scheme,这个错误的问题也适用于这里。 在构buildFragmentStatePagerAdapter时提供正确的子片段pipe理器。
代替
viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getFragmentManager(),mParentString));
做
viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getChildFragmentManager(),mParentString));
另见: github
保罗没有提到的是,如果你使用getChildFragmentManager ,那么你会遭受“回到黑屏的问题”的问题。