解决4.0后android.os.NetworkOnMainThreadException错误

来源:互联网 发布:nc57数据字典下载 编辑:程序博客网 时间:2024/05/03 00:22

Android SDK 2.0中访问网络不会出现android.os.NetworkOnMainThreadException异常错误,但在 4.0之后运行则会报此错误(即在主线程访问网络时发生异常)。

原因就是Android在4.0之前的版本都支持在主线程中访问网络,但在4.0以后对这部分程序进行了优化,若在主线程里执行Http请求都会报错,

其原则就是:UI线程不能有任何的网络访问操作


解决办法有两个思路,分别是:?
1
2
3
4
if(android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = newStrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}
从 Android 2.3 开始提供了一个新的类 StrictMode,该类可以用于捕捉发生在应用程序主线程中耗时的磁盘、网络访问或函数调用,可以帮助开发者改进程序,

使主线程处理 UI 和动画在磁盘读写和网络操作时变得更平滑,避免主线程被阻塞。?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
publicvoidonCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.share_mblog_view);
    newThread(runnable).start();
}
 
Handler handler = newHandler(){
    @Override
    publicvoidhandleMessage(Message msg) {
        super.handleMessage(msg);
        Bundle data = msg.getData();
        String val = data.getString("value");
        Log.i("mylog","请求结果-->"+ val);
    }
}
 
Runnable runnable = newRunnable(){
    @Override
    publicvoidrun() {
        //
        // TODO: http request.
        //
        Message msg = newMessage();
        Bundle data = newBundle();
        data.putString("value","请求结果");
        msg.setData(data);
        handler.sendMessage(msg);
    }
}
举例:如下获取Json字符串的方法在UI主线程中,就会报错:android.os.NetworkOnMainThreadException?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
publicclassJSONParser {
 
    staticInputStream is = null;
 
staticJSONObject jObj = null;
staticString json = "";
 
// constructor
publicJSONParser() {
 
}
 
publicJSONObject getJSONFromUrl(String url) {
 
    // Making HTTP request
    try{
        // defaultHttpClient
        DefaultHttpClient httpClient = newDefaultHttpClient();
        HttpGet httpPost = newHttpGet(url);
 
            HttpResponse getResponse = httpClient.execute(httpPost);
           finalintstatusCode = getResponse.getStatusLine().getStatusCode();
 
           if(statusCode != HttpStatus.SC_OK) {
              Log.w(getClass().getSimpleName(),
                  "Error " + statusCode + " for URL " + url);
              returnnull;
           }
 
           HttpEntity getResponseEntity = getResponse.getEntity();
 
        //HttpResponse httpResponse = httpClient.execute(httpPost);
        //HttpEntity httpEntity = httpResponse.getEntity();
        is = getResponseEntity.getContent();           
 
    }catch(UnsupportedEncodingException e) {
        e.printStackTrace();
    }catch(ClientProtocolException e) {
        e.printStackTrace();
    }catch(IOException e) {
        Log.d("IO", e.getMessage().toString());
        e.printStackTrace();
 
    }
 
    try{
        BufferedReader reader = newBufferedReader(newInputStreamReader(
                is,"iso-8859-1"),8);
        StringBuilder sb = newStringBuilder();
        String line = null;
        while((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        json = sb.toString();
    }catch(Exception e) {
        Log.e("Buffer Error","Error converting result " + e.toString());
    }
 
    // try parse the string to a JSON object
    try{
        jObj = newJSONObject(json);
    }catch(JSONException e) {
        Log.e("JSON Parser","Error parsing data " + e.toString());
    }
 
    // return JSON String
    returnjObj;
 
  }
}
正确的做法:可以采用AsyncTack?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
publicclassJSONParserextendsAsyncTask <String, Void, String>{
 
    staticInputStream is = null;
 
staticJSONObject jObj = null;
staticString json = "";
 
// constructor
publicJSONParser() {
 
}
@Override
protectedString doInBackground(String... params) {
 
    // Making HTTP request
    try{
        // defaultHttpClient
        DefaultHttpClient httpClient = newDefaultHttpClient();
        HttpGet httpPost = newHttpGet(url);
 
            HttpResponse getResponse = httpClient.execute(httpPost);
           finalintstatusCode = getResponse.getStatusLine().getStatusCode();
 
           if(statusCode != HttpStatus.SC_OK) {
              Log.w(getClass().getSimpleName(),
                  "Error " + statusCode + " for URL " + url);
              returnnull;
           }
 
           HttpEntity getResponseEntity = getResponse.getEntity();
 
        //HttpResponse httpResponse = httpClient.execute(httpPost);
        //HttpEntity httpEntity = httpResponse.getEntity();
        is = getResponseEntity.getContent();           
 
    }catch(UnsupportedEncodingException e) {
        e.printStackTrace();
    }catch(ClientProtocolException e) {
        e.printStackTrace();
    }catch(IOException e) {
        Log.d("IO", e.getMessage().toString());
        e.printStackTrace();
 
    }
 
    try{
        BufferedReader reader = newBufferedReader(newInputStreamReader(
                is,"iso-8859-1"),8);
        StringBuilder sb = newStringBuilder();
        String line = null;
        while((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        json = sb.toString();
    }catch(Exception e) {
        Log.e("Buffer Error","Error converting result " + e.toString());
    }
 
    // try parse the string to a JSON object
    try{
        jObj = newJSONObject(json);
    }catch(JSONException e) {
        Log.e("JSON Parser","Error parsing data " + e.toString());
    }
 
    // return JSON String
    returnjObj;
 
}
protectedvoidonPostExecute(String page)
{  
    //onPostExecute
}  
}
在主线程中只需执行如下调用:?
1
2
mJSONParser = newJSONParser();
mJSONParser.execute();

第一种:强制使用以下更改,即在MainActivity的setContentView(R.layout.activity_main)下添加如下代码:

第二种:使用Thread、Runnable、Handler。即在Runnable中做HTTP请求,不用阻塞UI线程。

第二种方法就是多线程访问,因此可以采用AsyncTask任务方式也是相通的。

原创粉丝点击