AsyncTask不刷新UI

问题描述 投票:0回答:1

我有一个应用程序,可以从AsyncTask中的API检索电影海报。我需要显示top_ratedpopular电影。因此,我的选项菜单中有热门最高评分。打开应用程序后,它将通过AsyncTask加载(20部)热门电影。现在的问题是,在我的选项菜单中单击“流行”或“最高评分”海报,它会将新获取的(20)张海报添加到UI上的(20)张海报中(现在已制作40张电影),而不是清除这些海报。屏幕并替换为新获取的20张电影海报。

我尝试在适配器上调用notifyDataSetChanged()。另外,我尝试为每个单击的选项调用一个新的AsyncTask,但均无效。我尝试了this thread的选项,但无济于事。

这是我的代码:

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。我之所以没有包含在这里,是因为我希望这篇文章尽量简短。请让我知道您是否需要任何东西。预先感谢。

java android android-studio android-asynctask
1个回答
0
投票

是的,发生这种情况是因为您不停地使用相同的列表对象,必须先创建一个新列表,然后才能在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();
....
....
....

祝你好运。

© www.soinside.com 2019 - 2024. All rights reserved.