Модернизация — android.os.NetworkOnMainThreadException

Я использую Retrofit 2, чтобы получить json и разобрать его на POJO. Моя цель - получить одно значение этого объекта.

compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'

Мой REST-клиент:

public interface MyClient {

    @GET("/part1/part2")
    Call<MyItem> getMyItem(@Query("param1") String param1,
                                                 @Query("param2") String param2,
                                                 @Query("param3") String param3);

}

Здесь я нашел отличный инструмент для создания сервиса:

public class ServiceGenerator {

    public static final String API_BASE_URL = "http://my.api.com";

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

    private static Retrofit.Builder builder =
            new Retrofit.Builder()
                    .baseUrl(API_BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create());

    public static <S> S createService(Class<S> serviceClass) {
        Retrofit retrofit = builder.client(httpClient.build()).build();
        return retrofit.create(serviceClass);
    }
}

Затем я создаю новый сервис, используя класс генератора сервисов:

MyClient api = ServiceGenerator.createService(MyClient.class);
        Call<MyItem> call = api.getMyItem(param1, param2, param3);
        MyItem myItem= null;
        try {
            myItem= call.execute().body();
            Log.d("MyTag", myItem.getValue());
        } catch (IOException e) {
            e.printStackTrace();
        }

Когда я пытаюсь запустить этот код, я получаю эту ошибку:

Я думал, что Retrofit автоматически выполняет работу в фоновом потоке. Или я что-то неправильно понял. Что не так в этой ситуации и как ее решить?

Я думал, что Retrofit автоматически выполняет работу в фоновом потоке.


person Joe Richard    schedule 18.02.2016    source источник
comment
Что, если я хочу вызвать службу синхронно?   -  person Rahul    schedule 18.02.2016


Ответы (3)


Да, если вы используете асинхронную версию — enqueue. Вы используете синхронную версию, которая выполняется в вызывающем потоке.

Назовите это так:

В onResponse() используйте response.body() для получения ответа, например:
MyItem myItem=response.body();

MyClient api = ServiceGenerator.createService(MyClient.class);
Call<MyItem> call = api.getMyItem(param1, param2, param3);
call.enqueue(new Callback<MyItem>() {
    @Override
    public void onResponse(Call<MyItem> call, Response<MyItem> response) {
        MyItem myItem=response.body();
    }

    @Override
    public void onFailure(Call<MyItem> call, Throwable t) {
        //Handle failure
    }
});

Изменить: исправлены подписи onResponse() и onFailure() и добавлен пример в onRespnose().

Вы вызываете веб-службу в основном потоке, поэтому вы получили эту ошибку «android.os.NetworkOnMainThreadException».

person NightSkyDev    schedule 18.02.2016
comment
См. этот код из OP: _1_ Используйте _2_ вместо _3_. - person Iqbal; 01.04.2016
comment
Хорошо, но когда мы это сделаем, мы получим Call<MyItem> call = api.getMyItem(param1, param2, param3); call.execute().body();, не можем ли мы сделать синхронизацию. позвонить без исключения? - person NightSkyDev; 01.04.2016
comment
Да, @GokhanArik, но для синхронного вызова вам нужно быть в фоновом потоке, например, в AsyncTask, очереди заданий или собственном фоновом потоке. - person Gokhan Arik; 27.07.2016
comment
Для тех, кто путается с ServiceGenerator, это интерфейс, в котором вы пишете свои запросы. - person NightSkyDev; 29.07.2016
comment
В Rxjava & Retrofit я забыл написать потоки .subscribeOn(Schedulers.io()) .observeOn(AppSchedulers.mainThread()) Поэтому я получаю эту ошибку. Спасибо за ответ - person Akshay Chouhan; 19.07.2020

Вы можете использовать приведенный выше код, на который отвечает NightSkyDev, чтобы получить данные, которые вы хотите.

При дооснащении выполняются два типа метода: Постановка в очередь. Работает в фоновом потоке, автоматически обрабатываемом при дооснащении. Выполнить. Работает в потоке пользовательского интерфейса вручную, необходимо включить либо фоновый поток, либо воспользоваться помощью асинхронной задачи.

person Sai Soe Harn    schedule 24.03.2017
comment
android.os.NetworkOnMainThreadException в android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147) в java.net.InetAddress.lookupHostByName(InetAddress.java:418) в java.net.InetAddress.getAllByNameImpl(InetAddress.java: 252) в java.net.InetAddress.getAllByName(InetAddress.java:215) в okhttp3.Dns$1.lookup(Dns.java:39) в okhttp3.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:173) в okhttp3 .internal.http.RouteSelector.nextProxy(RouteSelector.java:139) в okhttp3.internal.http.RouteSelector.next(RouteSelector.java:81) в okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:174) в okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:127) ) в okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:97) в okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:289) в okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java: 241) на okhttp3.RealCall.getResponse(RealCall.java:240) на okhttp3.RealCall$Applicati onInterceptorChain.proceed(RealCall.java:198) в okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160) в okhttp3.RealCall.execute(RealCall.java:57) в retrofit2.OkHttpCall.execute(OkHttpCall.java:177) в модернизация2. ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:87) в uz.cp.ox.data.MyRepository.getMyItem(MyRepository.java:31) в uz.cp.ox.presenters.MyPresenter.do(MyPresenter.java:30) в uz.cp.ox.activities.MyActivity.onClick(MyActivity.java:52) в android.view.View.performClick(View.java:4756) в android.view.View$PerformClick.run(View.java:19749) ) в android.os.Handler.handleCallback(Handler.java:739) в android.os.Handler.dispatchMessage(Handler.java:95) в android.os.Looper.loop(Looper.java:135) в android.app.ActivityThread.main(ActivityThread.java:5221) в java.lang.reflect.Method.invoke(собственный метод) в java.lang.reflect .Method.invoke(Method.java:372) в com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) в com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) ) - person Muhammadakbar Rafiqov; 30.06.2018

Пожалуйста, проверьте ответ и дайте мне знать, если у вас есть какие-либо опасения

person Rahul Jain    schedule 29.03.2017