Охтпп: получить значение переменной, назначенной внутри OnResponse - PullRequest
0 голосов
/ 10 марта 2019

Я назначил переменную внутри 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 голосов
/ 10 марта 2019

Это происходит потому, что вы выполняете вызовы асинхронно. Это означает, что 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, он должен будет передать интерфейс, который получит заголовок, когда он будет готов, то есть, когда вы фактически получили его из сети.

Ключевой концепцией здесь является то, что вещи являются и должны быть асинхронными, когда речь идет о сетевых запросах / ответах, и обратные вызовы являются одним из способов сделать это.

Существуют и другие методы, такие как реактивные потоки, которые могут перенести работу в другой поток.

редактировать

Функция может быть вызвана с помощью лямбды:

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

Если у вас нет лямбд, тогда вы всегда можете создать анонимный класс:

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

Точно так же, как вы сделали для обратных вызовов Retrofit.

...