android.os.NetworkOnMainThreadException的解決方案

06-24 18:04:36.857: E/AndroidRuntime(22251): FATAL EXCEPTION: main
06-24 18:04:36.857: E/AndroidRuntime(22251): android.os.NetworkOnMainThreadException
06-24 18:04:36.857: E/AndroidRuntime(22251):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1128)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:175)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at libcore.io.IoBridge.sendto(IoBridge.java:473)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:182)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at java.net.DatagramSocket.send(DatagramSocket.java:284)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at com.example.com.ihome.bang.util.UdpHelper.send(UdpHelper.java:93)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at com.example.com.ihome.bang.adapter.ListViewAdapter$2.onClick(ListViewAdapter.java:210)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at android.view.View.performClick(View.java:4171)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at android.view.View$PerformClick.run(View.java:17070)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at android.os.Handler.handleCallback(Handler.java:615)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at android.os.Handler.dispatchMessage(Handler.java:92)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at android.os.Looper.loop(Looper.java:137)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at android.app.ActivityThread.main(ActivityThread.java:4797)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at java.lang.reflect.Method.invokeNative(Native Method)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at java.lang.reflect.Method.invoke(Method.java:511)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:804)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:571)
06-24 18:04:36.857: E/AndroidRuntime(22251):     at dalvik.system.NativeStart.main(Native Method)
html

原來在Android2.2上面運行的好好的一個網絡應用程序,主要是發送UDP信息跟服務器進行通訊的程序,安裝到4.0上面就爆出了這個問題。java

查了一下官方文檔。文檔上說:NetworkOnMainThreadException是由於應用程序在主線程上嘗試網絡操做。另外,這個異常在Honeycomb SDK或更高版本的SDK上纔會拋出。低版本的SDK容許應用程序在主線程或loop線程執行網絡操做,但不鼓勵這樣作。android

 

方法1:咱們能夠把android:targetSdkVersion=」Version Num」這句話從AndroidManifest.xml去掉,問題就解決了,但不是治本的解決方案。(以下圖所示)

image

方法2:在進行網絡通訊的部分,單獨執行異步任務。

如今讓咱們思考一下,讓原有代碼修改最小的一種方法。若是程序對實時性的要求不是很高的話,咱們能夠建立一個異步任務類,這個異步任務類裏面含有一個網絡消息隊列(Queue)。這個類經過對外提供一個消息入隊列的接口,在異步類內部進行消息的發送。當要發送消息的時候(也就是原來進行網絡操做的地方,咱們假設是發送消息),咱們將網絡消息加入Queue,在異步任務裏面用一個while循環查詢Queue,當Queue中有數據的時候就進行發送,沒有的話,sleep一段時間。具體的代碼以下所示。服務器

package com.example.com.ihome.bang.tool;

import java.util.LinkedList;
import java.util.Queue;

import com.example.com.ihome.bang.util.UdpHelper;

import android.os.AsyncTask;
import android.util.Log;

public class SendThread extends AsyncTask{
    private static Queue<String> queue = new LinkedList<String>();  
    public static Boolean SendOrder(String Order){
        queue.offer(Order);
        return true;
    }
    
    
    @Override
    protected Object doInBackground(Object... params) {
        String str;
        while (true) {
            //Log.d(SendThread.class.getName(), "進入doInBackground");
            if ((str = queue.poll()) != null) {

                //Log.d(SendThread.class.getName(), "doInBackground_發送"+str);
                UdpHelper.sendReally(str);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    
                    e.printStackTrace();
                    
                }
            }
            

        }
    }

}

方法3:在進行網絡通訊的部分,用後臺線程來執行操做

本身建立線程的話,比建立異步任務更麻煩一點。記住,當你要用線程來處理網絡通訊部分的時候,記得將線程設置爲後臺運行,也就是經過設置線程的屬性爲」background」。咱們能夠經過傳遞參數 THREAD_PRIORITY_BACKGROUNDProcess.setThreadPriority() 。.若是咱們不經過這種方法將線程的優先級設爲較低級別的話,那麼這個線程就會擁有跟UI線程同樣的優先級,咱們的應用程序就可能被這個線程拖慢。網絡

相關文章
相關標籤/搜索