我正在加载RecyclerView
基于对Retrofit
本地SQLite
数据库的调用和存储的数据的。
屏幕旋转时,RecyclerView
保持重置。此外,当我喜欢电影时(将电影添加到我的本地房间数据库中),在某些情况下,微调器无法与填充的数据对齐RecyclerView
。下面是我的代码:
public class MainActivity extends AppCompatActivity { private RecyclerView mMovieResults; private MyAdapter mMovieResultsAdapter; private String query; private String mBaseURL; private int lastFirstVisiblePosition; //TODO: How is someone able to load my API Key if I am storing it private ArrayListmMovieURLS; private ArrayList mMovies; private List mMovieResultsList; private static final String SPINNER_SELECTION = "SPINNER_SELECTION"; private boolean mIsFavoriteSelected; private AppDatabase mDb; private Spinner mSpinner; private SharedPreferences mPrefs; private SharedPreferences.Editor mPrefsEditor; private static Bundle mBundleRecyclerViewState; private int saved_selection = -1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.v("ONCREATE", "ONCREATE"); if (savedInstanceState != null){ saved_selection = savedInstanceState.getInt(SPINNER_SELECTION); } if (isOnline()) { setContentView(R.layout.activity_main); Stetho.initializeWithDefaults(this); mDb = AppDatabase.getInstance(getApplicationContext()); mMovieResults = findViewById(R.id.main_recyclerview_image_results); GridLayoutManager glm = new GridLayoutManager(this, 3); glm.setOrientation(LinearLayoutManager.VERTICAL); mMovieResults.setLayoutManager(glm); mMovieURLS = new ArrayList<>(); mMovies = new ArrayList<>(); mMovieResultsList = new ArrayList<>(); mMovieResultsAdapter = new MyAdapter(mMovieResultsList); mMovieResults.setAdapter(mMovieResultsAdapter); mDb = AppDatabase.getInstance(getApplicationContext()); mPrefs = getSharedPreferences("prefs", MODE_PRIVATE); mPrefsEditor = mPrefs.edit(); switch (saved_selection){ case 0: mBaseURL = "https://api.themoviedb.org/3/movie/popular/"; calltoRetrofit(mBaseURL); break; case 1: mBaseURL = "https://api.themoviedb.org/3/movie/top_rated/"; calltoRetrofit(mBaseURL); break; case 2: mIsFavoriteSelected = true; mMovieURLS.clear(); retrieveMovies(); break; default: mBaseURL = "https://api.themoviedb.org/3/movie/popular/"; break; } } else { setContentView(R.layout.activity_no_internet); return; } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.action_bar_spinner, menu); MenuItem item = menu.findItem(R.id.spinner); mSpinner = (Spinner) item.getActionView(); if (isOnline()) { ArrayAdapter adapter = ArrayAdapter.createFromResource(getApplicationContext(), R.array.spiner_list_item_array, R.layout.custom_spinner); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mSpinner.setAdapter(adapter); if (saved_selection >= 0){ mSpinner.setSelection(saved_selection); } mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView> adapterView, View view, int i, long l) { mPrefsEditor.putInt(SPINNER_SELECTION, i); mPrefsEditor.commit(); switch (i) { case 0: mBaseURL = "https://api.themoviedb.org/3/movie/popular/"; calltoRetrofit(mBaseURL); break; case 1: mBaseURL = "https://api.themoviedb.org/3/movie/top_rated/"; calltoRetrofit(mBaseURL); break; case 2: mIsFavoriteSelected = true; mMovieURLS.clear(); retrieveMovies(); break; default: mBaseURL = "https://api.themoviedb.org/3/movie/popular/"; break; } } @Override public void onNothingSelected(AdapterView> adapterView) { } }); return true; } else { return true; } } @Override protected void onSaveInstanceState(Bundle outState) { outState.putInt(SPINNER_SELECTION, mSpinner.getSelectedItemPosition()); super.onSaveInstanceState(outState); } @Override public boolean onOptionsItemSelected(MenuItem item) { super.onOptionsItemSelected(item); int x = item.getItemId(); Log.v("OPTIONS_ID", String.valueOf(x)); return true; } private void retrieveMovies() { //TODO: I am unsure if I am handling correctly. When I favorite and unfavorite a movie, and then go back to the MainActivity, it is not displaying the correct item from the Spinner. //TODO: For example, favorites may be listed in the Spinner, however the screen may be displaying "TOP" //TODO: How could I tell if I am making unnecessary queries to Room? I know it is a project requirement, but I was not sure how to handle if I am making unnecessary calls //TODO: on screen rotation MainViewModel viewModel = ViewModelProviders.of(this).get(MainViewModel.class); final LiveData > movies = viewModel.getMovies(); movies.observe(this, new Observer
>() { @Override public void onChanged(@Nullable final List
movies) { for (Movie movie : movies) { String photoURL = "http://image.tmdb.org/t/p/w185" + movie.getPoster_path(); Log.v("FAVORITE_URL", photoURL); mMovieURLS.add(photoURL); } runOnUiThread(new Runnable() { @Override public void run() { mMovieResultsList = movies; mMovieResultsAdapter.notifyDataSetChanged(); } }); } }); } @Override protected void onResume() { super.onResume(); ((GridLayoutManager) mMovieResults.getLayoutManager()).scrollToPositionWithOffset(lastFirstVisiblePosition,0); } private void calltoRetrofit(String mBaseURL) { mMovieURLS.clear(); HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC); OkHttpClient client = new OkHttpClient .Builder() .addInterceptor(interceptor) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(mBaseURL) .client(client) .addConverterFactory(GsonConverterFactory.create()) .build(); final ApiInterface apiInterface = retrofit.create(ApiInterface.class); Log.v("API", API_KEY); Call call = apiInterface.getImages(API_KEY); call.enqueue(new Callback () { @Override public void onResponse(Call call, Response response) { Log.v("RESPONSE", response.body().toString()); String totalPages = String.valueOf(response.body().getTotal_pages()); Log.v("TOTAL", totalPages); mMovieResultsList = response.body().getResults(); for (Movie movie : mMovieResultsList) { if (movie.getPoster_path() != null) { String photoURL = "http://image.tmdb.org/t/p/w185" + movie.getPoster_path(); mMovieURLS.add(photoURL); } mMovieResultsAdapter.notifyDataSetChanged(); } } @Override public void onFailure(Call call, Throwable t) { Log.v("FAILURE", t.toString()); } }); } @Override public void onPointerCaptureChanged(boolean hasCapture) { } @Override protected void onPause() { super.onPause(); lastFirstVisiblePosition = ((GridLayoutManager)mMovieResults.getLayoutManager()).findFirstCompletelyVisibleItemPosition(); } public class MyAdapter extends RecyclerView.Adapter { public class ViewHolder extends RecyclerView.ViewHolder { protected ImageView mResultImage; public ViewHolder(View itemView) { super(itemView); mResultImage = itemView.findViewById(R.id.movie_poster_image); } } public MyAdapter(List mDataset) { mMovieResultsList = mDataset; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_poster_image, parent, false); return new ViewHolder(v); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, final int position) { final String urlForPhoto = "http://image.tmdb.org/t/p/w185" + mMovieResultsList.get(position).getPoster_path(); Picasso.get() .load(urlForPhoto) .into(holder.mResultImage); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent i = new Intent(getApplicationContext(), IndividualMovieActivity.class); i.putExtra("Movie", mMovieResultsList.get(position)); startActivity(i); } }); } @Override public int getItemCount() { return mMovieResultsList.size(); } } public interface ApiInterface { @GET("?language=en-US") Call getImages(@Query("api_key") String api_key); } private boolean isOnline() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netInfo = cm.getActiveNetworkInfo(); return netInfo != null && netInfo.isConnectedOrConnecting(); }
ianhanniball.. 5
RecyclerView仅保存其滚动位置,直到您调用为止setAdapter
。在setAdapter
没有数据的情况下通过调用,滚动位置将被丢弃(如果没有位置4,则无法滚动到位置4)。
您应该等待直到有数据可调用setAdapter
。
RecyclerView仅保存其滚动位置,直到您调用为止setAdapter
。在setAdapter
没有数据的情况下通过调用,滚动位置将被丢弃(如果没有位置4,则无法滚动到位置4)。
您应该等待直到有数据可调用setAdapter
。