Utils.java
/**
* Created by faiz on 15/08/17.
*/
package com.example.android.whereabouts;
import android.util.Log;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class Utils {
private String apiresponse;
private OkHttpClient okHttpClient;
public Utils(String url){
okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("exception",e.toString());
}
@Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
apiresponse = response.body().string();
Log.e("onResponse",apiresponse);
}
});
}
public String getData(){
if(apiresponse != null)
return apiresponse ;
else
return "error";
}
}
当我在我的主活动中实例化这个类并尝试记录getData方法的返回值时,它会记录"错误"而不是变量 apiresponse 的值。
很明显,从服务器获取响应需要一些时间,并且在服务器返回响应之前会执行 getData 调用。
那么如何确保在执行onResponse后调用getData。
答案 0 :(得分:1)
您可以在“活动”中实现回调,而不是在“实用工具”中进行回调,以便回调您的活动,并且可以在用户界面中更新而不会出现任何问题。
public Utils(String url, Callback callback){
okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
okHttpClient.newCall(request).enqueue(callback);
}
在你的行动中,你可以打电话,
public void getdata() {
new Utils("[url]", new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("exception",e.toString());
}
@Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
apiresponse = response.body().string();
Log.e("onResponse",apiresponse);
// here you can show in UI.
}
})
}
或者您可以创建单独的自定义界面,并且在从服务器获得响应后也可以这样做。
答案 1 :(得分:0)
您可以实现回调机制并从onResponse(Call call, okhttp3.Response response)
方法内部调用回调方法。
这是一个例子。您应该在Utils类中定义它 -
public interface Callback {
void getData(String data);
}
private Callback callback;
在实例化Utils类时,在构造函数中传递活动引用。
// In the activity
utilsInstance = new Utils(url, this);
// In your Utils class
public Utils(String url, Callback activityCallback) {
callback = activityCallback
}
在您的活动中,您需要实现此界面 -
public class RetrofitActivity implements Utils.Callback {
@Override
public void getData(String data) {
// do stuff
}
}
在您的OnResponse()
方法中,您会像这样调用此方法 -
@Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
apiresponse = response.body().string();
callback.getData(apiresponse);
Log.e("onResponse",apiresponse);
}
答案 2 :(得分:0)
步骤1:在Utils方法中传递调用活动,如下所示
public Utils(CallingActivity activity , String url) { Request request = new Request.Builder().url(url).build(); okHttpClient.newCall(request).enqueue(activity); }
第2步:在您的通话活动中实施OkHttpClient的回调。
步骤3:覆盖OkHttpClient的onFailure()和onResponse(),并在调用活动中调用Utils(this,url)。
答案 3 :(得分:0)
我找到了两个解决方法,我将在这里分享,并请求回答此问题的人分享他们对此的看法。(我很感谢在这个问题上分享的答案。谢谢大家) 注意:它更像是一个“干净的代码问题”,而不是“如何让这个问题得到解决”
解决方案1:
我们可以等到在getData()中调用onResponse方法,就像这样
while(true)
if(apiresponse!=null)
return(apiresponse);
要确保这不是一个不确定的while循环,我们将变量 apiresponse 设置为onResponse和OnFailure方法中的某个(肯定会执行一个)以打破循环。
这个似乎有用,但我很天真地使用无限循环并打破它。
解决方案2:
在该异步任务的doInBackground方法中编写AsyncTask和Executing Utils类。
(我认为第二种方法是有道理的,因为它属于android的标准做法,所以它使事情起作用并且也满足最佳实践。)
另一件事:一些明显的问题是,当你准备在活动中编写整个异步任务时,为什么直接在活动中编写Utils.java代码是一个问题。我对此的回应是,尽管在活动中编写了asynctask,但它更好,因为它使我免于手动处理Handler以在onResponse中创建另一个线程来更新UI,它也属于标准做法。所以我认为这种方法总体上更有意义。