当我回到 MainActivity 时,AsyncTaskLoader 不断重新加载数据
AsyncTaskLoader keeps reloading data when I come back to the MainActivity
我对 Android 开发还很陌生,我真的需要你的帮助。我的问题在下面的 MainActivity
中。该应用程序主要在 activity 中显示电影列表,在另一个 activity 中显示电影详细信息。问题在于,每当用户从 MovieActivity
返回到 MainActivity
时,加载程序会再次开始加载数据,尽管电影已经存在。然后它无法停止加载数据。这真的很烦人。我想摆脱这个。因此,当用户返回到 MainActivity 时,加载程序将知道已经加载了数据并且不会加载任何内容 again.If 它有帮助,这是我的完整 GitHub repohttps://github.com/mateuszwojnarowicz/PopularMovies
我被困了大约 3 周,尝试了数百种可能的解决方案。似乎没有任何效果。我真的很绝望。
非常感谢您的帮助,
马修
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<String> {
private MovieAdapter mAdapter;
private ArrayList<Movie> mMoviesCollection;
private SharedPreferences sharedPreferences;
private Resources resources;
private LoaderManager loaderManager;
private Loader<String> loader;
private RecyclerView.LayoutManager layoutManager;
private String sortBy;
@BindView(R.id.pb)
ProgressBar progressBar;
@BindView(R.id.er)
TextView errorTextView;
@BindView(R.id.rv)
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mMoviesCollection = new ArrayList<Movie>();
sharedPreferences = getSharedPreferences(Constants.SHARED_PREFS, Activity.MODE_PRIVATE);
resources = getResources();
sortBy = sharedPreferences.getString(Constants.KEY_SORT, null);
setSharedPref();
layoutManager = new GridLayoutManager(this, calculateNoOfColumns(this));
loaderManager = getLoaderManager();
loader = loaderManager.getLoader(Constants.LOADER_MOVIES_ID);
initialize();
makeOperationLoadMovies(sortBy);
}
public static int calculateNoOfColumns(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
int noOfColumns = (int) (dpWidth / 150);
return noOfColumns;
}
//Set first-launch pref and set title according to pref
private void setSharedPref(){
if(!sharedPreferences.contains(Constants.KEY_SORT)) {
saveData(Constants.VALUE_POP);
setTitle(resources.getString(R.string.title_pop));
} else {
if (Objects.equals(sharedPreferences.getString(Constants.KEY_SORT, null), Constants.VALUE_POP)) {
setTitle(resources.getString(R.string.title_pop));
}
if (Objects.equals(sharedPreferences.getString(Constants.KEY_SORT, null), Constants.VALUE_TOP)) {
setTitle(resources.getString(R.string.title_top));
}
}
}
//Set up the RecyclerView
private void initialize(){
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
mMoviesCollection = new ArrayList<>();
mAdapter = new MovieAdapter(mMoviesCollection, this, this);
recyclerView.setAdapter(mAdapter);
}
private void makeOperationLoadMovies(String SORT_BY){
Bundle bundle = new Bundle();
bundle.putString(Constants.LOADER_MOVIES_EXTRA, SORT_BY);
if(recyclerView.isDirty()){
}
else if(loader==null){
loaderManager.initLoader(Constants.LOADER_MOVIES_ID, bundle, this);
}else{
loaderManager.restartLoader(Constants.LOADER_MOVIES_ID, bundle, this);
}
}
//Update shared pref
private void saveData(String SORT_VALUE){
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(Constants.KEY_SORT, SORT_VALUE);
editor.apply();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id){
case R.id.menu_fav:
startActivity(new Intent(MainActivity.this, FavoritesActivity.class));
break;
case R.id.menu_pop:
saveData(Constants.VALUE_POP);
Toast.makeText(this, resources.getString(R.string.message_popularity),Toast.LENGTH_LONG).show();
break;
case R.id.menu_top:
saveData(Constants.VALUE_TOP);
Toast.makeText(this, resources.getString(R.string.message_rating),Toast.LENGTH_LONG).show();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onPause() {
super.onPause();
Parcelable recyclerViewState;
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();//save
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
}
@Override
protected void onPostResume() {
super.onPostResume();
Parcelable recyclerViewState;
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();//save
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
}
@SuppressLint("StaticFieldLeak")
@Override
public Loader<String> onCreateLoader(int id, final Bundle args) {
return new AsyncTaskLoader<String>(this) {
@Override
protected void onStartLoading() {
super.onStartLoading();
forceLoad();
progressBar.setVisibility(View.VISIBLE);
errorTextView.setVisibility(View.INVISIBLE);
}
@Override
public void deliverResult(String data) {
super.deliverResult(data);
}
@Override
public String loadInBackground() {
String jsonString = "";
URL url = NetworkUtils.buildUrl(args.getString(Constants.LOADER_MOVIES_EXTRA));
try {
jsonString += NetworkUtils.getResponseFromHttpUrl(url);
} catch (IOException e) {
e.printStackTrace();
}
if(jsonString.isEmpty()){
} else {
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray(Constants.JSON_KEY_MOVIE_RESULTS);
for (int i = 0; i < jsonArray.length(); i++) {
//Get 1 movie from JSON
String mTitle;
int mId;
String mPosterUrl;
String mPlot;
double mUserRating;
String mReleaseDate;
JSONObject Jmovie = (JSONObject) jsonArray.get(i);
mTitle = Jmovie.getString(Constants.JSON_KEY_MOVIE_TITLE);
mId = Jmovie.getInt(Constants.JSON_KEY_MOVIE_ID);
mPosterUrl = NetworkUtils.getPosterString(Jmovie.getString(Constants.JSON_KEY_MOVIE_POSTER_PATH));
mPlot = Jmovie.getString(Constants.JSON_KEY_MOVIE_OVERVIEW);
mUserRating = Jmovie.getDouble(Constants.JSON_KEY_MOVIE_VOTE_AVERAGE);
mReleaseDate = Jmovie.getString(Constants.JSON_KEY_MOVIE_RELEASE_DATE);
//Get videos
ArrayList<Video> mVideos = new ArrayList<Video>();
URL videosURL = NetworkUtils.buildUrlVideos(String.valueOf(mId));
String videosJSON = NetworkUtils.getResponseFromHttpUrl(videosURL);
JSONObject jsonObjectVideos = new JSONObject(videosJSON);
JSONArray jsonArrayVideos = jsonObjectVideos.getJSONArray(Constants.JSON_KEY_VIDEO_RESULTS);
if(jsonArrayVideos.length()==0){
mVideos = null;
} else {
for(int v = 0; v < jsonArrayVideos.length(); v++){
JSONObject Jvideo = (JSONObject) jsonArrayVideos.get(v);
String mVideoName;
String mVideoUrlString;
mVideoName = Jvideo.getString(Constants.JSON_KEY_VIDEO_NAME);
mVideoUrlString = "https://www.youtube.com/watch?v="+Jvideo.getString(Constants.JSON_KEY_VIDEO_KEY);
Video video = new Video(mVideoName, mVideoUrlString);
mVideos.add(video);
}
}
//GetReviews
ArrayList<Review> mReviews = new ArrayList<Review>();
URL reviewsURL = NetworkUtils.buildUrlReviews(String.valueOf(mId));
String reviewsJSON = NetworkUtils.getResponseFromHttpUrl(reviewsURL);
JSONObject jsonObjectReviews = new JSONObject(reviewsJSON);
JSONArray jsonArrayReviews = jsonObjectReviews.getJSONArray(Constants.JSON_KEY_REVIEW_RESULTS);
if(jsonArrayReviews.length()!=0) {
for(int r = 0; r < jsonArrayReviews.length(); r++){
JSONObject Jreview = (JSONObject) jsonArrayReviews.get(r);
String mReviewName;
String mReviewText;
mReviewName = Jreview.getString(Constants.JSON_KEY_REVIEW_AUTHOR);
mReviewText = Jreview.getString(Constants.JSON_KEY_REVIEW_CONTENT);
Review review = new Review(mReviewName, mReviewText);
mReviews.add(review);
}
}
Movie movie = new Movie(mTitle, mId, mPosterUrl, mPlot, mUserRating, mReleaseDate, mVideos, mReviews);
mMoviesCollection.add(movie);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
}
return null;
}
};
}
@Override
public void onLoadFinished(Loader<String> loader, String data) {
progressBar.setVisibility(View.GONE);
mAdapter.notifyDataSetChanged();
}
@Override
public void onLoaderReset(Loader<String> loader) {
}
}
因为您是Android的新手,所以有很多错误。所以,很多人可能不想插话。无论如何,我也是新人,而且现在和你一样class,所以我会试一试。
首先,您的加载器没有return输入正确的数据类型。你的装载机应该是 Loader<List<Movie>>
并且它应该是 return 和 new AsyncTaskLoader<List<Movie>>
。您想要这样做的原因是要利用 AsyncTaskLoader 必须提供的一切。我会进一步解释。
其次,我们将通过将初始引用从 Activity 移动到加载程序来缓存加载程序中的数据。
所以移动 private ArrayList<Movie> mMoviesCollection;
作为你的 AsyncTaskLoader 的一个实例变量。从 onCreate 和 initialize 方法中删除行 mMoviesCollection = new ArrayList<Movie>();
。
在你的AsyncTaskLoader中,你需要在forceLoad和实现deliverResult之前检查你的数据是否已经存在于你的onStartLoading中。
因此,您的 onStartLoading() 应该如下所示:
@Override
protected void onStartLoading() {
super.onStartLoading();
if(mMoviesCollection.isEmpty()){
forceLoad();
progressBar.setVisibility(View.VISIBLE);
errorTextView.setVisibility(View.INVISIBLE);
} else {
deliverResult(mMoviesCollection)
}
}
你的 deliverResult 应该是这样的:
@Override
public void deliverResult(List<Movie> data) {
mMoviesCollection = data;
super.deliverResult(data);
}
现在您需要实现一个 setData(List<Movie> movies)
方法来设置您的适配器的数据实例变量并在您的适配器中调用 notifyDataSetChanged()
。像这样:
public void setData(List<Movie> movies){
mMovies = movies;
notifyDataSetChanged();
}
从适配器的构造函数中删除 List<Movie>
。这样你就可以在没有任何数据的情况下构建适配器。如果数据为空,适配器的 getItemCount()
应该 return 0 并且 recyclerView 不会尝试构建视图。
完成后,您可以像这样调用 onLoadFinished:
@Override
public void onLoadFinished(Loader<List<Movie>> loader, List<Movie> data) {
progressBar.setVisibility(View.GONE);
mAdapter.setData(data);
}
编辑: 进行更正以说明 ArrayList 实例化为实例变量。你可以不在那里实例化 mMoviesCollection 然后稍后再做,或者只是用 mMoviesCollection.isEmpty() 检查它是否为空,因为我在 onStartLoading 上面改变了。:
编辑:
您需要弄清楚您的图书馆,您在某些地方使用 android.app 而在其他地方使用 android.support。
因此在您的导入中更改这些:
import android.app.LoaderManager;
import android.content.AsyncTaskLoader;
import android.content.Loader;
全部到:
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
现在 TMDB.org API 的请求限制为每 10 秒 40 个请求。
https://developers.themoviedb.org/3/getting-started/request-rate-limiting
因此,您的 Loader 甚至没有完成所有操作并抛出异常。我建议在将视频和评论调用到 MovieActivity 时,通过在其中创建另一个 AsyncTaskLoader 并在详细信息屏幕加载时调用每个 AsyncTaskLoader 来分手。
从技术上讲,您也可以在 AsyncTaskLoader 中添加 Thread.sleep(300) 或更少,但这会使它变得非常慢。换句话说,您必须将数据推送到超过 10 秒标记才能完全加载。
现在,有了这些以及我们所做的更改,一切都会在配置更改(例如屏幕旋转)后继续存在。
如果您希望数据继续存在,您将不得不以某种方式持久化数据。就像将 json 响应保存为 onSaveInstanceState 中的字符串或将 JSon 字符串保存到您创建的数据库中。
我对 Android 开发还很陌生,我真的需要你的帮助。我的问题在下面的 MainActivity
中。该应用程序主要在 activity 中显示电影列表,在另一个 activity 中显示电影详细信息。问题在于,每当用户从 MovieActivity
返回到 MainActivity
时,加载程序会再次开始加载数据,尽管电影已经存在。然后它无法停止加载数据。这真的很烦人。我想摆脱这个。因此,当用户返回到 MainActivity 时,加载程序将知道已经加载了数据并且不会加载任何内容 again.If 它有帮助,这是我的完整 GitHub repohttps://github.com/mateuszwojnarowicz/PopularMovies
我被困了大约 3 周,尝试了数百种可能的解决方案。似乎没有任何效果。我真的很绝望。
非常感谢您的帮助,
马修
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<String> {
private MovieAdapter mAdapter;
private ArrayList<Movie> mMoviesCollection;
private SharedPreferences sharedPreferences;
private Resources resources;
private LoaderManager loaderManager;
private Loader<String> loader;
private RecyclerView.LayoutManager layoutManager;
private String sortBy;
@BindView(R.id.pb)
ProgressBar progressBar;
@BindView(R.id.er)
TextView errorTextView;
@BindView(R.id.rv)
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mMoviesCollection = new ArrayList<Movie>();
sharedPreferences = getSharedPreferences(Constants.SHARED_PREFS, Activity.MODE_PRIVATE);
resources = getResources();
sortBy = sharedPreferences.getString(Constants.KEY_SORT, null);
setSharedPref();
layoutManager = new GridLayoutManager(this, calculateNoOfColumns(this));
loaderManager = getLoaderManager();
loader = loaderManager.getLoader(Constants.LOADER_MOVIES_ID);
initialize();
makeOperationLoadMovies(sortBy);
}
public static int calculateNoOfColumns(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
int noOfColumns = (int) (dpWidth / 150);
return noOfColumns;
}
//Set first-launch pref and set title according to pref
private void setSharedPref(){
if(!sharedPreferences.contains(Constants.KEY_SORT)) {
saveData(Constants.VALUE_POP);
setTitle(resources.getString(R.string.title_pop));
} else {
if (Objects.equals(sharedPreferences.getString(Constants.KEY_SORT, null), Constants.VALUE_POP)) {
setTitle(resources.getString(R.string.title_pop));
}
if (Objects.equals(sharedPreferences.getString(Constants.KEY_SORT, null), Constants.VALUE_TOP)) {
setTitle(resources.getString(R.string.title_top));
}
}
}
//Set up the RecyclerView
private void initialize(){
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
mMoviesCollection = new ArrayList<>();
mAdapter = new MovieAdapter(mMoviesCollection, this, this);
recyclerView.setAdapter(mAdapter);
}
private void makeOperationLoadMovies(String SORT_BY){
Bundle bundle = new Bundle();
bundle.putString(Constants.LOADER_MOVIES_EXTRA, SORT_BY);
if(recyclerView.isDirty()){
}
else if(loader==null){
loaderManager.initLoader(Constants.LOADER_MOVIES_ID, bundle, this);
}else{
loaderManager.restartLoader(Constants.LOADER_MOVIES_ID, bundle, this);
}
}
//Update shared pref
private void saveData(String SORT_VALUE){
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(Constants.KEY_SORT, SORT_VALUE);
editor.apply();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id){
case R.id.menu_fav:
startActivity(new Intent(MainActivity.this, FavoritesActivity.class));
break;
case R.id.menu_pop:
saveData(Constants.VALUE_POP);
Toast.makeText(this, resources.getString(R.string.message_popularity),Toast.LENGTH_LONG).show();
break;
case R.id.menu_top:
saveData(Constants.VALUE_TOP);
Toast.makeText(this, resources.getString(R.string.message_rating),Toast.LENGTH_LONG).show();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onPause() {
super.onPause();
Parcelable recyclerViewState;
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();//save
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
}
@Override
protected void onPostResume() {
super.onPostResume();
Parcelable recyclerViewState;
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();//save
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
}
@SuppressLint("StaticFieldLeak")
@Override
public Loader<String> onCreateLoader(int id, final Bundle args) {
return new AsyncTaskLoader<String>(this) {
@Override
protected void onStartLoading() {
super.onStartLoading();
forceLoad();
progressBar.setVisibility(View.VISIBLE);
errorTextView.setVisibility(View.INVISIBLE);
}
@Override
public void deliverResult(String data) {
super.deliverResult(data);
}
@Override
public String loadInBackground() {
String jsonString = "";
URL url = NetworkUtils.buildUrl(args.getString(Constants.LOADER_MOVIES_EXTRA));
try {
jsonString += NetworkUtils.getResponseFromHttpUrl(url);
} catch (IOException e) {
e.printStackTrace();
}
if(jsonString.isEmpty()){
} else {
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray(Constants.JSON_KEY_MOVIE_RESULTS);
for (int i = 0; i < jsonArray.length(); i++) {
//Get 1 movie from JSON
String mTitle;
int mId;
String mPosterUrl;
String mPlot;
double mUserRating;
String mReleaseDate;
JSONObject Jmovie = (JSONObject) jsonArray.get(i);
mTitle = Jmovie.getString(Constants.JSON_KEY_MOVIE_TITLE);
mId = Jmovie.getInt(Constants.JSON_KEY_MOVIE_ID);
mPosterUrl = NetworkUtils.getPosterString(Jmovie.getString(Constants.JSON_KEY_MOVIE_POSTER_PATH));
mPlot = Jmovie.getString(Constants.JSON_KEY_MOVIE_OVERVIEW);
mUserRating = Jmovie.getDouble(Constants.JSON_KEY_MOVIE_VOTE_AVERAGE);
mReleaseDate = Jmovie.getString(Constants.JSON_KEY_MOVIE_RELEASE_DATE);
//Get videos
ArrayList<Video> mVideos = new ArrayList<Video>();
URL videosURL = NetworkUtils.buildUrlVideos(String.valueOf(mId));
String videosJSON = NetworkUtils.getResponseFromHttpUrl(videosURL);
JSONObject jsonObjectVideos = new JSONObject(videosJSON);
JSONArray jsonArrayVideos = jsonObjectVideos.getJSONArray(Constants.JSON_KEY_VIDEO_RESULTS);
if(jsonArrayVideos.length()==0){
mVideos = null;
} else {
for(int v = 0; v < jsonArrayVideos.length(); v++){
JSONObject Jvideo = (JSONObject) jsonArrayVideos.get(v);
String mVideoName;
String mVideoUrlString;
mVideoName = Jvideo.getString(Constants.JSON_KEY_VIDEO_NAME);
mVideoUrlString = "https://www.youtube.com/watch?v="+Jvideo.getString(Constants.JSON_KEY_VIDEO_KEY);
Video video = new Video(mVideoName, mVideoUrlString);
mVideos.add(video);
}
}
//GetReviews
ArrayList<Review> mReviews = new ArrayList<Review>();
URL reviewsURL = NetworkUtils.buildUrlReviews(String.valueOf(mId));
String reviewsJSON = NetworkUtils.getResponseFromHttpUrl(reviewsURL);
JSONObject jsonObjectReviews = new JSONObject(reviewsJSON);
JSONArray jsonArrayReviews = jsonObjectReviews.getJSONArray(Constants.JSON_KEY_REVIEW_RESULTS);
if(jsonArrayReviews.length()!=0) {
for(int r = 0; r < jsonArrayReviews.length(); r++){
JSONObject Jreview = (JSONObject) jsonArrayReviews.get(r);
String mReviewName;
String mReviewText;
mReviewName = Jreview.getString(Constants.JSON_KEY_REVIEW_AUTHOR);
mReviewText = Jreview.getString(Constants.JSON_KEY_REVIEW_CONTENT);
Review review = new Review(mReviewName, mReviewText);
mReviews.add(review);
}
}
Movie movie = new Movie(mTitle, mId, mPosterUrl, mPlot, mUserRating, mReleaseDate, mVideos, mReviews);
mMoviesCollection.add(movie);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
}
return null;
}
};
}
@Override
public void onLoadFinished(Loader<String> loader, String data) {
progressBar.setVisibility(View.GONE);
mAdapter.notifyDataSetChanged();
}
@Override
public void onLoaderReset(Loader<String> loader) {
}
}
因为您是Android的新手,所以有很多错误。所以,很多人可能不想插话。无论如何,我也是新人,而且现在和你一样class,所以我会试一试。
首先,您的加载器没有return输入正确的数据类型。你的装载机应该是 Loader<List<Movie>>
并且它应该是 return 和 new AsyncTaskLoader<List<Movie>>
。您想要这样做的原因是要利用 AsyncTaskLoader 必须提供的一切。我会进一步解释。
其次,我们将通过将初始引用从 Activity 移动到加载程序来缓存加载程序中的数据。
所以移动 private ArrayList<Movie> mMoviesCollection;
作为你的 AsyncTaskLoader 的一个实例变量。从 onCreate 和 initialize 方法中删除行 mMoviesCollection = new ArrayList<Movie>();
。
在你的AsyncTaskLoader中,你需要在forceLoad和实现deliverResult之前检查你的数据是否已经存在于你的onStartLoading中。
因此,您的 onStartLoading() 应该如下所示:
@Override
protected void onStartLoading() {
super.onStartLoading();
if(mMoviesCollection.isEmpty()){
forceLoad();
progressBar.setVisibility(View.VISIBLE);
errorTextView.setVisibility(View.INVISIBLE);
} else {
deliverResult(mMoviesCollection)
}
}
你的 deliverResult 应该是这样的:
@Override
public void deliverResult(List<Movie> data) {
mMoviesCollection = data;
super.deliverResult(data);
}
现在您需要实现一个 setData(List<Movie> movies)
方法来设置您的适配器的数据实例变量并在您的适配器中调用 notifyDataSetChanged()
。像这样:
public void setData(List<Movie> movies){
mMovies = movies;
notifyDataSetChanged();
}
从适配器的构造函数中删除 List<Movie>
。这样你就可以在没有任何数据的情况下构建适配器。如果数据为空,适配器的 getItemCount()
应该 return 0 并且 recyclerView 不会尝试构建视图。
完成后,您可以像这样调用 onLoadFinished:
@Override
public void onLoadFinished(Loader<List<Movie>> loader, List<Movie> data) {
progressBar.setVisibility(View.GONE);
mAdapter.setData(data);
}
编辑: 进行更正以说明 ArrayList 实例化为实例变量。你可以不在那里实例化 mMoviesCollection 然后稍后再做,或者只是用 mMoviesCollection.isEmpty() 检查它是否为空,因为我在 onStartLoading 上面改变了。:
编辑: 您需要弄清楚您的图书馆,您在某些地方使用 android.app 而在其他地方使用 android.support。
因此在您的导入中更改这些:
import android.app.LoaderManager;
import android.content.AsyncTaskLoader;
import android.content.Loader;
全部到:
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
现在 TMDB.org API 的请求限制为每 10 秒 40 个请求。 https://developers.themoviedb.org/3/getting-started/request-rate-limiting
因此,您的 Loader 甚至没有完成所有操作并抛出异常。我建议在将视频和评论调用到 MovieActivity 时,通过在其中创建另一个 AsyncTaskLoader 并在详细信息屏幕加载时调用每个 AsyncTaskLoader 来分手。
从技术上讲,您也可以在 AsyncTaskLoader 中添加 Thread.sleep(300) 或更少,但这会使它变得非常慢。换句话说,您必须将数据推送到超过 10 秒标记才能完全加载。
现在,有了这些以及我们所做的更改,一切都会在配置更改(例如屏幕旋转)后继续存在。
如果您希望数据继续存在,您将不得不以某种方式持久化数据。就像将 json 响应保存为 onSaveInstanceState 中的字符串或将 JSon 字符串保存到您创建的数据库中。