Fragment is null while using FragmentStatePagerAdapter

202 views Asked by At

I have 3 bottom navigation tabs in my application :

  • Home
  • MyTour
  • Profile

In MyTour, I am using MyTourFragment which have 3 different tabs :

  • Pending(0)
  • Success(1)
  • Failed(2)

For all three tabs(Pending, Success, Failed) I am using FragmentMyTourJobList and depend on condition I am showing pending or success or failed data in all three tabs.

Problem statement :

When I click on MyTour Navigation Item, Pending Fragment instance is coming null and I am only able to see blank fragment but if i click to success or failed then I can see data. Pending tab data is only visible after coming back from other tabs but not initially.

Here is MyTourFragment code :

public class MyTourFragment {

    public MyTourFragment() {

    }

    public static MyTourFragment newInstance(MyTourFragmentListener myTourFragmentListener) {
        return new MyTourFragment(myTourFragmentListener);
    }

    private MyTourFragment(MyTourFragmentListener myTourFragmentListener) {
        this.mMyTourFragmentListener = myTourFragmentListener;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mViewModel.setNavigator(this);
        setHasOptionsMenu(true);

        //Get the Tab Id.
        Bundle bundle = this.getArguments();
        if (bundle != null) {
            mViewModel.setSelectedDateTimeMillis(bundle.getLong("todaysDateForMyTour", Calendar.getInstance().getTimeInMillis()));
            mSelectedTabId = bundle.getInt(KEY_SELECTED_TAB, 0);
        }

        mMyTourJobsListPagerAdapter = new MyTourJobsListPagerAdapter(this, mViewModel.getTourIdForSelectedDate(), this);

    }

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

        mFragmentMyTourBinding = getViewDataBinding();

        mFragmentMyTourBinding.vpMyTour.setOffscreenPageLimit(2);
        mFragmentMyTourBinding.vpMyTour.setCurrentItem(0);
        mFragmentMyTourBinding.vpMyTour.setAdapter(mMyTourJobsListPagerAdapter);
        mFragmentMyTourBinding.tabLayoutMyTour.setupWithViewPager(mFragmentMyTourBinding.vpMyTour, true);
        mFragmentMyTourBinding.tabLayoutMyTour.addOnTabSelectedListener(this);

        setUpTabs();
    }

    private void setUpTabs() {

        //Select the current Tab.
        mFragmentMyTourBinding.vpMyTour.setCurrentItem(mSelectedTabId);

        //Refresh job list as per the selected date.
        FragmentMyTourJobsList fragmentMyTourJobsList = mMyTourJobsListPagerAdapter.getFragmentAtTab(mSelectedTabId); **// this is null first time**
        if (fragmentMyTourJobsList != null) {
            fragmentMyTourJobsList.refreshJobsList(mViewModel.getTourIdForSelectedDate());
        } 
    }
}    

Here is MyTourJobsListPagerAdapter code :

public class MyTourJobsListPagerAdapter extends FragmentStatePagerAdapter {

    private static final int MY_TOUR_JOBS_LIST_PAGES_COUNT = 3;
    private static final int POSITION_TAB_PENDING = 0;
    private static final int POSITION_TAB_SUCCESS = 1;
    private static final int POSITION_TAB_FAILED = 2;
    private HashMap<Integer, FragmentMyTourJobsList> mTabsFragments = new HashMap<Integer, FragmentMyTourJobsList>();
    private long mTourId;
    private FragmentMyTourJobsList.FragmentMyTourJobsListListener mFragmentMyTourJobsListListener;

    public MyTourJobsListPagerAdapter(Fragment fragment, long tourId, FragmentMyTourJobsList.FragmentMyTourJobsListListener fragmentMyTourJobsListListener) {
        super(fragment.getChildFragmentManager(), BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
        this.mTourId = tourId;
        this.mFragmentMyTourJobsListListener = fragmentMyTourJobsListListener;
    }

    public void setTourId(long tourId) {
        this.mTourId = tourId;
    }

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

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        mTabsFragments.put(position, (FragmentMyTourJobsList) fragment);
        return fragment;
    }


    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        mTabsFragments.remove(position);
        super.destroyItem(container, position, object);
    }

    @Override
    public Fragment getItem(int position) {
        FragmentMyTourJobsList fragmentMyTourJobsList;
        switch (position) {
            case POSITION_TAB_SUCCESS:
                fragmentMyTourJobsList = getFragmentWithBundle(Constants.JOB_STATUS_SUCCESSFUL);
                break;
            case POSITION_TAB_FAILED:
                fragmentMyTourJobsList = getFragmentWithBundle(Constants.JOB_STATUS_FAILED);
                break;
            case POSITION_TAB_PENDING:
            default:
                fragmentMyTourJobsList = getFragmentWithBundle(Constants.JOB_STATUS_ACCEPTED);
                break;

        }
        return fragmentMyTourJobsList;
    }

    public FragmentMyTourJobsList getFragmentAtTab(int tabPosition) {
        return mTabsFragments.get(tabPosition);
    }

    private FragmentMyTourJobsList getFragmentWithBundle(String jobsStatus) {
        FragmentMyTourJobsList fragmentToLoad = FragmentMyTourJobsList.newInstance();

        Bundle bundle = new Bundle();
        bundle.putString(FragmentMyTourJobsList.KEY_ARG_JOBS_STATUS, jobsStatus);
        bundle.putLong(FragmentMyTourJobsList.KEY_ARG_TOUR_ID, mTourId);
        bundle.putSerializable(FragmentMyTourJobsList.KEY_ARG_FRAGMENT_MY_TOUR_JOBS_LIST_LISTENER, mFragmentMyTourJobsListListener);

        fragmentToLoad.setArguments(bundle);

        return fragmentToLoad;
    }
}

Everything is working but when i will go to Pending tab first time then it's not working. I am missing anything here?

Added FragmentMytourJobList

public class FragmentMyTourJobsList extends BaseFragment<FragmentMyTourJobsListBinding, MyTourJobsListViewModel> implements MyTourJobsListNavigator {

    public static FragmentMyTourJobsList newInstance() {
        return new FragmentMyTourJobsList();
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mViewModel.setNavigator(this);

        Bundle bundle = this.getArguments();
        if (bundle != null) {
            mJobsStatus = bundle.getString(KEY_ARG_JOBS_STATUS);
            mTourId = bundle.getLong(KEY_ARG_TOUR_ID, 0);
        }
    }

    @Override
    public int getBindingVariable() {
        return myTourJobsListViewModel;
    }

    @Override
    public int getLayoutId() {
        return R.layout.fragment_my_tour_jobs_list;
    }

    @Override
    public MyTourJobsListViewModel getViewModel() {
        mViewModel = ViewModelProviders.of(this, new ViewModelProviderFactory(Objects.requireNonNull(getActivity()).getApplication())).get(MyTourJobsListViewModel.class);
        return mViewModel;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mFragmentMyTourJobsListBinding = getViewDataBinding();

        // fetch job list  from database
        ArrayList<JobUiModel> jobList = mViewModel.fetchJobs(mTourId, mJobsStatus);
        RecyclerView.LayoutManager rvLayoutManager = new LinearLayoutManager(getActivity());
        mFragmentMyTourJobsListBinding.rvMyTourJobs.setLayoutManager(rvLayoutManager);

        // initialize adapter
        mJobsListAdapter = new MyTourJobsListAdapter(getContext(), jobList, mJobsStatus);
        mFragmentMyTourJobsListBinding.rvMyTourJobs.setAdapter(mJobsListAdapter);
        mJobsListAdapter.setClickInterface(this);

        mFragmentMyTourJobsListBinding.rvMyTourJobs.addItemDecoration(new EndOffsetItemDecoration(CommonUtils.dpToPx(56)));
    }

    void refreshJobsList(long tourId) {

        if (tourId > 0) {
            mTourId = tourId;
            mViewModel.fetchJobs(tourId, mJobsStatus);
            // fetch job list  from database
            ArrayList<JobUiModel> jobList = mViewModel.fetchJobs(mTourId, mJobsStatus);
            mJobsListAdapter.setDataset(jobList);
            mJobsListAdapter.notifyDataSetChanged();


        } else {
            mJobsListAdapter.setDataset(null);
            mJobsListAdapter.notifyDataSetChanged();

        }
    }
}
0

There are 0 answers