[英]How to properly restore view state on rotation?
I know this question relates to this question RecyclerView store / restore state between activities but it is specific to my own problem, maybe you can help. 我知道这个问题与此问题相关, RecyclerView在活动之间存储/恢复状态,但这是我自己的问题,也许您可以提供帮助。 I won't post all the code as there is a LOT of it. 我不会发布所有代码,因为有很多代码。
In the MainActivity
below I want follow what what is suggested in that answer, the only difference is that I use SharePreference
to distinguish between what view was last on the screen. 在下面的MainActivity
中,我要遵循该答案中的建议,唯一的区别是,我使用SharePreference
来区分屏幕上的最后一个视图。 For some reason it still loads the items for layoutManager
on rotation. 由于某些原因,它仍在旋转时为layoutManager
加载项目。 Not only this, but it does not even save the state of that view, it just resets. 不仅如此,它甚至不保存该视图的状态,它只是重置。 I posted all the code from this Activity
in the hopes that someone can spot where I went wrong. 我发布了本次Activity
所有代码,希望有人能发现我哪里出了问题。 I can also post the github link if needed. 如果需要,我还可以发布github链接。 Whole app can not be used unless you have API key described in the github. 除非您具有github中描述的API密钥,否则无法使用整个应用程序。 Please let me know if you need the AndroidManifest
or anything else. 如果您需要AndroidManifest
或其他任何东西,请告诉我。
public class MainActivity extends AppCompatActivity implements PosterAdapter.PosterItemClickHandler, FavoritesAdapter.FavoritesClickHandler {
private PosterAdapter posterAdapter;
private FavoritesAdapter favoritesAdapter;
private GridLayoutManager layoutManager;
private GridLayoutManager layoutManager1;
private MovieDataBase mDb;
private SharedPreferences prefs;
private SharedPreferences.Editor editor;
private final String FavoriteViewState = "favorites-view-state";
private boolean VIEWSTATE1;
private Parcelable favListState;
private final String FavListKey = "favorites-key";
private Bundle mBundleRecyclerViewState;
@BindView(R.id.rv_posters)RecyclerView mRecyclerViews;
@BindView(R.id.tv_error_message1) TextView mErrorMessage1;
@BindView(R.id.tv_error_message2) TextView mErrorMessage2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mDb = MovieDataBase.getInstance(getApplicationContext());
setRecyclerViews();
updateUI(popularSortLink);
loadFavoritesData();
prefs = PreferenceManager.getDefaultSharedPreferences(this);
if(savedInstanceState != null){
boolean favoritesState = prefs.getBoolean(FavoriteViewState, VIEWSTATE1);
if(favoritesState) {
favListState = savedInstanceState.getParcelableArrayList(FavListKey);
//List<MovieEntry> movies = new ArrayList<>(favListState);
if(favListState != null) {
favoritesAdapter = new FavoritesAdapter(favListState, MainActivity.this);
//favoritesAdapter.setFavorites(favListState);
mRecyclerViews.setLayoutManager(layoutManager1);
mRecyclerViews.setHasFixedSize(false);
mRecyclerViews.setAdapter(favoritesAdapter);
}
}
}
}
// This method sets the recycler views for the main screen
public void setRecyclerViews(){
// Create the grid layout and apply it to the poster recycler view
layoutManager = new GridLayoutManager(this,3);
layoutManager1 = new GridLayoutManager(this,1);
mRecyclerViews.setLayoutManager(layoutManager);
mRecyclerViews.setHasFixedSize(true);
}
// This method updates the UI based on whether there is a network connection or not.
public void updateUI(String movieLink){
if(!isOnline()){
mErrorMessage1.setVisibility(View.VISIBLE);
mRecyclerViews.setVisibility(View.INVISIBLE);
}else{
mErrorMessage1.setVisibility(View.INVISIBLE);
mRecyclerViews.setVisibility(View.VISIBLE);
startApp(movieLink);
}
}
//Information sourced from https://developer.android.com/training/volley/requestqueue
//09/11/18
// This method makes a network request using Androids Volley mechanisms to retrieve the json data
private void startApp(String movieLink){
RequestQueue mRequestQueue;
// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());
// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);
// Start the queue
mRequestQueue.start();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.GET, movieLink, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
setRecyclerViews();
mErrorMessage2.setVisibility(View.INVISIBLE);
mRecyclerViews.setVisibility(View.VISIBLE);
VIEWSTATE1 = false;
editor = prefs.edit();
editor.putBoolean(FavoriteViewState, VIEWSTATE1);
editor.apply();
//Parse the JSON string and store in a list of Movie objects
List<MovieDetails> movieDetailsList = JsonUtility.parseMovieDetailsJson(response);
// display the data
loadMovieData(movieDetailsList);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO: Handle error
Log.i("TAG", error.toString());
mErrorMessage2.setVisibility(View.VISIBLE);
mRecyclerViews.setVisibility(View.INVISIBLE);
VIEWSTATE1 = false;
editor = prefs.edit();
editor.putBoolean(FavoriteViewState, VIEWSTATE1);
editor.apply();
}
});
mRequestQueue.add(jsonObjectRequest);
}
public void loadMovieData(List movieDetailsList){
//Create the adapter using the MovieDetails lists and apply the adapter to the recycler view
posterAdapter = new PosterAdapter(movieDetailsList, this);
mRecyclerViews.setAdapter(posterAdapter);
}
// This method views changes in the favorites database and updates it's cooresponding recycler view
public void loadFavoritesData(){
MainViewModel viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
viewModel.getMovies().observe(this, new Observer<List<MovieEntry>>() {
@Override
public void onChanged(@Nullable List<MovieEntry> movieEntries) {
Log.d("TAG", "UPDATE FROM THE DATABASE using livedata in viewmodel");
favoritesAdapter = new FavoritesAdapter(movieEntries, MainActivity.this);
}
});
}
//This method updates the main view to show the favorites list
public void showFavsList(){
mRecyclerViews.setLayoutManager(layoutManager1);
mRecyclerViews.setHasFixedSize(false);
mRecyclerViews.setAdapter(favoritesAdapter);
mErrorMessage1.setVisibility(View.INVISIBLE);
VIEWSTATE1 = true;
editor = prefs.edit();
editor.putBoolean(FavoriteViewState, VIEWSTATE1);
editor.apply();
}
@Override //This method opens the next activity and loads data based on the index passed through from the adapter onClick method
public void onPosterItemClick(MovieDetails movieDetails) {
String parcelData = MainActivity.this.getString(R.string.parcel_data);
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra(parcelData, movieDetails);
startActivity(intent);
}
@Override //Override this method to inflate the menu resource
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.sort_by, menu);
return true;
}
@Override //Handle clicks on certain menu items. In this case it handles the sorting methods.
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == R.id.popular_sort){
updateUI(popularSortLink);
return true;
}else if(id == R.id.rating_sort){
updateUI(topRatingSortLink);
return true;
}else if(id == R.id.favorites_sort){
// display the favorites list
showFavsList();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
favoritesState = prefs.getBoolean(FavoriteViewState, VIEWSTATE1);
//Log.d("TEST", String.valueOf(favoritesState));
if(favoritesState){
outState.putParcelableArrayList(FavListKey,favListState);
}
}
}
onSaveInstanceState(Bundle bundle)
instead of onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)
. 使用onSaveInstanceState(Bundle bundle)
代替onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)
。 onRestoreInstanceState(Bundle savedInstanceState)
, you're getting Bundle
object in onCreate()
. 不要重写onRestoreInstanceState(Bundle savedInstanceState)
,您将在onCreate()
获得Bundle
对象。 Restore your state in there. 在那恢复您的状态。 SharedPreferences
to save state in key FavoriteViewState
use onSaveInstanceState()
and onCreate()
. 代替使用SharedPreferences
将状态保存在FavoriteViewState
键中,请使用onSaveInstanceState()
和onCreate()
。 SharedPreferences
is overkill in here. 在这里, SharedPreferences
是多余的。 setRecyclerViews()
you're always setting layoutManger
as your manager. 在setRecyclerViews()
您始终将layoutManger
设置为您的经理。 It may be a problem, it's hard to say without debuging your code. 这可能是一个问题,如果不调试代码就很难说。 EDIT 05.01.2019: 编辑05.01.2019:
layoutManager.onSaveInstanceState()
which returns Parcelable
object dont work like that. 返回Parcelable
对象的layoutManager.onSaveInstanceState()
那样工作。 You're not supposed to call it in your class, forget about it, it is called internally. 您不应该在班级中调用它,而忽略它,它是在内部调用的。 In order to restore your view properly, in onSaveInstanceState()
you need to save your data list which will be restored later in onCreate()
. 为了正确还原视图,您需要在onSaveInstanceState()
中保存数据列表,该列表稍后将在onCreate()
还原。 You can also save there your last clicked position and in your case, information about which layout manager should be set after view will be recreate. 您还可以将最后单击的位置保存在那里,在这种情况下,将在重新创建视图后重新设置应该设置哪个布局管理器的信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.