我正在使用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);
}
Here我找到了创建服务的绝佳工具:
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();
}
当我尝试运行此代码时,我收到此错误:
android.os.NetworkOnMainThreadException 在android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147) at java.net.InetAddress.lookupHostByName(InetAddress.java:418) at 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 $ ApplicationInterceptorChain.proceed(RealCall.java:198) 在okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160) 在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) 在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) at java.lang.reflect.Method.invoke(Native Method) 在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)
我认为Retrofit会自动完成后台线程中的工作。或者我误解了一些事情。这种情况有什么问题以及如何解决?
答案 0 :(得分:36)
我认为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()&amp; onFailure()签名并在onRespnose()中添加了示例。
答案 1 :(得分:2)
你在主线程上调用webservice,这就是为什么你得到这个错误' android.os.NetworkOnMainThreadException '。
您可以使用NightSkyDev回答的上述编码来获取您想要的数据。
答案 2 :(得分:2)
在改造中,有两种方法执行 - 入队 - 通过改造自动处理后台线程的工作。 执行 - 在UI线程上工作,需要手动放入后台线程或接受异步任务。