Reputation: 63
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
Reputation: 1009
Yes, the above-described scenario will happen if you fetch data onCreate()
. There are two ways you can handle this -
Call the method, which fetches the data from the ViewModel itself.
Use this -
if (!::mBinding.isInitialized) {
}
Use this block, as if the binding has already been initialized it won't do that again.
Upvotes: 0
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