Как правильно восстановить состояние просмотра при вращении? - PullRequest
0 голосов
/ 03 января 2019

Я знаю, что этот вопрос относится к этому вопросу RecyclerView хранит / восстанавливает состояние между действиями , но оно относится к моей собственной проблеме, может быть, вы можете помочь. Я не буду публиковать весь код, так как его много.

В MainActivity ниже я хочу следовать тому, что предлагается в этом ответе, единственное отличие состоит в том, что я использую SharePreference, чтобы различать, какой вид был последним на экране. По какой-то причине он по-прежнему загружает предметы на layoutManager при вращении. Не только это, но даже не сохраняет состояние этого представления, оно просто сбрасывается. Я выложил весь код из этого Activity в надежде, что кто-то может определить, где я ошибся. Я также могу опубликовать ссылку на GitHub, если это необходимо. Целое приложение не может быть использовано, если у вас нет ключа API, описанного в github. Пожалуйста, дайте мне знать, если вам нужен 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 Ответ

0 голосов
/ 03 января 2019
  1. Используйте onSaveInstanceState(Bundle bundle) вместо onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState).
  2. Не переопределяйте onRestoreInstanceState(Bundle savedInstanceState), вы получаете Bundle объект в onCreate().Восстановите там свое состояние.
  3. Вместо использования SharedPreferences для сохранения состояния в ключе FavoriteViewState используйте onSaveInstanceState() и onCreate().SharedPreferences здесь излишне.
  4. В setRecyclerViews() вы всегда устанавливаете layoutManger в качестве своего менеджера.Это может быть проблемой, трудно сказать без отладки вашего кода.

РЕДАКТИРОВАТЬ 05.01.2019:

layoutManager.onSaveInstanceState(), который возвращает Parcelable объектне работает так.Вы не должны называть это в своем классе, забудьте об этом, это называется внутренне.Чтобы правильно восстановить вид, в onSaveInstanceState() необходимо сохранить список данных, который будет восстановлен позже в onCreate().Вы также можете сохранить там свою последнюю нажатую позицию и, в вашем случае, информацию о том, какой менеджер раскладки следует установить после того, как представление будет воссоздано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...