android4.0以上网络访问为什么要开线程,已经Handler的使用
2015-01-21 02:47
489 查看
android4.0以上访问网络不能在主线程中进行以及在线程中操作UI的解决方法
2013/9/30 11:29:36刚刚上手android,在写一个利用Socket与服务器端进行通信的Demo时候报了一个android.os.NetworkOnMainThreadException的异常:
服务器端:
public class SimpleServer {
public static void main(String[] args){
try {
ServerSocket ss=new ServerSocket(40000);
System.out.println("等待连接......");
while(true){
Socket s=ss.accept();
OutputStream os=s.getOutputStream();
os.write("hello".getBytes("utf-8"));
os.close();
s.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
求助度娘后发现是SDK的版本问题,android4.0中访问网络不能在主程序中进行,行吧,那就老老实实的重新开启一个线程:
new Thread(){
public void run(){
try {
Socket s=new Socket("172.22.16.26", 40000);
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
String line=br.readLine();
show.setText("服务器说:"+line);
br.close();
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
结果又报了异常:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
相信各位已经看出了在下犯了一个很低级的错误:在新启的线程中操作UI,UI线程是非线程安全的,Android平台不允许Activity新启动的线程访问该Activity里的界面组件,这时就要借助Handler的消息传递机制了:
new Thread(){
public void run(){
try {
Socket s=new Socket("172.18.6.26",40000);
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
String line=br.readLine();
//System.out.println("服务器说:"+line);
Message msg=new Message();
msg.what=0x123;
msg.obj=line;
myhandler.sendMessage(msg);
br.close();
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
然后重写handlerMessage方法获取消息:
final Handler myhandler=new Handler(){
public void handleMessage(Message msg){
if(msg.what==0x123){
System.out.println("--------------->"+msg.obj);
show2.setText((String)msg.obj);
}
}
};
当新线程发送消息时,该方法自动被调用,handlerMessage(Message msg)方法依旧位于主线程中,所以可以动态的修改UI组件。
网络连接不能放在主线程
android 4.0 以上
网络连接不能放在主线程
4.0 以下 好像可以
在Android4.0以后,会发现,只要是写在主线程(就是Activity)中的HTTP请求,运行时都会报错,这是因为Android在4.0以后为了防止应用的ANR(aplication Not Response)异常,即使这里表达不是很清晰,大家应该都明白吧,哈哈
就针对此问题有两种解决的方法:
1.可以再Activity的onCreate()方法中加入这样一段代码,如下:
if (Build.VERSION.SDK_INT >= 11) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads ().detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());
}
后就可以在主线程中进行网络操作了
2.一般情况我们应该这样做
启动一条子线程进行你的网络请求。
当然,如果你的应用程序执行的网络请求数据量很小的话,可以使用第一种方案
相关文章推荐
- 关于android4.0中访问网络不能在主线程中进行以及Handler的使用
- android4.0以上访问网络不能在主线程中进行以及在线程中操作UI的解决方法
- 关于android4.0中访问网络不能在主线程中进行以及Handler的使用
- “android.os.NetworkOnMainThreadException”---关于Android4.0后无法将访问网络放入主线程中的解决办法
- Android5.0以上使用XUtils访问网络出现错误: java.io.IOException: stack size 1036KB
- 10_Android中通过HttpUrlConnection访问网络,Handler和多线程使用,读取网络html代码并显示在界面上,ScrollView组件的使用
- Android5.0以上使用XUtils访问网络出现错误或者网络数据无法加载: java.io.IOException: stack size 1036KB
- 10_Android中通过HttpUrlConnection访问网络,Handler和多线程使用,读取网络html代码并显示在界面上,ScrollView组件的使用
- Android低阶之【chapter - 6】Handler结合网络访问的使用方法,通过Handler实现异步网络请求
- 【访问网络资源出错】不允许一个用户使用一个以上用户名与服务器或共享资源的多重连接
- Android - 使用Timer+Handler定时跨线程访问UI控件
- 【黑马Android】(05)短信/查询和添加/内容观察者使用/子线程网络图片查看器和Handler消息处理器/html查看器/使用HttpURLConnection采用Post方式请求数据/开源项目
- Android4.0 主线程不能访问网络异常解决办法
- 为什么Handler在主线程中不需要使用Looper.prepare()和loop()方法?看源码!
- 用Java线程获取优异性能(II)——使用同步连载线程访问关键代码部份
- 网络中无法访问XP系统下共享文件,错误:计算机无法访问,您可能没有权限使用网络资源
- 计算机名"无法访问。您可能没有权限使用网络资源。请与这台服务器的管理员联系以查明您是否有访问权限。拒绝访问。"
- 为什么 FleaPHP 使用 Table Data Gateway 代替 Active Record 来提供数据库访问服务
- 为什么 FleaPHP 使用 Table Data Gateway 代替 Active Record 来提供数据库访问服务
- 用Java线程获取优异性能(II)——使用同步连载线程访问关键代码部份