没有从OkHttp回调接收JSON响应正文

时间:2016-04-24 11:42:17

标签: java android android-recyclerview okhttp okhttp3

我正在尝试查询API以获取JSON响应并将响应存储在ArrayList中。

此ArrayList稍后将用于设置RecyclerView。

如果我从OkHttp登录 OnResponse()方法,我会收到回复。但是当我通过 OkhttpHandler 中的返回将我的片段中的响应作为字符串接收时,则字符串值将被接收为null

这是代码

OkHttpHelper.Java

package com.execube.genesis.utils;

import android.util.Log;
import android.widget.Toast;

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

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by Prateek Phoenix on 4/24/2016.
 */


public class OkHttpHandler {

    private String queryUrl;
    private String jsonData;

    private static final String TAG = "CustomTAG1";



   public OkHttpHandler(String Url) {
        this.queryUrl = Url;
    }

    public String fetchData() {

        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(queryUrl)
                .build();

        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.v(TAG, "Exception: ", e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.v(TAG, response.body().string());

                if (response.isSuccessful()) {

                    jsonData = response.body().string();

                }
            }
        });

        return jsonData; //Even this is null when I check via Debugger
    }
}

PopularMoviesFragment.java

package com.execube.genesis.views;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;

import com.execube.genesis.R;
import com.execube.genesis.model.Movie;
import com.execube.genesis.utils.API;
import com.execube.genesis.utils.OkHttpHandler;

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

import java.util.ArrayList;

/**
 * Created by Prateek Phoenix on 4/24/2016.
 */
public class PopularMoviesFragment extends Fragment {

    private static final String TAG = "CustomTAG";
    private ArrayList<Movie> mMovies;

    private String jsonResponse;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        mMovies=new ArrayList<>();

        String url= API.BASE_URL+API.API_KEY+API.SORT_POPULARITY;

        OkHttpHandler handler= new OkHttpHandler(url);
        jsonResponse=handler.fetchData();

        try {
           mMovies= parseItems(jsonResponse);
        } catch (JSONException e) {
            Log.v(TAG,"Exception caught: ",e);
        }

        super.onCreate(savedInstanceState);


    }

    private ArrayList<Movie> parseItems( String jsonResponse) throws JSONException{

        JSONObject jsonData= new JSONObject(jsonResponse);
        JSONArray moviesJSONArray= jsonData.getJSONArray("results");
        ArrayList<Movie> Movies= new ArrayList<>();
        for (int i = 0; i <moviesJSONArray.length() ; i++) {

            Movie movie= new Movie();
            JSONObject movieJson= moviesJSONArray.getJSONObject(i);

            movie.setId(movieJson.getInt("id"));
            Log.v(TAG,"TITLE IS "+movieJson.getString("title"));
            movie.setOriginalTitle(movieJson.getString("original_title"));
            movie.setOverview(movieJson.getString("overview"));
            movie.setPosterPath(movieJson.getString("poster_path"));
            movie.setVoteAverage((float) movieJson.getDouble("vote_average"));
            movie.setTitle(movieJson.getString("title"));

            Movies.add(movie);
        }

        return  Movies;
    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view= inflater.inflate(R.layout.fragment_popular_movies,container,false);
        return view;
    }



}
用于构建网址的

API.java

package com.execube.genesis.utils;

/**
 * Created by Prateek Phoenix on 4/24/2016.
 */
public class API {


    public static String BASE_URL = "http://api.themoviedb.org/3/discover/movie?";
    public static String MOVIE_BASE_URL = "http://api.themoviedb.org/3/movie/";
    public static String API_KEY = "api_key=a98debe57ccd9b42fe6b99b9014c80e3";
    public static String SORT_POPULARITY = "&sort_by=popularity.desc";
    public static String SORT_R_RATED = "&certification_country=US&certification=R&sort_by=vote_average.desc&vote_count.gte=250";
    public static String IMAGE_URL = "http://image.tmdb.org/t/p/";
    public static String IMAGE_SIZE_185 = "w500";
   }

这是我要查询的网址http://api.themoviedb.org/3/discover/movie?api_key=a98debe57ccd9b42fe6b99b9014c80e3&sort_by=popularity.desc

2 个答案:

答案 0 :(得分:0)

Call#enqueue是OkHttp的异步API。这意味着请求将在后台线程上处理,并且调用线程将继续使用OR运行而不运行回调。

要使用数据,您需要使用某种形式的Future(Guava的ListenableFuture或RxJava可能有效)来响应最终数据的可用性或使用<{1}}代替Call#execute()以同步方式进行调用。

答案 1 :(得分:0)

问题是,在网络操作完成并在其中放入内容之前,您正在访问变量jsonData。 哪种情况不太可能发生。

使用类似事件总线的东西(我喜欢绿色机器人),并在jsonData有东西时发布一个事件,紧跟在行jsonData = response.body().string();

之后

在您的UI片段中收听此事件,并在收到此事件后填充数据。

然后,继续显示进度对话框/ UI。

通过这种方式,您的代码将保持异步,您也可以完成此操作