Search code examples
androidrestandroid-viewpagerandroid-tabsandroid-networking

First fragment in view pager not showing because of rest api delay


I have a navigation drawer activity, with one fragment having a view pager and tabs. All 4 fragments are fetching data from a server. My problem is that the view pager is loading the first 2 fragments therefore my first fragment doesn't show a content at first because of the delay of the rest api. So the second fragment is being created and shown before the data in the first fragment is parsed and shown. How can I solve this?

This is my fragment container

public class FragmentMoviesContainer extends KFragment {
private MainActivity activity;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_movies_container, container, false);
    activity = (MainActivity) getActivity();
    assert activity != null;
    activity.setVisibleFragment(this);
    SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
    // Set up the ViewPager with the sections adapter.
    ViewPager mViewPager = rootView.findViewById(R.id.container);
    TabLayout tabLayout = rootView.findViewById(R.id.tabs);

    mViewPager.setAdapter(mSectionsPagerAdapter);
    tabLayout.setupWithViewPager(mViewPager);

    return rootView;
}

@Override
public void onResume() {
    super.onResume();
    ActionBar actionBar = activity.getSupportActionBar();
    if (actionBar != null)
        actionBar.setTitle(R.string.movies);

    activity.getNavigationView().setCheckedItem(R.id.nav_movies);
    activity.setElevation(true);
}

public class SectionsPagerAdapter extends FragmentPagerAdapter {

    SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }


    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return replaceFragmentMovies(Constants.STRINGS.UPCOMING);
            case 1:
                return replaceFragmentMovies(Constants.STRINGS.NOW_PLAYING);
            case 2:
                return replaceFragmentMovies(Constants.STRINGS.POPULAR);
            case 3:
                return replaceFragmentMovies(Constants.STRINGS.TOP_RATED);
            default:
                return null;
        }
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return getString(R.string.coming_soon);
            case 1:
                return getString(R.string.now_playing);
            case 2:
                return getString(R.string.popular);
            case 3:
                return getString(R.string.top_rated);
            default:
                return "";
        }
    }

    @Override
    public int getCount() {
        return 4;
    }


    private FragmentMovies replaceFragmentMovies(String type) {
        FragmentMovies fragmentMovies = new FragmentMovies();
        fragmentMovies.setType(type);
        return fragmentMovies;
    }
}

@Override
public void serviceResponse(int responseID, List<KObject> objects) {

}

@Override
public void update(ModelService service, boolean reload) {
}
}

Here's my fragment showed in the tabs

public class FragmentMovies extends KFragment implements MoviesAdapter.OnLoadMoreListener {
private MainActivity activity;
private ModelService service;

private RecyclerView moviesRv;
private String type;

public void setType(String type) {
    this.type = type;
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_movies, container, false);
    activity = (MainActivity) getActivity();

    if (activity != null) {
        service = activity.getService();
        activity.setVisibleFragment(this);
    }

    moviesRv = rootView.findViewById(R.id.movies_list);
    moviesRv.setLayoutManager(new LinearLayoutManager(getContext()));
    this.update(service, false);

    return rootView;
}


@Override
public void serviceResponse(int responseID, List<KObject> objects) {
    if ((objects != null && !objects.isEmpty()) && (responseID == Constants.UPCOMING || responseID == Constants.NOW_PLAYING || responseID == Constants.POPULAR
            || responseID == Constants.TOP_RATED)) {
        Section section = (Section) objects.get(0);
        MovieListAdapter adapter = new MovieListAdapter(getContext(), section.getMovieList());
        moviesRv.setAdapter(adapter);
    }
}

@Override
public void update(final ModelService service, final boolean reload) {
    boolean hasConnection = Connection.isNetworkAvailable(getContext());
    if (hasConnection && service != null) {
        final int responseId = getResponseID();
        service.getMovies(type, "", false, responseId, reload);
    } else {
//            progressBar.setVisibility(View.GONE);
        DialogHelper.noConnectionDialog(getContext());
    }
}

private int getResponseID() {
    switch (type) {
        case Constants.STRINGS.UPCOMING:
            return Constants.UPCOMING;
        case Constants.STRINGS.NOW_PLAYING:
            return Constants.NOW_PLAYING;
        case Constants.STRINGS.POPULAR:
            return Constants.POPULAR;
        case Constants.STRINGS.TOP_RATED:
            return Constants.TOP_RATED;
        default:
            return 0;
    }
}

@Override
public void onLoadMore(MoviesAdapter adapter) {
}

@Override
public void onResume() {
    super.onResume();
    if (activity.getSupportActionBar() != null)
        activity.getSupportActionBar().setTitle("Movies");

    activity.getNavigationView().setCheckedItem(R.id.nav_movies);
    activity.setElevation(true);
    activity.getAddFab().hide();
}

@Override
public void onDestroy() {
    super.onDestroy();
}
}

The method update calls the rest api url and fetches the data. This is a framework I created based on AsyncTask. The list of objects then is returned to the fragment parsed in the method onServiceResponse where I create the adapter and show the data. The problem is that the second fragment is being created before the method onServiceResponse of the first fragment.


Solution

  • You should make api call from the first fragment and after getting the result you should make the rest of the calls. Let me know if you need any help with the code. I think this should be straight forward.