1. 程式人生 > >解決android.os.NetworkOnMainThreadException

解決android.os.NetworkOnMainThreadException


在我用手機測試我們的APP的時候,丟擲一個如題的異常:
android.os.NetworkOnMainThreadException

字面意思是說:在主執行緒中的網路異常。然後我就去了解了下這個異常,先看看官方的說明:

NetworkOnMainThreadException

Class Overview

The exception that is thrown when an application attempts to perform a networking operation on its main thread.

This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged. See the document Designing for Responsiveness.

Also see StrictMode

所以事情就很清楚了。一個APP如果在主執行緒中請求網路操作,將會丟擲此異常。Android這個設計是為了防止網路請求時間過長而導致介面假死的情況發生。

解決方案有兩個,一個是使用StrictMode,二是使用執行緒來操作網路請求。

第一種方法:簡單暴力,強制使用,程式碼修改簡單(但是非常不推薦)

在MainActivity檔案的setContentView(R.layout.activity_main)下面加上如下程式碼
if(android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = newStrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}

第二種方法 將請求網路資源的程式碼使用Thread去操作。在Runnable中做HTTP請求,不用阻塞UI執行緒。

publicvoid onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.main_view);
    newThread(runnable).start(); //here or somewhere to start
}
 
Handler handler = newHandler(){
    @Override
    publicvoid handleMessage(Message msg) {
        super.handleMessage(msg);
        Bundle data = msg.getData();
        String val = data.getString("value");
        Log.i(TAG,"請求結果:"+ val);
    }
}
 
Runnable runnable = newRunnable(){
    @Override
    publicvoid run() {
        // TODO: http request.
        Message msg = newMessage();
        Bundle data = newBundle();
        data.putString("value","請求結果");
        msg.setData(data);
        handler.sendMessage(msg); //send to the handler of the caller thread
    }
}

上面是比較通用的方法,我的程式碼:

// Android 4.0 之後不能在主執行緒中請求HTTP請求
            newThread(newRunnable(){
                @Override
                publicvoid run() {
                    cachedImage = asyncImageLoader.loadDrawable(imageUrl, position);
                    imageView.setImageDrawable(cachedImage);
                }
            }).start();



測試使用的完整例程下載:http://download.csdn.net/detail/changliangdoscript/7452907