Search code examples
androidandroid-fragmentsfragmentpageradapter

Saving and restoring fragment state in viewpager


This might be a duplicate question however it seems that none of the answers provided can solve my problem. So I have a class that extends ViewPager and in the horizontal navigation, I have 3 pages. In one of the Fragment's onActivityCreated() method I am making a call to a server, fetching some data and inserting TableRows in a TableLayout. Now I want to save this exact state and restore it when navigating back to the same Fragment.

One peculiar thing I have noticed is that when I swipe from one Tab to next and then back to the first one, there is no change in the state of first Tab. However on navigating from first to second to third and then back to first I lose the state. Is there any method to save the state of the Fragment and then restore it later apart from using onSaveInstanceState()? As that would require me to manually store all data in the Bundle. Here is my Fragment

public static class ProfileFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){

        View fragmentView = inflater.inflate(R.layout.fragment_profile, container, false);
        return fragmentView;
    }

    private final int EMPLOYER_TABLE_ROWS = 3;
    private final int STUDENT_TABLE_ROWS = 7;
    @Override
    public void onActivityCreated(Bundle savedInstanceState){
        super.onActivityCreated(savedInstanceState);

        HasuraClient client = Hasura.getClient();

        // make network calls to fetch data from server

        HasuraUser user = client.getUser();
        String[] role = user.getRoles();

        if(role[1].equals(getString(R.string.student_role).toLowerCase())){
            StudentProfileQuery query = new StudentProfileQuery(user.getId());
            client.asRole(getString(R.string.student_role).toLowerCase()).useDataService()
                    .setRequestBody(query)
                    .expectResponseType(ProfileResponse.class)
                    .enqueue(new Callback<ProfileResponse, HasuraException>() {
                        @Override
                        public void onSuccess(ProfileResponse response) {
                            // Handle response

                            // get headingContainer
                            LinearLayout headingContainer = (LinearLayout) getView().findViewById(R.id.name_and_institute);
                            // get inflater object
                            LayoutInflater inflater = LayoutInflater.from(getContext());

                            // place name
                            TextView headingName = (TextView) inflater.inflate(R.layout.profile_page_title, headingContainer, false);
                            headingName.setText(response.getName());
                            headingContainer.addView(headingName, 0);

                            // place instituteName
                            TextView headingInstitution = (TextView) inflater.inflate(R.layout.profile_page_title, headingContainer, false);
                            headingInstitution.setText("Student" + " at " + response.getInstitution());
                            headingContainer.addView(headingInstitution, 1);

                            String[] field = {"Email", "Date Of Birth", "Gender", "Year of Admission", "Year of Passing", "Percentage",
                                    "Resume URL"};
                            String[] detail = {response.getEmail(), response.getDob(), response.getGender(),
                                    response.getYear_of_admission().toString(), response.getYear_of_passing().toString(),
                                    response.getPercentage().toString(), response.getPath_to_cv()};

                            // insert TableRows in TableLayout
                            // get TableLayout container
                            TableLayout tableContainer = (TableLayout) getView().findViewById(R.id.profile_table);

                            for(int i = 0; i < STUDENT_TABLE_ROWS; i++){
                                // inflate TableRow
                                TableRow row = (TableRow) inflater.inflate(R.layout.profile_page_table, tableContainer, false);

                                // inflate element of col0 and set field, width
                                TextView col0Element = (TextView)inflater.inflate(R.layout.profile_table_row_element, row, false);
                                col0Element.setLayoutParams(new ViewGroup.LayoutParams(R.dimen.profile_col_0, ViewGroup.LayoutParams.WRAP_CONTENT));
                                col0Element.setText(field[i]);

                                // inflate element of col1 and set detail, width
                                TextView col1Element = (TextView)inflater.inflate(R.layout.profile_table_row_element, row, false);
                                col1Element.setLayoutParams(new ViewGroup.LayoutParams(R.dimen.profile_col_1, ViewGroup.LayoutParams.WRAP_CONTENT));
                                col1Element.setText(detail[i]);

                                // add col0 element to TableRow
                                row.addView(col0Element, 0);

                                // add col1 element to TableRow
                                row.addView(col1Element, 1);

                                // add TableRow to TableLayout
                                tableContainer.addView(row, i);
                            }
                        }

                        @Override
                        public void onFailure(HasuraException e) {
                            //Handle error
                            Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    });
        }

        else if(role[1].equals(getString(R.string.employer_role).toLowerCase())){
            EmployerProfileQuery query = new EmployerProfileQuery(user.getId());
            client.asRole(getString(R.string.employer_role).toLowerCase()).useDataService()
                    .setRequestBody(query)
                    .expectResponseType(ProfileResponse.class)
                    .enqueue(new Callback<ProfileResponse, HasuraException>() {
                        @Override
                        public void onSuccess(ProfileResponse response) {
                            // Handle response

                            // get headingContainer
                            LinearLayout headingContainer = (LinearLayout) getView().findViewById(R.id.name_and_institute);
                            // get inflater object
                            LayoutInflater inflater = LayoutInflater.from(getContext());

                            // place name
                            TextView headingName = (TextView) inflater.inflate(R.layout.profile_page_title, headingContainer, false);
                            headingName.setText(response.getName());
                            headingContainer.addView(headingName, 0);

                            // place company name and designation
                            TextView headingCompany = (TextView) inflater.inflate(R.layout.profile_page_title, headingContainer, false);
                            headingCompany.setText(response.getDesignation() + " at " + response.getCompany());
                            headingContainer.addView(headingCompany, 1);

                            String[] field = {"Name", "Email", "Date Of Birth", "Gender"};
                            String[] detail = {response.getName(), response.getEmail(), response.getDob(), response.getGender()};

                            // insert TableRows in TableLayout
                            // get TableLayout container
                            TableLayout tableContainer = (TableLayout) getView().findViewById(R.id.profile_table);

                            for(int i = 0; i < EMPLOYER_TABLE_ROWS; i++){
                                // inflate TableRow
                                TableRow row = (TableRow) inflater.inflate(R.layout.profile_page_table, tableContainer, false);

                                // inflate element of col0 and set field, width
                                TextView col0Element = (TextView)inflater.inflate(R.layout.profile_table_row_element, row, false);
                                col0Element.setLayoutParams(new ViewGroup.LayoutParams(R.dimen.profile_col_0, ViewGroup.LayoutParams.WRAP_CONTENT));
                                col0Element.setText(field[i]);

                                // inflate element of col1 and set detail, width
                                TextView col1Element = (TextView)inflater.inflate(R.layout.profile_table_row_element, row, false);
                                col1Element.setLayoutParams(new ViewGroup.LayoutParams(R.dimen.profile_col_1, ViewGroup.LayoutParams.WRAP_CONTENT));
                                col1Element.setText(detail[i]);

                                // add col0 element to TableRow
                                row.addView(col0Element, 0);

                                // add col1 element to TableRow
                                row.addView(col1Element, 1);

                                // add TableRow to TableLayout
                                tableContainer.addView(row, i);
                            }
                        }

                        @Override
                        public void onFailure(HasuraException e) {
                            //Handle error
                            Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    });
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

    }
}

And here is the FragmentPagerAdapter

public class SectionsPagerAdapter extends FragmentPagerAdapter {

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

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a UI (defined as a static inner class below).
        switch(position){
            case 0:
                return new ProfileFragment();

            case 1:
                return new MessagesFragment();

            case 2:
                return new HomeFragment();
        }

        return null;
    }

    @Override
    public int getCount() {
        // Show 3 total pages.
        return 3;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return getString(R.string.profile_tab);
            case 1:
                return getString(R.string.messages_tab);
            case 2:
                return getString(R.string.home_tab);
        }
        return null;
    }
}

Apart from this there are 2 other Fragments whose code I don't think is necessary to post. Thanks in advance!


Solution

  • Use mViewPager.setOffscreenPageLimit(noOfPageYouWantToKeepInMemory);