Ogi
Ogi

Reputation: 13

How to Save State Data inside recyclerview when screen rotated

I had created a Movie app using android java programming language, the data taken from TMDB using an API, everything is fine and working as i expected, but the problem is data reloaded again and again when the screen rotated, i was following some tutorial from this website but still did not working.

i was following this link : How to save an Android Activity state using save instance state?, but i can't figuring out this tutorial to be implemented on my case

// this is my Movie Fragment
package com.ogi.layarkacamobile.fragment;


import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;

import com.ogi.layarkacamobile.MainActivity;
import com.ogi.layarkacamobile.R;
import com.ogi.layarkacamobile.adapter.MoviesAdapter;
import com.ogi.layarkacamobile.api.Client;
import com.ogi.layarkacamobile.api.Service;
import com.ogi.layarkacamobile.model.movie.MovieData;
import com.ogi.layarkacamobile.model.movie.MoviesResponse;
import com.ogi.layarkacamobile.util.PaginationScrollListener;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * A simple {@link Fragment} subclass.
 */
public class MoviesFragment extends Fragment {
    private static final String TAG = "MoviesFragment";

    RecyclerView rvMoviesList;
    ProgressBar pbMovies;
    MoviesAdapter moviesAdapter;
    LinearLayoutManager linearLayoutManager;

    private static final int PAGE_START = 1;
    private boolean isLoading = false;
    private boolean isLastPage = false;

    private int TOTAL_PAGES = 10;
    private int currentPage = PAGE_START;

    private Service movieService;

    public MoviesFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View layout = LayoutInflater.from(getContext()).inflate(R.layout.fragment_movies, container, false);
        rvMoviesList = layout.findViewById(R.id.rv_movies_id);
        pbMovies = layout.findViewById(R.id.pb_movies_id);
        moviesAdapter = new MoviesAdapter(getContext());

        linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
        rvMoviesList.setLayoutManager(linearLayoutManager);

        rvMoviesList.setItemAnimator(new DefaultItemAnimator());
        rvMoviesList.setAdapter(moviesAdapter);

        rvMoviesList.addOnScrollListener(new PaginationScrollListener(linearLayoutManager) {
            @Override
            protected void loadMoreItems() {
                isLoading = true;
                currentPage += 1;

                // mocking network delay for API  call
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        loadNextPage();
                    }
                }, 1000);
            }

            @Override
            public int getTotalPageCount() {
                return TOTAL_PAGES;
            }

            @Override
            public boolean isLastPage() {
                return isLastPage;
            }

            @Override
            public boolean isLoading() {
                return isLoading;
            }
        });

        // init service and load data
        movieService = Client.getClient().create(Service.class);

        loadFirstPage();

        return layout;
    }

    private void loadFirstPage() {
        Log.d(TAG, "LoadFirstPage");

        callPopularMovieApi()
                .enqueue(new Callback<MoviesResponse>() {
                    @Override
                    public void onResponse(Call<MoviesResponse> call, Response<MoviesResponse> response) {
                        // Got data send into adapter
                        List<MovieData> results = fetchResults(response);
                        pbMovies.setVisibility(View.GONE);
                        moviesAdapter.addAll(results);

                        if (currentPage <= TOTAL_PAGES) moviesAdapter.addLoadingFooter();
                        else isLastPage = true;
                    }

                    @Override
                    public void onFailure(Call<MoviesResponse> call, Throwable t) {
                        t.printStackTrace();
                    }
                });

    }

    private List<MovieData> fetchResults(Response<MoviesResponse> response) {
        MoviesResponse popularMovies = response.body();
        return popularMovies.getResults();
    }

    private void loadNextPage() {
        Log.d(TAG, "loadNextPage "+ currentPage);
        callPopularMovieApi()
                .enqueue(new Callback<MoviesResponse>() {
                    @Override
                    public void onResponse(Call<MoviesResponse> call, Response<MoviesResponse> response) {
                        moviesAdapter.removeLoadingFooter();
                        isLoading = false;

                        List<MovieData> results = fetchResults(response);
                        moviesAdapter.addAll(results);

                        if (currentPage != TOTAL_PAGES)moviesAdapter.addLoadingFooter();
                        else isLastPage = true;
                    }

                    @Override
                    public void onFailure(Call<MoviesResponse> call, Throwable t) {
                        t.printStackTrace();
                    }
                });
    }

    private Call<MoviesResponse> callPopularMovieApi() {
        return  movieService.getPopularMovies("f6602517b834e9ce06a48548f949e397", currentPage);
    }

}

And this is my MainActivity

package com.ogi.layarkacamobile;

import android.content.Intent;
import android.provider.Settings;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

import com.ogi.layarkacamobile.adapter.ViewPagerAdapter;
import com.ogi.layarkacamobile.fragment.MoviesFragment;
import com.ogi.layarkacamobile.fragment.TvShowsFragment;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        ViewPager viewPager = findViewById(R.id.viewpager);
            setupViewPager(viewPager);

        TabLayout tabLayout = findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
    }

    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new MoviesFragment(), getResources().getString(R.string.movies_label));
        adapter.addFragment(new TvShowsFragment(), getResources().getString(R.string.tv_shows_label));
        viewPager.setAdapter(adapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.language_setting) {
            Intent mIntent = new Intent(Settings.ACTION_LOCALE_SETTINGS);
            startActivity(mIntent);
        }
        return super.onOptionsItemSelected(item);
    }
}

I was trying the suggestion about the similar question but non of them working, because i do not know exactly how to implement that in my case, thank you so much in advanced

Upvotes: 0

Views: 1867

Answers (2)

Johann
Johann

Reputation: 29867

Use LiveData. It will cache your Recyclerview data and reload it from internal cache when the device is rotated.

Upvotes: 0

Kabir
Kabir

Reputation: 862

Fragment :

You are using fragment.So prevent destroy on orientation change occurs to fragment you can use setRetainInstance(true)

 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // retain this fragment when activity is re-initialized
        setRetainInstance(true);
    } 

Activity:

When orientaion change occurs,android restarts the running Activity ( onDestroy() is called, followed by onCreate()). If you want to handle inside activity,you cant use: in manifest file for particular activity.

For API 12 and below:

android:configChanges="orientation"

if you are targeting API 13 or above

android:configChanges="orientation|screenSize"

Update:Saving Fragment State on Orientation Change

If you want to use onSaveInstanceState inside activity to save fragment state,You can use putFragment.
In your activity’s onSaveInstanceState looks like this:

@Override
protected void onSaveInstanceState(Bundle outState) {
   getFragmentManager().putFragment(outState, MyFragment.TAG, mMyFragment);
}

For getting fragment state after activity restart,you can use getFragment method.

@Override
protected void onRestoreInstanceState(Bundle inState) {


   FragmentTransaction transaction =getFragmentManager().beginTransaction();

   if (inState != null) {
      mMyFragment = (MyFragment) getFragmentManager().getFragment(inState, MyFragment.TAG);
   } else {
      mMyFragment = new MyFragment();
      transaction.add(R.id.fragment, mMyFragment, MyFragment.TAG);
      transaction.commit();
   }

}

Upvotes: 1

Related Questions