类中的方法返回null而不是通过异步调用

时间:2017-08-15 17:28:43

标签: java android

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。

4 个答案:

答案 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,它也属于标准做法。所以我认为这种方法总体上更有意义。