我知道这个问题与这个问题有关 RecyclerView store / restore state between activities,但这是针对我自己的问题的,也许您可以提供帮助。我不会发布所有代码,因为有很多代码。
在下面的MainActivity
中,我想遵循该答案中的建议,唯一的不同是,我使用SharePreference
来区分屏幕上最后一个视图。由于某些原因,它仍在旋转时加载layoutManager
的项目。不仅如此,它甚至不保存该视图的状态,它只是重置。我发布了Activity
中的所有代码,希望有人能发现我出了错。如果需要,我还可以发布github链接。除非您具有github中描述的API密钥,否则无法使用整个应用程序。请让我知道您是否需要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);
}
}
}
答案 0 :(得分:0)
onSaveInstanceState(Bundle bundle)
代替onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)
。onRestoreInstanceState(Bundle savedInstanceState)
,您将在Bundle
中获得onCreate()
对象。在那恢复您的状态。SharedPreferences
和FavoriteViewState
而不是使用onSaveInstanceState()
来保存键onCreate()
中的状态。 SharedPreferences
在这里过大。setRecyclerViews()
中,您始终将layoutManger
设置为经理。这可能是个问题,如果不调试代码就很难说。编辑05.01.2019:
返回layoutManager.onSaveInstanceState()
对象的 Parcelable
不能那样工作。您不应该在班级中调用它,而忽略它,它是在内部调用的。为了正确还原视图,您需要在onSaveInstanceState()
中保存数据列表,稍后将在onCreate()
中进行恢复。您还可以将最后单击的位置保存在那里,在这种情况下,将在重新创建视图后重新设置应该设置哪个布局管理器的信息。