Search code examples
androidandroid-fragmentsandroid-recyclerviewandroid-adapterandroid-tablayout

Blank Fragment inside Tablayout / Viewpager


So i'm desperately looking for an answer to my problem. I spend hours try and retry some things but that did not work. So here is my problem :

I have only one activity for my application which is the main activity. This activity contains a bottom navigation bar and a frame layout to load a fragment depending the choice of the item on the bottom navigation bar.

My PredictionsFragment (loaded by bottom navigation bar) contains a TabLayout (using SmartTabLayout library). In this Fragment, a list of data is loaded in a thread because it use internet connection. TabLayout is containing PredictionsViewFragment which displays a RecyclerView. When I select the PredictionsFragment on my bottom navigation bar, tablayout and all the recyclerview are perfectly displayed. But when I go to another item and go back to PredictionsFragment it displays a blank view...

PredictionsFragment code :

public class PredictionsFragment extends Fragment {

    private static List<Country> countryList = new ArrayList<>();
    private ViewPager viewPager;
    private SmartTabLayout viewPagerTab;
    private FragmentStatePagerItemAdapter adapter;
    private FragmentPagerItems pages;
    private ProgressBar progressBar;
    private ViewGroup tab;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_predictions_tab, container, false);
        initView(view);
        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (countryList.size() == 0) {
            refresh();
        } else {
            refreshViewPager();
        }
    }

    private void initView(View view) {
        tab = (ViewGroup) view.findViewById(R.id.tab);
        tab.addView(LayoutInflater.from(getContext()).inflate(R.layout.fragment_view_predictions, tab, false));
        progressBar = (ProgressBar) view.findViewById(R.id.progressbar);
        viewPager = (ViewPager) view.findViewById(R.id.viewpager);
        viewPagerTab = (SmartTabLayout) view.findViewById(R.id.viewpagertab);

        viewPager.setOffscreenPageLimit(countryList.size());

        pages = new FragmentPagerItems(getContext());
        adapter = new FragmentStatePagerItemAdapter(getFragmentManager(), pages){
            public int getItemPosition(Object object) {
                return POSITION_NONE;
            }
        };
        viewPager.setAdapter(adapter);
        viewPagerTab.setViewPager(viewPager);
    }

    private void refresh() {
        // Thread car connexion internet
        new Thread(new Runnable() {
            @Override
            public void run() {
                countryList = InternetData.getCountryList();
                refreshViewPager();
            }
        }).start();
    }


    private void refreshViewPager() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
            for (Country country : countryList) {
                pages.add(FragmentPagerItem.of(country.getCode(), PredictionsViewFragment.class));
            }
            adapter.notifyDataSetChanged();
            viewPagerTab.setViewPager(viewPager);
            progressBar.setVisibility(View.GONE);
            }
        });
    }

    public static List<Prediction> getPredictionList(int index) {
        return countryList.get(index).getPredictionList();
    }
}

PredictionsViewFragment code :

public class PredictionsViewFragment extends Fragment {
    private RecyclerView recyclerView;
    private PredictionAdapter adapter;
    private int position;

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.recycler_view_pronos, container, false);
        position = FragmentPagerItem.getPosition(getArguments());
        initRecyclerView(view);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }

    private void initRecyclerView(View view) {
        recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        adapter = new PredictionAdapter(PredictionsFragment.getPredictionList(position));
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerView.setAdapter(adapter);
    }
}

Screenshot of the blank fragment and the app

EDIT :

When I use getChildFragmentManager() method :

adapter = new FragmentStatePagerItemAdapter(getChildFragmentManager(), pages){
            public int getItemPosition(Object object) {
                return POSITION_NONE;
            }
        };

I get this error when I go the second time on the Fragment (The first time I go on it, it works perfectly) :

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.util.SparseArray.get(int)' on a null object reference
                      at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:936)
                      at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:217)
                      at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1461)
                      at android.view.View.dispatchRestoreInstanceState(View.java:18608)
                      at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3821)
                      at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3827)
                      at android.view.View.restoreHierarchyState(View.java:18586)
                      at android.support.v4.app.Fragment.restoreViewState(Fragment.java:494)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1486)
                      at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
                      at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
                      at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
                      at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
                      at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
                      at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
                      at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
                      at android.os.Handler.handleCallback(Handler.java:873)
                      at android.os.Handler.dispatchMessage(Handler.java:99)
                      at android.os.Looper.loop(Looper.java:193)
                      at android.app.ActivityThread.main(ActivityThread.java:6669)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

EDIT 2 :

I added these lines to the onViewCreated method on my PredictionsFragment :

else {
      refreshViewPager();
     }

But it does absolutely nothing... The name of the tab appears properly but not the recyclerview... It's like the Fragment inside the tablayout isn't loaded

EDIT 3 : I have added a SwipeRefreshLayout to my recyclerview and for the 2 first tabs i can't do a pull to refresh and from the 3rd tabs only one item of the recyclerview appears and pull to refresh "works" but it displays only one item in the recyclerview

If you have any questions tell me I'll do my best to answer it ! Thanks in advance for you help I appreciate it


Solution

  • So I solved my problem...

    You have to use this :

    adapter = new FragmentPagerItemAdapter(getChildFragmentManager(), pages);
    

    Use FragmentPagerItemAdapter and NOT FragmentStatePagerItemAdapter And for sur you have to use getChildFragmentManager()