Я пытаюсь сделать запрос на ресурс, json
используяHttpURLConnection
Я тестирую следующий код в onCreate()
try {
URL url = new URL("http://localhost/testrealm/api/v1/status");
HttpURLConnection urlConnection = null;
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
Log.d(TAG, "get json: " + in.toString());
urlConnection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
Ошибка в запросе
java.lang.RuntimeException: невозможно запустить активность ComponentInfo... android.os.NetworkOnMainThreadException
Целое число ошибок журнала
06-10 14:32:21.113 E/AndroidRuntime: FATAL EXCEPTION: main
Process: realm.test.app.testrealm, PID: 11702
java.lang.RuntimeException: Unable to start activity ComponentInfo{realm.test.app.testrealm/realm.test.app.testrealm.MainActivity}: android.os.NetworkOnMainThreadException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2339)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2413)
at android.app.ActivityThread.access$800(ActivityThread.java:155)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5343)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1161)
at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at com.android.okhttp.HostResolver$1.getAllByName(HostResolver.java:29)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:232)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:124)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:272)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:382)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:332)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:199)
at realm.test.app.testrealm.MainActivity.onCreate(MainActivity.java:57)
at android.app.Activity.performCreate(Activity.java:6010)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2292)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2413)
at android.app.ActivityThread.access$800(ActivityThread.java:155)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5343)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
Документация по HttpURLConnection
Если вы используете StrictMode.ThreadPolicy.Builder , чтобы разрешить любую операцию, она работает, но вы отключаете политику, которая не должна разрешать определенное поведение в приложении, в этом случае операции в основном потоке, это в основном используется для разработки, для производства вы не должны использовать его .
Используйте runOnUiThread()
Другими вариантами являются Asynctask , а также Handler.post() .
Я нашел эту прекрасную статью для получения дополнительной информации: «Фоновые задачи Android (I): Thread and AsyncTask» (блог Сальвадора Гомеса).
Вы должны использовать AsynkTask:
Если вам нужно знать, когда вы получаете ответ и/или изменяете представления после вызова, используйте AsynkTask следующим образом:
Добавьте следующий код перед выполнением веб-запроса с помощью
HttpURLConnection
Как еще один вариант этой проблемы, который я также прошел через свои руки, заключается в том, чтобы реализовать свой код внутри a
runOnUiThread()
, который позволит получить доступ к переменным основного потока, поскольку именно в этом проблема.В этом вопросе я объясняю этот метод:
Использовать Activity.runOnUiThread() или Handler.post(Runnable) для обновления основного потока?
Как только у меня снова появится возможность, я попробую ваше решение и, таким образом, узнаю о других возможных решениях.
На эту тему всегда есть о чем поговорить. Отключение политик определенно не вариант.
Но имейте в виду, что это во многом зависит от того, как вы хотите что-то делать, по моему опыту я видел следующие сценарии:
Поэтому я не знаю, что у вас за дело, и важно, чтобы вы об этом подумали. Для первого случая
AsyncTask
это очень хорошо для вас. Вы выполняете вdoInBackground
нем свой тяжелый процесс, информируете пользователя о его продвижении в немpublishProgress
и в конце показываете результат на его экране через файлonPostExecute
. Обычно это не только для запросов к серверам, но и для сложных вычислений, поиска в базе данных и т. д. Пока вы намерены заставить пользователя ждать этого процесса (что-то, что может раздражать) и чтобы он мог взаимодействовать с приложением после его завершения.Для второго случая пригодится один
Thread
или одинRunnable
вместе с одним , вы выполняете процесс в методе , который не зависит от статуса его завершения и пользователь даже не подозревает об этом.Handler
run
Для третьего случая возьмем пример: у вас есть процесс, который собирает данные и преобразует их в полезную информацию, вы сохраняете эту информацию в своей локальной базе данных, но вы также должны отправлять ее на сервер по причинам избыточности данных; но вы также должны дождаться результата отправки на сервер, чтобы обновить индикатор на записи, который определяет, была ли отправка успешной или нет, чтобы, например, не отправлять ее снова. Для такого типа ситуаций удобно работать с планировщиками потоков, которые позволяют выполнять действие в тот момент, когда поток заканчивает свое выполнение. Очень простой пример — Google Guava и его классы ,
Futures
а также файлыListenableFuture
.Это немного дополнительной информации к тому, что вам ответили, что полезно знать, поэтому хорошо определите свои сценарии, чтобы вы могли выбрать лучший способ работы.