Использование залпа, чтобы сделать 2 отдельных удаленных запроса одним методом - PullRequest
0 голосов
/ 27 мая 2018

Пожалуйста, что я делаю не так?Я использую залп для получения данных из API Moviedb.Первый вызов метода должен извлекать популярные фильмы и сохранять их в ArrayListA (PopularMoviesList), а второй вызов должен извлекать фильмы с самым высоким рейтингом и сохранять в другом ArrayListB (topRatedMoviesList).Но когда я вызываю метод и передаю соответствующие URL-адреса, ArrayListA содержит данные как для популярных, так и для фильмов с самым высоким рейтингом, а ArrayListB пуст.

Это класс с методом

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class MovieDataSource {
private final static String MOVIE_ID="id";
private final static String MOVIE_RATING = "vote_average";
private final static String MOVIE_TITLE = "original_title";
private final static String MOVIE_POSTERPATH = "poster_path";
private final static String MOVIE_DESCRIPTION = "overview";
private final static String MOVIE_RELEASEDATE = "release_date";
private final static String API_KEY = "";// paste api key inside the double quote

private RequestQueue mRequestQueue = VolleySingleton.getmInstance().getmRequestQueue();


public ArrayList<Movie> movieArrayList(String URL){

    final ArrayList<Movie> listOfMovies = new ArrayList<>();

    String url= URL + API_KEY;

    JsonObjectRequest jsonObjectRequest= new JsonObjectRequest
            (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {


                @Override
                public void onResponse(JSONObject response) {
                    int movieId;
                    double movieRating;
                    String movieTitle, imagePath, movieDescription,movieReleaseDate;

                    Log.i("successful", response.toString());
                    try {
                        JSONArray results = response.getJSONArray("results"); // get json array from the object
                        JSONObject object; // to get objects from result array

                        Movie movie;

                        for(int i=0; i<results.length(); i++) {
                            object = results.getJSONObject(i);// get objects in the array based on their position/index in the array

                            //get values from the objects that will be used to populate instantiated movies
                            movieId = object.getInt(MOVIE_ID);
                            movieRating = object.getDouble(MOVIE_RATING);
                            movieTitle = object.optString(MOVIE_TITLE);
                            imagePath = object.optString(MOVIE_POSTERPATH);
                            movieDescription = object.optString(MOVIE_DESCRIPTION);
                            movieReleaseDate = object.optString(MOVIE_RELEASEDATE);
                            //// for every element in the array( index i), create a new movie
                            movie = new Movie(movieId,movieRating,movieTitle,imagePath,movieDescription, movieReleaseDate);
                            // add each movie created to the arrayList
                            listOfMovies.add(movie);
                        }

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    error.printStackTrace();
                    Log.i("error", "onErrorResponse: something went wrong ");

                }
            });

    mRequestQueue.add(jsonObjectRequest);

    return  listOfMovies;
}

Метод вызывается в MainActivity

MovieDataSource movieDataSource = new MovieDataSource();
final ArrayList<Movie>popularMoviesList = movieDataSource.movieArrayList(popularMoviesUrl)
final ArrayList<Movie> topRatedMoviesList = movieDataSource1.movieArrayList(topRatedMovieUrl);

. Проблема в том, что PopularMovieList содержит собственные ожидаемые данные и данные, предназначенные для topRatedMoviesList.Ничего не возвращается в topRatedMoviesList.Что может быть ответственным за это поведение?

Ответы [ 2 ]

0 голосов
/ 27 мая 2018

Вы должны использовать обратные вызовы (интерфейсы) вместо использования возвращаемого значения.

  • Возврат значения работает с синхронной задачей, например, вычисление суммы двух чисел, когда вам не нужно помещать код вычисления в отдельный поток.
  • Возврат значения не работает сАсинхронная задача, такая как вызов rest api или выполнение длительной задачи.Потому что, как его имя Async говорит, что он будет параллельно выполнять задачу.

Что будет делать ваш код (Совершенно неверно):

  • Будет создан список

  • Будет вызывать API в отдельной задаче ( См. AsyncTask ), поэтому ваш код не будет ждать, пока его ответ придет.

  • Он вернетсявы пустой список.

  • Теперь, когда приходит ваш ответ, он не имеет к этому никакого отношения.

Решение:

Если бы вы знали об интерфейсах, вы бы использовали это.Интерфейсы используются для вызова какого-либо метода, когда ваша задача выполнена.

Правильный способ реализации API в вашем коде будет следующим:

    public static final int REQUEST_CODE_POPULAR = 1;
    public static final int REQUEST_CODE_TOP_RATED = 2;

    ArrayList<Movie> popularMoviesList = new ArrayList<>();
    ArrayList<Movie> topRatedMoviesList = new ArrayList<>();

    private void setData() {
        String popularMoviesUrl = "yourUrl";
        String topRatedMovieUrl = "yourUrl";
        MovieDataSource object = new MovieDataSource(); // use only one object
        OnResponseListener<ArrayList<Movie>> listener = new OnResponseListener<ArrayList<Movie>>() {
            @Override
            public void onSuccess(int tag, ArrayList<Movie> object) {
                if (tag == REQUEST_CODE_POPULAR) {
                    popularMoviesList = object;
                    // TODO: 5/27/2018 use this list further
                } else if (tag == REQUEST_CODE_TOP_RATED) {
                    topRatedMoviesList = object;
                    // TODO: 5/27/2018 use this list further
                }
            }

            @Override
            public void onError(Exception e) {
//            todo handle error
            }
        };
        object.movieArrayList(popularMoviesUrl, REQUEST_CODE_POPULAR, listener);
        object.movieArrayList(topRatedMovieUrl, REQUEST_CODE_TOP_RATED, listener);
    }

И ваш MovieDataSource класс.

import android.graphics.Movie;
import android.util.Log;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

public class MovieDataSource {
    private final static String MOVIE_ID = "id";
    private final static String MOVIE_RATING = "vote_average";
    private final static String MOVIE_TITLE = "original_title";
    private final static String MOVIE_POSTERPATH = "poster_path";
    private final static String MOVIE_DESCRIPTION = "overview";
    private final static String MOVIE_RELEASEDATE = "release_date";
    private final static String API_KEY = "";// paste api key inside the double quote
    private RequestQueue mRequestQueue = VolleySingleton.getmInstance().getmRequestQueue();

    public void movieArrayList(String URL, final int tag, final OnResponseListener<ArrayList<Movie>> listener) {
        final ArrayList<Movie> listOfMovies = new ArrayList<>();
        String url = URL + API_KEY;
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
                (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        int movieId;
                        double movieRating;
                        String movieTitle, imagePath, movieDescription, movieReleaseDate;
                        try {
                            JSONArray results = response.getJSONArray("results"); // get json array from the object
                            JSONObject object; // to get objects from result array
                            Movie movie;
                            for (int i = 0; i < results.length(); i++) {
                                object = results.getJSONObject(i);// get objects in the array based on their position/index in the array
                                //get values from the objects that will be used to populate instantiated movies
                                movieId = object.getInt(MOVIE_ID);
                                movieRating = object.getDouble(MOVIE_RATING);
                                movieTitle = object.optString(MOVIE_TITLE);
                                imagePath = object.optString(MOVIE_POSTERPATH);
                                movieDescription = object.optString(MOVIE_DESCRIPTION);
                                movieReleaseDate = object.optString(MOVIE_RELEASEDATE);
                                //// for every element in the array( index i), create a new movie
                                movie = new Movie(movieId, movieRating, movieTitle, imagePath, movieDescription, movieReleaseDate);
                                // add each movie created to the arrayList
                                listOfMovies.add(movie);
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        listener.onSuccess(tag, listOfMovies);
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        listener.onError(error);
                        error.printStackTrace();
                        Log.i("error", "onErrorResponse: something went wrong ");
                    }
                });

        mRequestQueue.add(jsonObjectRequest);
      // removed return type, as it was redundant. 
    }


    interface OnResponseListener<T extends List> {
        void onSuccess(int tag, T object);
        void onError(Exception e);
    }
}
0 голосов
/ 27 мая 2018

Это потому, что ваш запрос выполняется асинхронно.Итак, вы запускаете 2 запроса с одним и тем же источником данных фильма.Когда оба запроса завершаются, вы заполняете один и тот же movieDataSource.listOfMovies, который затем возвращается.Попробуйте создать отдельный MovieDataSource для каждого запроса в MainActivity.

MovieDataSource movieDataSource1 = new MovieDataSource();
final ArrayList<Movie>popularMoviesList = movieDataSource1.movieArrayList(popularMoviesUrl)
MovieDataSource movieDataSource2 = new MovieDataSource();
final ArrayList<Movie> topRatedMoviesList = movieDataSource2.movieArrayList(topRatedMovieUrl);

Но, если честно, этот код выглядит неправильно для меня.Вы немедленно возвращаете пустой массив и затем заполняете его, когда запрос завершается, но как ваша MainActivity должна знать, готов ли он?Я бы передавал обратный вызов завершения из MainActivity, который мог бы быть вызван с полученным массивом, в качестве аргумента после завершения запроса.Спросите меня, нужна ли вам дополнительная помощь.

...