繁体   English   中英

如何正确恢复旋转状态?

[英]How to properly restore view state on rotation?

我知道这个问题与此问题相关, RecyclerView在活动之间存储/恢复状态,但这是我自己的问题,也许您可​​以提供帮助。 我不会发布所有代码,因为有很多代码。

在下面的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);
    }
}
}
  1. 使用onSaveInstanceState(Bundle bundle)代替onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)
  2. 不要重写onRestoreInstanceState(Bundle savedInstanceState) ,您将在onCreate()获得Bundle对象。 在那恢复您的状态。
  3. 代替使用SharedPreferences将状态保存在FavoriteViewState键中,请使用onSaveInstanceState()onCreate() 在这里, SharedPreferences是多余的。
  4. setRecyclerViews()您始终将layoutManger设置为您的经理。 这可能是一个问题,如果不调试代码就很难说。

编辑05.01.2019:

返回Parcelable对象的layoutManager.onSaveInstanceState()那样工作。 您不应该在班级中调用它,而忽略它,它是在内部调用的。 为了正确还原视图,您需要在onSaveInstanceState()中保存数据列表,该列表稍后将在onCreate()还原。 您还可以将最后单击的位置保存在那里,在这种情况下,将在重新创建视图后重新设置应该设置哪个布局管理器的信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM