Android - Child fragment not loading the second time inside FragmentStatePagerAdapter
Asked Answered
S

3

5

I'm having an issue to display correctly fragments inside fragments with a FragmentStatePagerAdapter. The first time everything loads properly, but then the next time the view is blank. I tried this and this answers but it doesn't solve the issue.

So basically I have a FriendActivityFragment which is loaded inside MainActivity:

public class FriendActivityFragment extends Fragment {

private FriendsTabsPagerAdapter mAdapter;
private ViewPager mPager;
private SlidingTabLayout mTabs;

public FriendActivityFragment() {

}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (mAdapter == null) {
        //mAdapter = new FriendsTabsPagerAdapter(getActivity().getSupportFragmentManager());
        mAdapter = new FriendsTabsPagerAdapter(getChildFragmentManager());
    }

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.activity_friend, container, false);
    super.onCreate(savedInstanceState);

    mPager = (ViewPager) view.findViewById(R.id.pager);
    mPager.setAdapter(mAdapter);

    mTabs = (SlidingTabLayout) view.findViewById(R.id.tabs);
    mTabs.setDistributeEvenly(true);
    mTabs.setSelectedIndicatorColors(getResources().getColor(R.color.red));
    mTabs.setBackgroundColor(getResources().getColor(R.color.theme_color));
    mTabs.setViewPager(mPager);

    return view;

}

@Override
public void onResume() {
    super.onResume();
    mAdapter.notifyDataSetChanged();
}
}

Inside this fragment, I have set the FragmentStatePagerAdapter, which looks like this:

public class FriendsTabsPagerAdapter extends FragmentStatePagerAdapter {

    // Tab titles
    private String[] tabs = { "Friends", "Requests" };
    private FriendsListFragment[] mFragments;

    public FriendsTabsPagerAdapter(FragmentManager fm) {
        super(fm);
        mFragments = new FriendsListFragment[tabs.length];
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return tabs[position];
    }

    @Override
    public Fragment getItem(int position) {
        if (mFragments[position] == null) {
            mFragments[position] = FriendsListFragment.getInstance(position);
        }

        return mFragments[position];
    }

    @Override
    public int getCount() {
        // get item count - equal to number of tabs
        return 2;
    }

    @Override
    public Parcelable saveState() {
        return null;
    }
}

And then I loads another fragment, FriendsListFragment, where my listView is:

public class FriendsListFragment extends Fragment {

    private View parentView;
    private ListView listView;
    private FriendListAdapter mAdapter;
    private TextView noFriends;


    public static FriendsListFragment getInstance(int position) {

        FriendsListFragment friendsListFragment = new FriendsListFragment();

        Bundle args = new Bundle();
        args.putInt("position", position);
        friendsListFragment.setArguments(args);

        return friendsListFragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        parentView = inflater.inflate(R.layout.fragment_friend_list, container, false);
        listView   = (ListView) parentView.findViewById(R.id.listView);
        noFriends = (TextView) parentView.findViewById(R.id.noFriends);

        return parentView;
    }


    @Override
    public void onResume() {
        super.onResume();
        parentView.findViewById(R.id.avloadingIndicatorView).setVisibility(View.VISIBLE);
        initView();
    }

    @SuppressLint("NewApi")
    @SuppressWarnings("deprecation")
    public void initView() {

        QueryAPI query = new QueryAPI();

        Bundle bundle = getArguments();
        final int pos = bundle.getInt("position");

        if (bundle != null) {
            switch (pos) {
                case 0:
                    // Friend List
                    listView.setVisibility(View.VISIBLE);
                    parentView.findViewById(R.id.avloadingIndicatorView).setVisibility(View.VISIBLE);
                    query.friendList(new QueryAPI.ApiResponse<List<ModelFriend>>() {
                        @Override
                        public void onCompletion(List<ModelFriend> result) {
                            parentView.findViewById(R.id.avloadingIndicatorView).setVisibility(View.GONE);
                            if (result != null && !result.isEmpty()) {
                                if (mAdapter == null) {
                                    mAdapter = new FriendListAdapter(getActivity(), R.layout.fragment_friend_list_item, result);
                                }
                                listView.setAdapter(mAdapter);
                                mAdapter.notifyDataSetChanged();
                            } else {
                                noFriends.setVisibility(View.VISIBLE);
                            }
                        }
                    });
                    break;

                case 1:
                    // Friend Requests
                    parentView.findViewById(R.id.avloadingIndicatorView).setVisibility(View.VISIBLE);
                    query.friendRequestList(new QueryAPI.ApiResponse<List<ModelUser>>() {
                        @Override
                        public void onCompletion(List<ModelUser> result) {
                            parentView.findViewById(R.id.avloadingIndicatorView).setVisibility(View.GONE);
                            if (result != null && !result.isEmpty()) {
                                FriendRequestListAdapter adapter = new FriendRequestListAdapter(getActivity(), R.layout.fragment_friend_list_item, result);
                                listView.setAdapter(adapter);
                                adapter.notifyDataSetChanged();

                            } else {
                                noFriends.setText("No friend request.");
                                noFriends.setVisibility(View.VISIBLE);
                            }
                        }
                    });
                    break;
            }
        }

    }

}

Any idea what the problem might be?

EDIT: the crash log if I return super.saveState();

03-14 13:50:29.965 12418-12418/com.kalianey.oxapp E/FragmentManager: Fragment no longer exists for key f0: index 0
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp E/FragmentManager: Activity state:
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/FragmentManager:   Active Fragments in 53f7ca48:
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/FragmentManager:     #0: null
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/FragmentManager:     #1: null
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/FragmentManager:   Added Fragments:
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/FragmentManager:     #0: FriendsListFragment{53dde390}
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/FragmentManager:     #1: FriendsListFragment{53dde4dc}
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/FragmentManager:   FragmentManager misc state:
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/FragmentManager:     mHost=null
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/FragmentManager:     mContainer=null
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/FragmentManager:     mCurState=0 mStateSaved=true mDestroyed=true
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/FragmentManager:     mAvailIndices: [0, 1]
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp D/AndroidRuntime: Shutting down VM
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa4ce9b20)
03-14 13:50:29.965 12418-12418/com.kalianey.oxapp E/AndroidRuntime: FATAL EXCEPTION: main
                                                                    Process: com.kalianey.oxapp, PID: 12418
                                                                    java.lang.IllegalStateException: Fragment no longer exists for key f0: index 0
                                                                        at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:673)
                                                                        at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:211)
                                                                        at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1319)
                                                                        at android.view.View.dispatchRestoreInstanceState(View.java:12799)
                                                                        at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2637)
                                                                        at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2643)
                                                                        at android.view.View.restoreHierarchyState(View.java:12777)
                                                                        at android.support.v4.app.Fragment.restoreViewState(Fragment.java:471)
                                                                        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1105)
                                                                        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1259)
                                                                        at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
                                                                        at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1624)
                                                                        at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
                                                                        at android.os.Handler.handleCallback(Handler.java:733)
                                                                        at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                        at android.os.Looper.loop(Looper.java:136)
                                                                        at android.app.ActivityThread.main(ActivityThread.java:5001)
                                                                        at java.lang.reflect.Method.invokeNative(Native Method)
                                                                        at java.lang.reflect.Method.invoke(Method.java:515)
                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
                                                                        at dalvik.system.NativeStart.main(Native Method)
03-14 13:55:30.165 12418-12418/? I/Process: Sending signal. PID: 12418 SIG: 9
Salerno answered 10/3, 2016 at 13:27 Comment(9)
I think you should instantiate your madapter inside onCreateView instead of onCreateMagee
I tried, it's not working :/Salerno
did you tried calling super.saveState() instead of returning null.Chancre
If I do that, the app crash when I open the fragment the second time with this error: java.lang.IllegalStateException: Fragment no longer exists for key f0: index 0Salerno
can you please post the whole exception log? I think thats the reason for the weird behaviour. I have faced similar issue and removing this did the trickChancre
Sure, I edited my postSalerno
try initializing adapter in onCreateView instead of onCreateChancre
I tried as said above, it's not workingSalerno
Let us continue this discussion in chat.Chancre
P
4

I have also face same issue and i fixed by changing some point in fragmentAdapter and in Parent fragment.

  1. First check you extend FragmentPagerAdapter in FriendsTabsPagerAdapter.
  2. When you create an object of FriendsTabsPagerAdapter you must be pass getChildFragmentManager() method instead of getActivity().getSupportFragmentManager().

I changed only these two point any my fragment work properly.

Penance answered 1/11, 2017 at 8:42 Comment(0)
G
3

I have encountered this problem a few weeks ago,and always has some wrong with saveState() or restoreState() in FragmentStatePagerAdapter, so I understand why you try to return null in saveState().

First I advised you use FragmentPagerAdapter instead of FragmentStatePagerAdapter, and add this in your Adapter:

@Override
public int getItemPosition(Object object) {
    return PagerAdapter.POSITION_NONE;
}

If it doesn't work for you, maybe you'd like to create you own PageAdapter directly inherit from PageAdapter, and copy the FragmentPagerAdapter's code into your PageAdapter. If you insist to use restoreState() and saveState(), just follow FragmentStatePagerAdapter and debug it.

This may seems trouble, but after I implemented my PageAdapter, I would never afraid of any qestions about viewpage + fragment.

Glassy answered 17/3, 2016 at 7:6 Comment(0)
Y
0

I have face the same issue, use the following code.

public class FriendsTabsPagerAdapter extends FragmentPagerAdapter {

    // Tab titles
    private String[] tabs = { "Friends", "Requests" };
    private FriendsListFragment[] mFragments;

    public FriendsTabsPagerAdapter(FragmentManager fm) {
        super(fm);
        mFragments = new FriendsListFragment[tabs.length];
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return tabs[position];
    }

    @Override
    public Fragment getItem(int position) {
        if (mFragments[position] == null) {
            mFragments[position] = FriendsListFragment.getInstance(position);
        }

        return mFragments[position];
    }

    @Override
    public int getCount() {
        // get item count - equal to number of tabs
        return 2;
    }

}
Yurik answered 6/6, 2018 at 8:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.