Piotr Zaremba
Piotr Zaremba

Reputation: 63

Saving application state after turning landscape with viewModel

I'm trying to preserve state of my activity after rotating to landscape (configuration change). In oficial docs it says that with viewModel this should be handled, but its not. Obviously onCreate is called and relaods everything. My applciation displays a list of images called from api. Tried SaveStateHandle, but i dont think it will work with ViewModel done in Singleton. I figured one thing though, when I call callApi method once (I set a static flag if it was called) it works fine (after scrolling down and changing to landscape, it stays where I scrolled).

repo: https://github.com/LightingTT/PicturesRecycler

ViewModel:

public class PictureListViewModel extends ViewModel{

    private MutableLiveData<List<Pictures>> pictureList = new MutableLiveData<>();
    private PictureRepository pictureRepository;

    public PictureListViewModel(SavedStateHandle savedStateHandle) {
        pictureRepository = PictureRepository.getInstance();
    }

    //Gets its liveData from Repository
    public LiveData<List<Pictures>> getPictures(){
        return pictureRepository.getPictures();
    }

    public void picturesApi(String page, String limit) {
        pictureRepository.picturesApi(page, limit);
    }


}

MainActivity:

public class MainActivity extends AppCompatActivity {

    public static List<Pictures> imageList;
    private MyRecycleAdapter recyclerAdapter;
    private PictureListViewModel pictureListViewModel;
    private ActivityMainBinding activityMainBinding;
    private static boolean isNew = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        pictureListViewModel = new ViewModelProvider(this).get(PictureListViewModel.class);

        initRecyclerView();
        subscribeObservers();
        callAPI();
    }

    private void subscribeObservers()
    {
        //This is where Activity is observing the livedata in the ViewModel
        pictureListViewModel.getPictures().observe(this, (List<Pictures> pictures) -> {
            recyclerAdapter.updateRecycleAdapter(pictures);
        });
    }

    private void initRecyclerView()
    {
            imageList = new ArrayList<>();
            RecyclerView recycleView = findViewById(R.id.linear_layout_with_recycleView_ID);

            GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
            recycleView.setLayoutManager(gridLayoutManager);
            recyclerAdapter = new MyRecycleAdapter(MainActivity.this, imageList);
            recycleView.setAdapter(recyclerAdapter);
    }

     //MainActivity <-- PictureListViewModel <-- PictureRepository <-- PictureApiClient
    private void picturesApi(String page, String limit)
    {
        pictureListViewModel.picturesApi(page, limit);
    }

    //Temp workaround for changing to landscape and saving state
    private void callAPI(){
//        if (!isNew)
//        {
            //Number of pages and number of images
            picturesApi("4", "40");
            isNew = true;
//        }
    }
}


Upvotes: 0

Views: 241

Answers (2)

Ashutosh Sagar
Ashutosh Sagar

Reputation: 1009

Yes, the above-described scenario will happen if you fetch data onCreate(). There are two ways you can handle this -

  1. Call the method, which fetches the data from the ViewModel itself.

  2. Use this -

    if (!::mBinding.isInitialized) {

    }

Use this block, as if the binding has already been initialized it won't do that again.

Upvotes: 0

EpicPandaForce
EpicPandaForce

Reputation: 81549

public class PictureListViewModel extends ViewModel {
    private final PictureRepository pictureRepository;
    private final LiveData<List<Pictures>> pictures;

    public PictureListViewModel(SavedStateHandle savedStateHandle) {
        pictureRepository = PictureRepository.getInstance();
        pictures = pictureRepository.getPictures();

        pictureRepository.picturesApi("4", "40");
    }

    public LiveData<List<Pictures>> getPictures(){
        return pictures;
    }

    public void picturesApi(String page, String limit) {
        pictureRepository.picturesApi(page, limit);
    }
}

and

public class MainActivity extends AppCompatActivity {
    private MyRecycleAdapter recyclerAdapter;
    private PictureListViewModel pictureListViewModel;
    private ActivityMainBinding activityMainBinding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        pictureListViewModel = new ViewModelProvider(this).get(PictureListViewModel.class);

        initRecyclerView();

        pictureListViewModel.getPictures().observe(this, (List<Pictures> pictures) -> {
            recyclerAdapter.updateRecycleAdapter(pictures);
        });
    }
    
    private void initRecyclerView() {
        RecyclerView recycleView = findViewById(R.id.linear_layout_with_recycleView_ID);

        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
        recycleView.setLayoutManager(gridLayoutManager);
        recyclerAdapter = new MyRecycleAdapter(MainActivity.this, Collections.emptyList());
        recycleView.setAdapter(recyclerAdapter);
    }
}

Upvotes: 1

Related Questions