java - AsyncTask 不刷新 UI
问题描述
我有一个应用程序,我在其中从AsyncTask中的 API 检索电影海报。我需要显示top_rated和流行的电影。因此,我在我的选项菜单中获得了热门和最高评价。打开应用程序时,它会通过 AsyncTask 加载 (20) 部流行电影。现在的问题是在我的选项菜单中单击流行或评分最高的一个,它会将新获取的 (20) 海报添加到 UI 上的 (20) 海报中(现在变成 40 部电影),而不是清除屏幕并替换为新取来的 20 张电影海报。
我试过调用notifyDataSetChanged()
适配器。此外,我尝试为单击的每个选项调用一个新的 AsyncTask,但均无效。我已经尝试过这个线程的选项,但无济于事。
这是我的代码:
package com.quwaysim.popularmovies.ui;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.quwaysim.popularmovies.MovieAdapter;
import com.quwaysim.popularmovies.R;
import com.quwaysim.popularmovies.model.MovieDetails;
import com.quwaysim.popularmovies.utils.NetworkUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
MovieAdapter mAdapter;
ArrayList<MovieDetails> mMovieList = new ArrayList<>();
ProgressBar mProgressBar;
String api = "popular";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mProgressBar = findViewById(R.id.progressBar);
mRecyclerView = findViewById(R.id.movies_rv);
fetchMovies(api);
}
public void fetchMovies(String api) {
URL apiURL = NetworkUtils.buildUrl(api);
new FetchMovie().execute(apiURL);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.sort_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.popular:
Toast.makeText(this, "Popular", Toast.LENGTH_SHORT).show();
// Trying my options here
URL popular = NetworkUtils.buildUrl("popular");
new FetchMovie().execute(popular);
mAdapter.notifyDataSetChanged();
return true;
case R.id.top_rated:
Toast.makeText(this, "Top Rated", Toast.LENGTH_SHORT).show();
// Trying my options here
URL topRated = NetworkUtils.buildUrl("top_rated");
new FetchMovie().execute(topRated);
mAdapter.notifyDataSetChanged();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public class FetchMovie extends AsyncTask<URL, Void, String> {
private final String TAG = "FetchMovieAsyncTask";
private int mNoOfMovies;
@Override
protected void onPreExecute() {
mProgressBar.setVisibility(View.VISIBLE);
super.onPreExecute();
}
@Override
protected String doInBackground(URL... urls) {
URL url = urls[0];
String movieResults = null;
try {
movieResults = NetworkUtils.getResponseFromUrl(url);
} catch (IOException e) {
Log.d(TAG, "doInBackground: " + e);
}
return movieResults;
}
@Override
protected void onPostExecute(String s) {
if (s != null && !s.equals("")) {
mProgressBar.setVisibility(View.INVISIBLE);
try {
JSONObject parsedMoviesJSON = new JSONObject(s);
JSONArray moviesArray = parsedMoviesJSON.getJSONArray("results");
mNoOfMovies = moviesArray.length();
moviesArray.getString(1);
for (int i = 0; i < mNoOfMovies; i++) {
MovieDetails mMovDetails = new MovieDetails();
String details = moviesArray.get(i).toString();
JSONObject detailsParsed = new JSONObject(details);
mMovDetails.setMoviePoster("http://image.tmdb.org/t/p/w185/"
+ detailsParsed.getString("poster_path"));
mMovieList.add(mMovDetails);
Log.d(TAG, "onPostExecute: forLoop" + mMovDetails.getMoviePoster());
}
} catch (JSONException e) {
Log.d(TAG, "onPostExecute: error => " + e);
e.printStackTrace();
}
Log.d("TAG", "onPostExecute: movieList" + mMovieList);
mAdapter = new MovieAdapter(mMovieList);
mRecyclerView.setLayoutManager(new GridLayoutManager(MainActivity.this, 2));
mRecyclerView.setAdapter(mAdapter);
Log.d(TAG, "onPostExecute: it's a success " + mNoOfMovies);
}
}
}
}
NetworkUtils类仅用于打开连接和构建完整的 api URL 。我没有在此处包含它,因为我想使这篇文章尽可能简短。如果您需要任何东西,请告诉我。提前致谢。
解决方案
是的,这是因为您一直在使用相同的列表对象,您必须在 onPostExecute() 中使用它之前创建一个新列表添加:
mMovieList = new ArrayList<>();
在 for 循环的正上方,如下所示:
//create a new list for each query
mMovieList = new ArrayList<>();
for (int i = 0; i < mNoOfMovies; i++) {
MovieDetails mMovDetails = new MovieDetails();
String details = moviesArray.get(i).toString();
....
....
....
祝你好运。
推荐阅读
- powerapps - 如何根据电源应用中的特定列值过滤图库?
- php - 网站显示 http 错误 500,所有似乎在 conf 文件中都正确
- python - 基于其他图像的蒙版“填充”区域
- java - 如何通过地图
> 在 application.properties spring boot 应用程序中 - javascript - 尝试导入 amCharts 模块时出现语法错误
- sql - MS-SQL 脚本具有不同的处理时间。我在哪里可以找到罪魁祸首?
- cakephp - 查询生成器:在关联数据上具有多个 SUM 的子查询
- powershell - Azure DevOps Pipeline 脚本中的租户 ID 已审查
- types - 如何在 Rust 中指定值约束?
- c++ - 如果将传递的初始化列表映射为符号 (constexpr),则 MSVC 上的 constexpr std::max 失败