Retrofit - android.os.NetworkOnMainThreadException

28,141

Solution 1

I thought that Retrofit automatically does the job in the background thread.

It does if you use the asynchronous version - enqueue. You're using the synchronous version, which runs on the calling thread.

Call it this way instead:

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
    }
});

In onResponse(), use response.body() to get your response, such as:
MyItem myItem=response.body();

Edit: Fixed onResponse() & onFailure() signatures and added example to onRespnose().

Solution 2

In Retrofit Two Types of Method execution takes place- Enqueue - Works on background thread automatically handle by retrofit. Execute - Works on UI thread manually required to put in either background thread or take help of async task.

Solution 3

You are calling webservice on main thread, that's why u got this error 'android.os.NetworkOnMainThreadException'.

You can use the above coding answered by NightSkyDev to get the data what u want.

Share:
28,141

Related videos on Youtube

Joe Richard
Author by

Joe Richard

Updated on July 09, 2022

Comments

  • Joe Richard
    Joe Richard almost 2 years

    I am using Retrofit 2 to get json and parse it to POJO. My purpose is getting one value of that object.

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

    My REST client:

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

    Here I found great great tool to create service:

    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);
        }
    }
    

    Then I am creating new service using Service generator class:

    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();
            }
    

    When I am trying to run this code I am getting this error:

    android.os.NetworkOnMainThreadException at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147) 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 okhttp3.Dns$1.lookup(Dns.java:39) at okhttp3.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:173) at okhttp3.internal.http.RouteSelector.nextProxy(RouteSelector.java:139) at okhttp3.internal.http.RouteSelector.next(RouteSelector.java:81) at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:174) at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:127) at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:97) at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:289) at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:241) at okhttp3.RealCall.getResponse(RealCall.java:240) at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:198) at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160) at okhttp3.RealCall.execute(RealCall.java:57) at retrofit2.OkHttpCall.execute(OkHttpCall.java:177) at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:87) at uz.cp.ox.data.MyRepository.getMyItem(MyRepository.java:31) at uz.cp.ox.presenters.MyPresenter.do(MyPresenter.java:30) at uz.cp.ox.activities.MyActivity.onClick(MyActivity.java:52) at android.view.View.performClick(View.java:4756) at android.view.View$PerformClick.run(View.java:19749) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) 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:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

    I thought that Retrofit automatically does the job in the background thread. Or I misunderstood something. What is wrong in this situation and how to solve it?

    • Rahul
      Rahul about 8 years
      Please check the answer and let me know if you have any concern
  • Iqbal
    Iqbal about 8 years
    What if I want to call the service synchronously?
  • NightSkyDev
    NightSkyDev about 8 years
    See this code from the OP: Call<MyItem> call = api.getMyItem(param1, param2, param3); call.execute().body(); Use .execute() instead of .enqueue.
  • Gokhan Arik
    Gokhan Arik almost 8 years
    Ok but when we do that we get NetworkOnMainThreadException, can't we make sync. call without having exception?
  • NightSkyDev
    NightSkyDev almost 8 years
    Yes @GokhanArik, but to call it synchronously, you need to be on a background thread, such as in an AsyncTask, a job queue or your own background thread.
  • Muhammadakbar Rafikov
    Muhammadakbar Rafikov almost 6 years
    In Rxjava & Retrofit I forgot to write threads .subscribeOn(Schedulers.io()) .observeOn(AppSchedulers.mainThread()) So I get this error. Thanks for answer
  • Akshay Chouhan
    Akshay Chouhan almost 4 years
    For anyone who is confused with ServiceGenerator, it's an interface where you write your requests.