android - 改造 2 错误 : NetworkOnMainThreadException

标签 android multithreading retrofit retrofit2

我正尝试在 Android 中向我的服务器发出同步请求。 (代码在普通 Java 项目中完美运行)

我知道不应该在主线程上完成同步请求,所以我在网络完成的地方启动了一个新线程。我也知道可以进行异步调用,但同步调用更适合我的用例。

bool networkingIsDoneHere(){
  dostuff();
  int number = doNetworkCall();
  if(number < 500){
    return true;
  }
  return false
}

问题是我仍然收到“NetworkOnMainThreadException”错误。改造是否以某种方式在主线程上运行,而在副线程上执行?

开始新线程:

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(); 来完成此操作。

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():

Call<MapApiCall> call = api.getDurationJson();  
MapApiCall apiCall = call.execute().body();  

如果您出于某种原因想要在不使用线程的情况下禁用 NetworkOnMainThreadException,请使用:

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

但是,这真的不推荐,如果你不知道 StrictMode 的作用,请不要使用它。

关于android - 改造 2 错误 : NetworkOnMainThreadException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35796850/

相关文章:

c# - 如何编写触发器?

c++ - 这个 RAII 独占资源检查对象/管理器组合线程安全吗?

c++ - Qt5 应用程序在关闭时崩溃 (QWidget::show)

android - 从改造响应中获取 JSON 数组

android - 将 Logcat 从 Android 应用程序保存到 txt 文件

java - Android:如何使用警报管理器

android - 如何使用 SendGrid Api 在单个电子邮件中发送多个附件?

java - Android 4.3 果冻 bean 时间格式问题

json - 使用密封类或 Moshi 接口(interface)时无法为类创建转换器

android - 如何在 Retrofit 中解析没有任何对象的 JSON 数组?