当前位置: 代码迷 >> 人工智能 >> Android 三 开始 Activity MainThread中不能执行http通信了
  详细解决方案

Android 三 开始 Activity MainThread中不能执行http通信了

热度:8239   发布时间:2013-02-26 00:00:00.0
Android 3 开始 Activity MainThread中不能执行http通信了

                      年前发现一个问题, 我们平台搞出来的Android 支付SDK在android 4.0下面出异常了。

                      查log,发现是在httpClient做http request的时候出异常, 异常如下

                     

android.os.NetworkOnMainThreadException


                     原因是Google从3开始,强制默认禁止UI主线程发起通信请求,看来Google越来越重视UI体验了。这是好事情

                     

                     对应的方法, 有两个:

                    1. 可以临时性的 在Activity初期化的时候,指定StickMode,可以绕开这个OS check, 不过别把这个当彻底的解决方法

                           具体说起来, 就是在要通信的画面的Activity的OnCreate方法中如下配置stickMode

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath().build());


                     2. 永久性的对应, 把通信的代码转移到子线程里去做, 比较靠谱的是new一个AyncTask,在里面做通信

                          有几个细节性的问题是,

                                第一, 一般原有通信的代码都是共通的API, 被许多个Activity调用, 一个良好的修改方法是在共通API里面new AyncTask

                               第二, 通信的API一般来说都是同步的, 你通信,然后画面主线程需要堵塞住,等待API的通信结果,再决定下面的业务逻辑的走向。

所以,这块可以采取 AyncTask.get(), 让主线程堵塞,直到通信结束。 当然,如果你需要将通信异步的话, 可以用Handler机制来解决

                               第三, 用来通信的AyncTask中不能再请求其他子线程, 比如你不能在AyncTask中调用以下的代码

                             

String userAgent = SystemInfo.getUserAgentFromWebView(context);

                              原因是WebView在App中本身是已单独的子线程的模式存在

                        

                      具体的代码如下

                         a. 异步的http请求线程

class HttpReqTask extends AsyncTask<Object, Object, HttpResponse>{         @Override    protected HttpResponse doInBackground(Object... params){                String url = (String)params[0];        String session = (String)params[1];        List<NameValuePair> paierList  = (ArrayList<NameValuePair>)params[2];        HttpClient httpclient  = (HttpClient)params[3];                HttpPost request = new HttpPost(url);        HttpResponse response = null;        if (session != null && session.length() != 0) {            request.addHeader(SM.COOKIE, "sessid" + "=" + session);        }        try {            request.setEntity(new UrlEncodedFormEntity(paierList, HTTP.UTF_8));            response = httpclient.execute(request);        } catch (Exception e) {            throw new RuntimeException(e);        }        return response;    }    }

                       b.调用的代码

        Object []param = new Object[4];        param[0] = url;        param[1] = session;        param[2] = paierList;        param[3] = httpclient;        AsyncTask res  = new HttpReqTask().execute(param);                HttpResponse response = null;        try {            response = (HttpResponse) res.get();        } catch (Exception e) {            Log.e("HttpAPI.callHttpPost()", "Error", e);        }

#以上#

  相关解决方案