从onResponse Retrofit返回变量

时间:2017-02-16 10:51:31

标签: android retrofit response

我对网络服务器进行API调用,然后在方法onResponse中获取ID。

现在我要保存此ID并在方法doLogin的返回中返回此id。如何在return语句中获取该变量ID?

这是我的代码:

public class LoginController {

    public static String doLogin(String loginMail, String loginPassword) {

        //Logging Retrofit
        final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("###URLTOAPICALL###")
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        APIService service = retrofit.create(APIService.class);
        Call<JsonElement> call = service.doLogin(loginMail, loginPassword);

        call.enqueue(new Callback<JsonElement>() {
            @Override
            public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {

                if (response != null) {
                    JSONObject obj = null;

                    try {
                        obj = new JSONObject(response.body().toString());
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                    JSONObject setup = null;
                    try {
                        setup = obj.getJSONObject("setup");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                    if(setup != null) {
                        try {
                            Setup stp = new Setup();
                            stp.setUserId(setup.getInt("id"));

                            //I WANT HERE TO SAVE MY ID

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }


                    }
                }
            }

            @Override
            public void onFailure(Call<JsonElement> call, Throwable t) {
                Log.v("ERROR", t+"");
            }


        });

        return "I WANT RETURN THAT ID HERE";
    }
}

4 个答案:

答案 0 :(得分:5)

由于改造是异步的,所以不要从方法返回而是使用接口回调。

public class LoginController {

    public interface LoginCallbacks{
        void onLogin(String id);
        void onLoginFailed(Throwable error);
    }

    public static void doLogin(String loginMail, String loginPassword, final LoginCallbacks loginCallbacks) {

        //Logging Retrofit
        final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("###URLTOAPICALL###")
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        APIService service = retrofit.create(APIService.class);
        Call<JsonElement> call = service.doLogin(loginMail, loginPassword);

        call.enqueue(new Callback<JsonElement>() {
            @Override
            public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {

                if (response != null) {
                    JSONObject obj = null;

                    try {
                        obj = new JSONObject(response.body().toString());
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                    JSONObject setup = null;
                    try {
                        setup = obj.getJSONObject("setup");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                    if(setup != null) {
                        try {
                            Setup stp = new Setup();
                            stp.setUserId(setup.getInt("id"));

                            //I WANT HERE TO SAVE MY ID
                            if (loginCallbacks != null)
                                loginCallbacks.onLogin(setup.getInt("id"));
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }


                    }
                }
            }

            @Override
            public void onFailure(Call<JsonElement> call, Throwable t) {
                Log.v("ERROR", t+"");
                if (loginCallbacks != null)
                    loginCallbacks.onLoginFailed(t);
            }


        });
    }
}

通话方式:

doLogin("email", "password", new LoginCallbacks() {
            @Override
            public void onLogin(String id) {

            }

            @Override
            public void onLoginFailed(Throwable error) {

            }
        });

答案 1 :(得分:1)

虽然call.execute()函数是同步的,但它会在Android 4.0或更高版本上触发应用程序崩溃,您将获得NetworkOnMainThreadException。您必须执行异步请求,将全局变量初始化为可运行的线程。在您的班级名称中添加Runnable implementation.Your getDataFunction()将如下所示:

public void getData(){
    Call<JsonElement> call = service.doLogin(loginMail, loginPassword);

    call.enqueue(new Callback<JsonElement>() {
        @Override
        public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {

            if (response.isSuccessful() && response != null) {
                jsonObject = response.body().toString();//initialize your global variable
            }
        }

        @Override
        public void onFailure(Call<JsonElement> call, Throwable t) {
            Log.v("ERROR", t+"");
        }
    });

}

@Override
pulic void run(){
    getDataFunction();
    //here you can use your initialized variable
}

现在在onCreate函数上创建运行线程并启动它。

Thread thread = new Thread(this);
thread.start();

这就是解决我类似问题的方法。

答案 2 :(得分:0)

由于您请求的呼叫是异步的,因此无法使用。如果要在同一个线程中运行它,则必须避免使用enqueue并使用execute()。请记住,您需要创建一个线程,因为您无法在同一个线程上使用网络操作。

您可以使用Observables解决它,或者在这种情况下使用execute(未测试)

    new Thread(new Runnable() {
        @Override
        public void run() {
            String var = doLogin("email", "paswsord");
        }
    }); 

您可以使用

在活动中调用它
runOnUiThread();

请注意,如果您想要更新UI,则需要使用

<p dir="rtl">Write this text right-to-left!</p>

答案 3 :(得分:0)

您可以在Retrofit调用的onResponse方法内使用setter方法。 举一个实例,我有一个全局变量来保存从Google Maps距离矩阵API获得的两点之间的距离:

String final_distance;

这是我的改造电话:

call.enqueue(new Callback<JsonObject>() {
        
        @Override
        public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
            // TODO Auto-generated method stub
            JsonObject object = response.body();
            String distance = object.get("rows").getAsJsonArray().get(0).getAsJsonObject().get("elements").getAsJsonArray().
                    get(0).getAsJsonObject().get("distance").getAsJsonObject().get("value").getAsString();
            //The setter method to change the global variable
            setDistance(distance);

        }
        
        @Override
        public void onFailure(Call<JsonObject> call, Throwable t) {
            // TODO Auto-generated method stub
            
        }
    });

这是setter方法的作用:

private static void setDistance(String distance) {
    final_distance = distance;
}

由于Retrofit onResponse方法是异步的,因此您始终需要先检查final_distance是否不为null