Okhttp:获取在OnResponse内部分配的变量的值

时间:2019-03-10 05:50:41

标签: android okhttp

我在OnResponse内分配了一个变量,但似乎无法在OnResponse之外获取其值,如何获得它的值?这是下面的代码。

    public class LoginMethods {
        public String title, str;

        public String Login(String URL, String account, String password, String verifycode){
            FormBody formbody =  new FormBody.Builder()
                    .add("TextBox2",password)
                    .add("txtSecretCode",verifycode)
                    .add("txtUserName",account)
                    .build();
            Request request=new Request.Builder()
                    .url(url)
                    .post(formbody)
                    .build();
            OkHttpClient client2 = new OkHttpClient();

            client2.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    str = response.body().string();
                }
            });

            Document doc=Jsoup.parse(str);
            title = doc.select("title").first().text();
            return title;
        }
    }

以下是Logcat的一部分:

    java.lang.IllegalArgumentException: String input must not be null
        at org.jsoup.helper.Validate.notNull(Validate.java:26)
        at org.jsoup.parser.TreeBuilder.initialiseParse(TreeBuilder.java:26)
        at org.jsoup.parser.TreeBuilder.parse(TreeBuilder.java:42)
        at org.jsoup.parser.HtmlTreeBuilder.parse(HtmlTreeBuilder.java:52)
        at org.jsoup.parser.Parser.parse(Parser.java:89)
        at org.jsoup.Jsoup.parse(Jsoup.java:58)

1 个答案:

答案 0 :(得分:0)

发生这种情况是因为您正在异步运行这些调用。这意味着Jsoup.parse(str);很可能会在通话结束并为str分配一个值之前发生。

例如,您需要在onResponse内移动代码并为标题提供回调。这是一个示例:

interface OnTitleReceivedListener {
   void onTitleReceived(String title);
}

public class LoginMethods {
    public void Login(String URL, String account, String password, String verifycode, OnTitleReceivedListener listener){
        FormBody formbody =  new FormBody.Builder()
                .add("TextBox2",password)
                .add("txtSecretCode",verifycode)
                .add("txtUserName",account)
                .build();
        Request request=new Request.Builder()
                .url(url)
                .post(formbody)
                .build();
        OkHttpClient client2 = new OkHttpClient();

        client2.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                response.body().string();
                Document doc=Jsoup.parse(str);
                listener.onTitleReceived(doc.select("title").first().text());
            }
        });
    }

现在,呼叫Login的人都必须传递一个接口,该接口将在标题准备就绪时(即您实际上是从网络上获得的)接收标题。

这里的关键概念是,当涉及到网络请求/响应时,事物应该并且应该是异步的,而回调是做到这一点的一种方法。

其他方法(例如反应式流)也有可能将工作分流到另一个线程。

修改

然后可以使用lambda调用函数:

new LoginMethods.Login("url", "account", "pwd", "verify code", (title) -> System.out.println(title));

如果您没有lambda,则可以随时创建一个匿名类:

new LoginMethods.Login("url", "account", "pwd", "verify code", new OnTitleReceivedListener() {
  public void onTitleReceived(String title){
        System.out.println(title);
   }
 });

就像您对Retrofit回调所做的那样。