1

There's RecyclerView and during orientation change I want the data to not load again from internet. How do you do that?

Here's the code

    package picodiploma.dicoding.database.picodiploma.dicoding.database.tv;


import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;

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

import picodiploma.dicoding.database.ApiClient;
import picodiploma.dicoding.database.ApiInterface;
import picodiploma.dicoding.database.R;
import retrofit2.Call;
import retrofit2.Callback;

import static android.view.View.VISIBLE;


/**
 * A simple {@link Fragment} subclass.
 */
public class TvShow extends Fragment  {

    private static RecyclerView recyclerView;
    private static final String API_KEY = "2e08750083b7e21e96e915011d3f8e2d";
    private static final String TAG = TvShow.class.getSimpleName();
    private static ProgressBar progressBar;
    private static List<ResultsItem> resultsTv = new ArrayList<>();
    private static TvShowRecyclerAdapter recyclerAdapter;


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

    }

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

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

        recyclerView = view.findViewById(R.id.recycler_tv);
        progressBar = view.findViewById(R.id.progress_bar);

        progressBar.setVisibility(VISIBLE);


        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
        recyclerView.setLayoutManager(layoutManager);

        getData();

        if (savedInstanceState == null) {
            getData();
        }
        else  {
            resultsTv = savedInstanceState.getParcelableArrayList("tv");
            recyclerAdapter.refill(resultsTv);
        }


        return view;
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        outState.putParcelableArrayList("tv", (ArrayList<? extends Parcelable>) resultsTv);
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // TODO Auto-generated method stub
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.menu, menu);
    }

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

    public void getData() {
        ApiInterface apiInterface = ApiClient.getList().create(ApiInterface.class);

        Call<Response> responseCall = apiInterface.getTvList(API_KEY);
        responseCall.enqueue(new Callback<Response>() {
            @Override
            public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
                resultsTv = response.body().getResults();
                recyclerAdapter = new TvShowRecyclerAdapter(resultsTv, getContext());
                recyclerView.setAdapter(recyclerAdapter);
                recyclerView.setVisibility(VISIBLE);
                progressBar.setVisibility(View.GONE);
            }

            @Override
            public void onFailure(Call<Response> call, Throwable t) {
                progressBar.setVisibility(View.GONE);
                Log.d(TAG, t.toString());
            }
        });
    }


}

Right now the after orientation change the RecyclerView load data again from the internet. I want to make it use previously saved data on the Fragment. Btw, the Fragment is also connected to FragmentPagerAdapter on MainActivity. Thank you for your answers.

ghifari.akbar
  • 119
  • 1
  • 7

2 Answers2

1

The recommended way to deal with these kind of situations - handling orientation changes - without needing to refetch the data from network, is to use the ViewModel from the Android Architecture Components from google.

You ViewModel can be like below

public class YourViewModel extends ViewModel {

private MutableLiveData<List<ResultsItem>> resultsItem;

public LiveData<List< ResultsItem >> getData() {
    if (resultsItem == null) {
        resultsItem = new MutableLiveData<List<resultsItem>>();
        loadData();
    }
    return resultsItem;
}

private void loadData() {
    // Request your data from network
}
}

And then in your Fragment

YourViewModel model = ViewModelProviders.of(this).get(YourViewModel.class);
    model.getData().observe(this, resultsItem -> {
        // here you can update UI - passing the list of data
    });
makis.k
  • 432
  • 6
  • 23
  • what about the recyclerview? is it loaded on here? `model.getData().observe(this, resultsItem -> {` – ghifari.akbar Jul 01 '19 at 16:16
  • Yeah. The recycler view and the adapter should be initialised and inside the `observe` you will just need to set the data in the adapter and `notifyDatasetChanged()` – makis.k Jul 01 '19 at 16:18
  • `java.util.ArrayList cannot be cast to android.arch.lifecycle.MutableLiveData` when trying to set retrieved data to Mutable<> – ghifari.akbar Jul 01 '19 at 16:37
  • 1
    You should use `setValue()` to set the value to the MutableLiveData object – makis.k Jul 01 '19 at 16:40
-1

Possible duplicate of this question. When the orientation of the device changes,android creates a new instance of the particular activity or fragment.So data will be lost.But you can override onSaveInstanceState method of the activity/fragment, then write the data in bundle implementing parcelable or serializable interface in ResultItem class and in oncreate, you need to check if data available else you need to load the data from the server.

Gowtham K K
  • 3,123
  • 1
  • 11
  • 29