代码之家  ›  专栏  ›  技术社区  ›  user7609274

使用Volley以一种方法发出两个独立的远程请求

  •  0
  • user7609274  · 技术社区  · 8 年前

    拜托,我做错什么了?我正在使用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);
    

    问题是:PopulatorVieList包含其自己的预期数据和用于TopRatedMoviesList的数据。没有任何内容返回到TopRatedMoviesList。这种行为的原因是什么?

    2 回复  |  直到 8 年前
        1
  •  0
  •   Khemraj Sharma    8 年前

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

    • 返回值与同步任务一起工作,例如在不需要将计算代码放入单独的线程时计算两个数字的和。
    • 返回值不适用于异步任务,如调用RESTAPI或执行耗时较长的任务。因为它的名字 异步的 说它将并行执行任务。

    您的代码将做什么(完全错误):

    • 它将创建一个列表

    • 将在单独的任务中调用API( See 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);
        }
    }
    
        2
  •  0
  •   Zoe - Save the data dump 张群峰    8 年前

    这是因为您的请求是异步运行的。所以,使用相同的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的完成回调,当请求完成时,可以使用接收的数组作为参数调用它。问我你是否需要其他帮助。