У меня есть приложение, в котором я получаю афиши фильмов из API в AsyncTask . Мне нужно отображать фильмы с самыми популярными и популярными . Таким образом, в моем меню параметров есть популярные и самые популярные . При открытии приложение загружает (20) популярных фильмов через AsyncTask. Теперь проблема заключается в том, чтобы щелкнуть один из популярных или самых популярных в моем меню параметров, он добавляет недавно выбранные (20) плакатов к (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 предназначен только для открытия соединения и создания полного URL-адреса API. Я не включил его сюда, потому что хочу, чтобы этот пост был как можно короче. Пожалуйста, дайте мне знать, если вам что-нибудь понадобится. Заранее спасибо.

0
Quwaysim 16 Апр 2020 в 10:51

1 ответ

Лучший ответ

Да, это происходит потому, что вы постоянно используете один и тот же объект списка, вы должны создать новый список, прежде чем использовать его в 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();
....
....
....

Удачи.

1
Hasan Bou Taam 16 Апр 2020 в 08:07