Andoid UI toolkit 并不是线程安全的,所以你不能从非 UI 线程来操纵 UI 组件。你必须把所有的 UI 操作放在 UI 线程里,所以 Android 的单线程模型有两条原则:
1.不要阻塞 UI 线程。
2.不要在 UI 线程之外访问 Android UI toolkit(主要是这两个包中的组件:android.widget and android.view)。
那我之前写的一个 demo 中,在 UI 线程中我需要发起一个网络请求并解析响应的结果,调试几次发现,每次到达发送 http 请求时就会抛出异常。。
谷歌了一大把,终于发现本文最前面讲的东西。在安卓 4.0 以后采用了严苛模式,造成这样的错误原因是代码不符合 Android 规范,如果把上面访问方式改为异步操作就不会出现在 4.0 上访问出现 android.os.NetworkOnMainThreadException 异常
方法一:
那么为了保留这个项目并可运行,我们可以在 oncreate 方法的一开始就添加如下代码:
//严苛模式(StrictMode)
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() //构造StrictMode
.detectDiskReads() //当发生磁盘读操作时输出
.detectDiskWrites()//当发生磁盘写操作时输出
.detectNetwork() //访问网络时输出,这里可以替换为detectAll() 就包括了磁盘读写和网络I/O
.penaltyLog() //以日志的方式输出
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects() //探测SQLite数据库操作
.penaltyLog() //以日志的方式输出
.penaltyDeath()
.build());
方法二:
或者
“只有在 UI 线程中的对象才能操作 UI 线程中的对象,为了将非 UI 线程中的数据传送到 UI 线程,可以使用一个 Handler 运行在 UI 线程中。Handler 是 Android framework 中管理线程的部分,一个 Handler 对象负责接收消息然后处理消息。”
我可以为一个新的线程创建一个 Handler,也可以创建一个 Handler 然后将它和已有线程连接。
代码如下:
//获取网络资源..采用handler+Thread模式实现多线程异步加载
private void loadContent(){
Thread thread = new Thread(){
@Override
public void run(){
//载入xml文件
try {
//先得到文章信息
title = analyzeXML(i);//analyzeXML()为我一个自定义方法,返回一个String
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 模拟网络延时
SystemClock.sleep(2000);
Message msg = new Message();
//将title通过sendMessage方法发送到handler中
msg.obj = title;
myHandler.sendMessage(msg);
}
};
thread.start();
}
//更新UI
private Handler myHandler = new Handler(){
@SuppressWarnings("unused")
public void handlerMessage(Message msg){
//super.handleMessage(msg);
//取得其他线程发送过来的Message对象
//设置textview控件的值
textview.setText("第"+(i+1)+"篇文章标题是:"+msg.obj);
}
};
搞定!
另外注明,本人乃刚入手学习安卓,不对之处请各位多多指教~~~