版本不同引起的android.os.NetworkOnMainThreadException

這段時間在做客戶端,用的是2.3的模擬器,一直沒注意做網絡請求時的延時問題(因爲在本地),今天放到4.0版本的真機上做測試,結果用不了,DEBUG一下:

05-19 14:40:09.432: W/HttpUtils(1274): Exception =null
05-19 14:40:09.432: W/System.err(1274): android.os.NetworkOnMainThreadException
05-19 14:40:09.477: W/System.err(1274): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
05-19 14:40:09.482: W/System.err(1274): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
05-19 14:40:09.482: W/System.err(1274): at libcore.io.IoBridge.connectErrno(IoBridge.java:144)
05-19 14:40:09.482: W/System.err(1274): at libcore.io.IoBridge.connect(IoBridge.java:112)
05-19 14:40:09.493: W/System.err(1274): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
05-19 14:40:09.512: W/System.err(1274): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
05-19 14:40:09.512: W/System.err(1274): at java.net.Socket.connect(Socket.java:842)
05-19 14:40:09.512: W/System.err(1274): at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:119)
...


網上找解決辦法:http://www.2cto.com/kf/201402/281526.html


一個APP如果在主線程中請求網絡操作,將會拋出此異常。Android這個設計是爲了防止網絡請求時間過長而導致界面假死的情況發生。


解決方案有兩個,一個是使用StrictMode,二是使用線程來操作網絡請求。



第一種方法:簡單暴力,強制使用,代碼修改簡單(但是非常不推薦)
在MainActivity文件的setContentView(R.layout.activity_main)下面加上如下代碼


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

第二種方法就是我使用的方法也是我要推薦的方法,將請求網絡資源的代碼使用Thread去操作。在Runnable中做HTTP請求,不用阻塞UI線程。

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.main_view);
    new Thread(runnable).start();
}
 
Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        Bundle data = msg.getData();
        String val = data.getString("value");
        Log.i(TAG,"請求結果:" + val);
    }
}
 
Runnable runnable = new Runnable(){
    @Override
    public void run() {
        // TODO: http request.
        Message msg = new Message();
        Bundle data = new Bundle();
        data.putString("value","請求結果");
        msg.setData(data);
        handler.sendMessage(msg);
    }
}


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


// Android 4.0 之後不能在主線程中請求HTTP請求
new Thread(new Runnable(){
    @Override
	public void run() {              
	cachedImage = asyncImageLoader.loadDrawable(imageUrl, position);
    imageView.setImageDrawable(cachedImage);
    }
}).start();




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章