web-dev-qa-db-ja.com

レトロフィット-Android.os.NetworkOnMainThreadException

Retrofit 2を使用してjsonを取得し、POJOに解析します。私の目的は、そのオブジェクトの1つの値を取得することです。

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

}

ここ サービスを作成するための素晴らしいツールが見つかりました:

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

次に、Service Generatorクラスを使用して新しいサービスを作成しています。

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

このコードを実行しようとすると、次のエラーが表示されます。

Android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork(StrictMode.Java:1147)at Android.os.NetworkOnMainThreadException 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) 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 uz.cp.ox.data.MyRepository.getMyItem(MyRepository.Java:31)のretrofit2.ExecutorCallAdapterFactory $ ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.Java:87)の.execute(OkHttpCall.Java:177)uz.cp.oxのpresents.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.ZygoteIn it $ MethodAndArgsCaller.run(ZygoteInit.Java:899)at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:694)

Retrofitはバックグラウンドスレッドで自動的にジョブを実行すると考えました。または、私は何かを誤解しました。この状況で何が問題で、どのように解決しますか?

18
Joe Richard

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

OnResponse()で、response.body()を使用して、次のような応答を取得します。
MyItem myItem=response.body();

編集:onResponse()およびonFailure()シグネチャを修正し、onRespnose()に例を追加しました。

38
NightSkyDev

メインスレッドでwebserviceを呼び出しているため、このエラー「Android.os.NetworkOnMainThreadException」が発生しました。

NightSkyDev で回答された上記のコーディングを使用して、必要なデータを取得できます。

3
Sai Soe Harn

レトロフィットでは、2種類のメソッドの実行が行われます。Enqueue-レトロフィットによって自動的に処理されるバックグラウンドスレッドで動作します。 実行-バックグラウンドスレッドを入力するか、非同期タスクを支援するために手動で必要とされるUIスレッドで動作します。

2
Rahul Jain