改造 - android.os.NetworkOnMainThreadException

Joe*_*ard 19 java android retrofit retrofit2

我正在使用Retrofit 2来获取json并将其解析为POJO.我的目的是获得该对象的一个​​值.

compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
Run Code Online (Sandbox Code Playgroud)

我的REST客户端:

public interface MyClient {

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

}
Run Code Online (Sandbox Code Playgroud)

在这里,我找到了创建服务的绝佳工具:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我使用服务生成器类创建新服务:

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();
        }
Run Code Online (Sandbox Code Playgroud)

当我尝试运行此代码时,我收到此错误:

android.os.NetworkOnMainThreadException位于java.net.InetAddress.getAllByNameImpl的java.net.InetAddress.lookupHostByName(InetAddress.java:418)的android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147)上(InetAddress.java: 252)在okhttp3.Dns的java.net.InetAddress.getAllByName(InetAddress.java:215),在okhttp3的okhttp3.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:173)$ 1.lookup(Dns.java:39) .internal.http.RouteSelector.nextProxy(RouteSelector.java:139)位于okhttp3.internal.http.RouteSelector.next(RouteSelector.java:81)的okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:174)at 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)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)在uof.cp.ox上的uc.cp.ox.data.MyRepository.getMyItem(MyRepository.java:31)上的retrofit2.ExecutorCallAdapterFactory $ ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:87). 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 .在android.os.Handler.dispatchMessage(Handler.java:95)的android.os.Looper上的android.os.Handler.handleCallback(Handler.java:739)上查看$ PerformClick.run(View.java:19749).在java.lang.reflect.Method.invoke的java.lang.reflect.Method.invoke(Native Method)的android.app.ActivityThread.main(ActivityThread.java:5221)上循环(Looper.java:135)(方法. java:372)在com.android.internal.os.ZygoteIn 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)的$ MethodAndArgsCaller.run(ZygoteInit.java:899)

我认为Retrofit会自动在后台线程中完成工作.或者我误解了一些事情.这种情况有什么问题以及如何解决?

Nig*_*Dev 39

我认为Retrofit会自动在后台线程中完成工作.

如果您使用异步版本,它会这样做enqueue.您正在使用在调用线程上运行的同步版本.

这样称呼它:

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
    }
});
Run Code Online (Sandbox Code Playgroud)

在onResponse()中,用于response.body()获取您的响应,例如:
MyItem myItem=response.body();

编辑:修复onResponse()和onFailure()签名并将示例添加到onRespnose().

  • 如果我想同步调用服务怎么办? (6认同)
  • 好的,但是当我们这样做时,我们得到`NetworkOnMainThreadException`,我们不能进行同步.没有例外的电话? (4认同)
  • 是@GokhanArik,但要同步调用它,您需要在后台线程上,例如在AsyncTask,作业队列或您自己的后台线程中. (3认同)