這段時間在做客戶端,用的是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();