Как отправить post-запрос в Android без использования AsyncTask

#java #android #okhttp

#java #Android #okhttp

Вопрос:

Я выполняю post-запрос на сервер, используя HttpURLConnection но я получил исключение, что это не может быть сделано в потоке пользовательского интерфейса.

Я искал информацию, но я нашел информацию только с помощью AsyncTask класса, но, согласно документации Android, этот класс устарел, и я должен использовать java.util.concurrent вместо этого.

Я нашел много информации (например, полный класс HttpClient или для использования внешних библиотек), но ничто из этого не делает простой вещи для отправки post-запроса на URL.

Можете ли вы указать мне правильное направление?

Это весь мой класс, который мне нужно вызывать асинхронно:

 import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;

public class ServerConnection {
    private String absoluteUrl;
    String parameters;

    public ServerConnection(String postUrl, HashMap<String, String> keyValuePairs)
    {
        absoluteUrl = postUrl;

        StringBuilder sbParams = new StringBuilder();
        int i = 0;
        for (String key : keyValuePairs.keySet()) {
            try {
                if (i != 0){
                    sbParams.append("amp;");
                }
                sbParams.append(key).append("=")
                        .append(URLEncoder.encode(keyValuePairs.get(key), "UTF-8"));

            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            i  ;
        }

        parameters = sbParams.toString();
    }

    public boolean Send()
    {
        HttpURLConnection conn = null;

        try {
            URL urlObj = new URL(absoluteUrl);
            conn = (HttpURLConnection) urlObj.openConnection();
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Accept-Charset", "UTF-8");

            conn.setReadTimeout(10000);
            conn.setConnectTimeout(15000);

            conn.connect();

            DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
            wr.writeBytes(parameters);
            wr.flush();
            wr.close();

            InputStream in = new BufferedInputStream(conn.getInputStream());
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            StringBuilder result = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                result.append(line);
            }

            return result.toString().equals("OK");
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return false;
        } catch (ProtocolException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }

    }

}
  

Кроме того, это проект lib, который я также вызову для приложения iOS, поэтому я ищу стандартный способ Java.

Спасибо, Джейми

Ответ №1:

Как указано в документации, AsyncTask теперь она устарела, и вам нужно использовать java.util.concurrent вместо этого, вот полезная библиотека под названием ObservableScheduler, позволяющая вам использовать java.util.concurrent :

 implementation 'com.jiang.android.observablescheduler:schedule:1.0.1'
  

Пример :

   public void send() {
        JObservable.create(new JObservable.OnSubscribe<StringBuilder>() {
            @Override
            public void call(SubscribeManager<StringBuilder> mSubscriber) {
                try {

                    HttpURLConnection conn = null;
                    URL urlObj = new URL(absoluteUrl);
                    conn = (HttpURLConnection) urlObj.openConnection();
                    conn.setDoOutput(true);
                    conn.setRequestMethod("POST");
                    conn.setRequestProperty("Accept-Charset", "UTF-8");
                    conn.setReadTimeout(10000);
                    conn.setConnectTimeout(15000);
                    conn.connect();
                    DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
                    wr.writeBytes(parameters);
                    wr.flush();
                    wr.close();
                    InputStream in = new BufferedInputStream(conn.getInputStream());
                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder result = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        result.append(line);
                    }
                    mSubscriber.notifyData(result);
                } catch (Exception e) {
                    mSubscriber.error(e);
                }
            }
        }).workedOn(Schedules.background())
                .subscribeOn(Schedules.mainThread())
                .subscribe(new Subscriber<StringBuilder>() {
                    @Override
                    public void notifyData(StringBuilder result) {
                        //DO YOUR STUFF HERE
                    }

                    @Override
                    public void error(Throwable t) {
                        Toast.makeText(context, "Ops ! "   t.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                });
    }
  

Комментарии:

1. Здравствуйте … в качестве обходного пути на данный момент я создал Thread объект и добавил свой код подключения внутри run метода. Это работает, но я попытаюсь выяснить, можно ли с помощью этого подхода отправить указание на успех или ошибку, чтобы основной пользовательский интерфейс мог показать сообщение пользователю. Ваше решение интересно, но оно работает только для Android. У меня есть этот код в библиотеке, который также будет вызываться из проекта iOS.

Ответ №2:

Я только что создал объект Thread и добавил свой код подключения внутри метода run.