安卓错误 android.os.NetworkOnMainThreadException 的解决

Android 2020-04-17 阅读 120 评论 0

问题描述

在安卓中请求 http,代码如下,出现了异常, android.os.NetworkOnMainThreadException

public void retrieveFeed() {
    OkHttpClient client = new OkHttpClient();
    String url = "http://api.baidu.com/feed";
    Request request = new Request.Builder()
            .url(url)
            .build();
    try {
        Response response = client.newCall(request).execute();
        String result = response.body().string();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
W/System.err: android.os.NetworkOnMainThreadException
W/System.err:     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
        at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:86)
        at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:74)
        at java.net.InetAddress.getAllByName(InetAddress.java:752)
        at okhttp3.Dns$Companion$DnsSystem.lookup(Dns.kt:49)
W/System.err:     at okhttp3.internal.connection.RouteSelector.resetNextInetSocketAddress(RouteSelector.kt:164)
        at okhttp3.internal.connection.RouteSelector.nextProxy(RouteSelector.kt:129)
        at okhttp3.internal.connection.RouteSelector.next(RouteSelector.kt:71)
        at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:213)
        at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:108)
        at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:76)
        at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:245)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:82)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
        at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:197)
        at okhttp3.internal.connection.RealCall.execute(RealCall.kt:148)
        at com.example.test.MainActivity.sendPolicy(MainActivity.java:47)
        at java.lang.reflect.Method.invoke(Native Method)
        at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:397)
        at android.view.View.performClick(View.java:5619)
        at android.view.View$PerformClick.run(View.java:22298)
        at android.os.Handler.handleCallback(Handler.java:754)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:163)
        at android.app.ActivityThread.main(ActivityThread.java:6360)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:880)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)

解决方法

可以有2种方法处理。

1. 使用以下代码禁用严格模式

可以在 ActivityonCreate() 方法中加入这样一段代码,适用于网络请求数据量很小的话,如下。

if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}

对于一些比较耗时间的网络请求,如果还在主线程发送,将会非常糟糕,android 手机会卡顿,进而出现“没有相应”的弹出框,体验很不好,可以考虑第2种方法。

2. 使用异步任务 AsyncTask

class RetrieveFeedTask extends AsyncTask<String, Void, String> {
    protected String doInBackground(String... urls) {
        OkHttpClient client = new OkHttpClient();
        String url = urls[0];
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response = null;
        String result = "";
        try {
            response = client.newCall(request).execute();
            result = response.body().string();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    protected void onPostExecute(String result) {
        Log.e("========", result);
    }
}
最后更新 2020-04-17