【转载】Android 3 开始 Activity MainThread中不能执行http通信了
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中不能再请求其他子线程
具体的代码如下
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); }