问题描述
我正在尝试向Android中的服务器发出同步请求. (代码在普通的Java项目中可以完美地工作)
I'm trying to do a synchronous request to my server in Android. (Code works flawlessly in a plain Java project)
我知道不应该在主线程上完成同步请求,因此我在完成网络连接后启动了一个新线程.我也知道可以进行异步调用,但同步调用更适合我的用例.
I know that sync requests shouldn't be done on the main thread, so I start a new thread where the networking is done. I also know that it is possible to do Async-calls but a sync call fits my usecase better.
bool networkingIsDoneHere(){
dostuff();
int number = doNetworkCall();
if(number < 500){
return true;
}
return false
}
问题是我仍然收到"NetworkOnMainThreadException"错误.改造是否以某种方式在主线程上运行,而在侧线程上执行?
The problem is that I still get the "NetworkOnMainThreadException" error. Does retrofit somehow run on the main thread, while being executed on a side thread?
开始新线程:
Thread timerThread = new Thread() {
@Override
public void run() {
while (true) {
try {
networkingIsDoneHere();
sleep(getExecutionInterval());
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
@Override
public void startRule() {
timerThread.start();
}
改装代码
private Retrofit createRetrofitAdapter() throws Exception {
return retrofit = new Retrofit.Builder()
.baseUrl("https://maps.googleapis.com/maps/api/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
public interface ApiGoogleMapsService {
@GET("url...")
Call<MapApiCall> getDurationJson(@Query("origins") String origin, @Query("destinations") String destination);
}
错误:
Caused by: android.os.NetworkOnMainThreadException
be.kul.gj.annotationfw W/System.err: at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273)
be.kul.gj.annotationfw W/System.err: at com.android.org.conscrypt.OpenSSLSocketImpl.shutdownAndFreeSslNative(OpenSSLSocketImpl.java:1131)
be.kul.gj.annotationfw W/System.err: at com.android.org.conscrypt.OpenSSLSocketImpl.close(OpenSSLSocketImpl.java:1126)
be.kul.gj.annotationfw W/System.err: at okhttp3.internal.Util.closeQuietly(Util.java:105)
be.kul.gj.annotationfw W/System.err: at okhttp3.internal.http.StreamAllocation.deallocate(StreamAllocation.java:260)
be.kul.gj.annotationfw W/System.err: at okhttp3.internal.http.StreamAllocation.connectionFailed(StreamAllocation.java:289)
be.kul.gj.annotationfw W/System.err: at okhttp3.internal.http.HttpEngine.close(HttpEngine.java:429)
be.kul.gj.annotationfw W/System.err: at okhttp3.RealCall.getResponse(RealCall.java:270)
be.kul.gj.annotationfw W/System.err: at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:198)
be.kul.gj.annotationfw W/System.err: at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160)
be.kul.gj.annotationfw W/System.err: at okhttp3.RealCall.execute(RealCall.java:57)
be.kul.gj.annotationfw W/System.err: at retrofit2.OkHttpCall.execute(OkHttpCall.java:177)
be.kul.gj.annotationfw W/System.err: at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:87)
be.kul.gj.annotationfw W/System.err: at model.GoogleMapsAccess.getTravelDuration(GoogleMapsAccess.java:52)
be.kul.gj.annotationfw W/System.err: at rule.RoutePickupRule.condition(RoutePickupRule.java:40)
推荐答案
Retrofit无需自己启动新线程,而是可以在单独的线程上自动执行请求.您可以通过调用enqueue();
来做到这一点.
Instead of starting a new thread yourself, Retrofit can automatically do requests on a separate thread. You can do this by calling enqueue();
.
Call<MapApiCall> call = api.getDurationJson(foo);
call.enqueue(new Callback<MapApiCall>() {
@Override
public void onResponse(Call<MapApiCall> call, Response<MapApiCall> response) {
//Do something with response
}
@Override
public void onFailure(Call<MapApiCall> call, Throwable t) {
//Do something with failure
}
});
如果要同步请求,请在单独的线程中使用execute()
:
If you want synchronous requests use execute()
within your seperate thread:
Call<MapApiCall> call = api.getDurationJson();
MapApiCall apiCall = call.execute().body();
如果出于某种原因,您想在不使用线程的情况下禁用NetworkOnMainThreadException
,请使用:
If you, for some reason, want to disable the NetworkOnMainThreadException
without using threads use:
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
但是,实际上不建议这样做,如果您不知道StrictMode
的用途,请不要使用它.
However, this is really not recommended, if you don't know what StrictMode
does, do NOT use it.
这篇关于改造2错误:NetworkOnMainThreadException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!