使用volley使用一种方法创建2个单独的远程请求

时间:2018-05-27 15:42:32

标签: java android android-volley

拜托,我做错了什么?我使用volley从Moviedb api获取数据。第一种方法调用应该是获取流行电影并将它们存储在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 :(得分:0)

这是因为您的请求以异步方式运行。因此,您使用相同的movieDataSource运行2个请求。当两个请求完成后,您将填充相同的movieDataSource.listOfMovies,然后返回。尝试为MainActivity中的每个请求创建单独的MovieDataSource。

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

但说实话,这段代码对我来说错了。您立即返回空数组,然后在请求完成时填充它,但是您的MainActivity如何知道它是否准备就绪?我将从MainActivity传递完成回调,当请求完成时,可以使用接收数组作为参数调用。问我是否需要其他帮助。

答案 1 :(得分:0)

您应该使用回调(接口)而不是使用返回值。

  • 返回值与同步任务一起使用,例如当您不需要将计算代码放在单独的线程中时计算两个数字的总和。
  • 返回值不适用于异步任务,如调用rest api或执行耗时的任务。因为它的名称 Async 表示它将并行执行任务。

您的代码将执行什么操作(完全错误):

  • 它会创建一个列表

  • 将在单独的任务(See AsyncTask)中调用api,因此您的代码不会等待让其响应。

  • 它会返回空白列表。

  • 现在,当您的回复出现时,它与此无关。

解决方案:

如果您了解接口,那么就可以使用它。接口用于在任务完成时调用某些方法。

在您的代码中实现api的正确方法如下

<GridLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:columnCount="4"
    android:rowCount="6"
    <!-- android:onClick="dropIn" -->
    android:layout_alignParentEnd="true"
    android:id="@+id/gridLayout">

您的 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