#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.