NetworkOnMainThreadException,
一、问题
在安卓2.3版本之前,我们在主线程里面进行网络操作时没有问题的,但是在2.3版本之后(也就是3.0等),就会出现NetworkOnMainThreadException。异常。举一个例子,比如我们要显示一张网络图片,以世纪乐知的标志;徽标为例,可以这样写:
包com。举例。net图像查看器;
导入Java。io。io异常;
导入com。举例。net图像查看器。服务。图像实用程序;
导入安卓。OS。捆绑;
导入安卓。OS。严格模式;
导入安卓。app。活动;
导入安卓。图形。位图;
导入安卓。查看。菜单;
导入安卓。查看。查看;
导入安卓。查看。查看。onclick侦听器;
导入安卓。小部件。按钮;
导入安卓。小部件。编辑文本;
导入安卓。小部件。imageview
导入安卓。小部件。敬酒;
公共类主要活动扩展活动{
私人按钮按钮;
私有图像视图图像视图
@覆盖
受保护的void onCreate(Bundle saved instancestate){
超级棒。oncreate(savedInstanceState);
setContentView(r . layout。活动_主);
Button=(Button)findViewById(r . id。按钮);
imageView=(imageView)findViewById(r . id。img);
按钮。setonclicklistener(new OnClickListener(){
@覆盖
公共void onClick(视图五){
@覆盖
public boolean onCreateOptionsMenu(菜单菜单){
getMenuInflater().inflate(R.menu.main,menu);
返回真实的
获取图片的工具类:
URL url=新URL(地址URL);
http URL connection conn=(http URL connection)URL。打开连接();
conn . setrequestmethod( GET );
conn . setconnecttimeout(5000);
InputStream is=conn . getinputstream();
byte[]b=stream util。获取字节(是);
位图BF=bitmapfactory。decodebytearray(b,0,b . length);
回报BF;
把输入流转化成一个字节[]的工具类:
公共静态字节[]获取字节(输入流为)引发IOException{
ByteArrayOutputStream=new ByteArrayOutputStream();
字节[] b=新字节[1024];
int len=0;
while ((len=is.read(b))!=-1) {
stream.write(b,0,len);
是。close();
byte[]字节流=流。tobytearray();
系统。出去。println(字节流。tostring());
返回字节流
然后添加上访问网络权限:uses-permission Android:name= Android。许可。互联网/,最后运行程序,如果在2.3版本之前就可以显示出图片,但是在2.3版本之后就会出现NetworkOnMainThreadException。异常。
二、解决方法:
1、一是在主线程的onCreate()方法中加入如下代码:
StrictMode.setThreadPolicy(新严格模式.线程策略。构建器()。detectDiskReads().detectDiskWrites().检测网络()。penaltyLog().build());
StrictMode.setVmPolicy(新严格模式.虚拟机策略。构建器()。detectLeakedSqlLiteObjects().detectLeakedClosableObjects()。penaltyLog().penaltyDeath().build());
注:
通过查阅相关资料,发现,自从安卓2.3之后,系统增加了一个类:严格模式。这个类对网络的访问方式进行了一定的改变安卓。的官方文档给出了这个类设置的目的:严格模式是一个系统提供的开发工具,用以检测在开发过程中因为偶然的事故从而造成的系统潜在的问题,进而提示开发者对其进行修复100 .严格模式通常用于捕获磁盘访问或者网络访问中与主进程之间交互产生的问题,因为在主进程中,用户界面操作和一些动作的执行是最经常用到的,它们之间会产生一定的冲突问题。将磁盘访问和网络访问从主线程中剥离可以使磁盘或者网络的访问更加流畅,提升响应度和用户体验。
显然,大多数初学者在进行网络开发时,会选择将访问网络的代码直接放到主进程中,由于和主进程的首要工作——UI交互——相矛盾,因此,必须设置一定的检测机制,以保证系统运行的流畅,所有的异常都可以被检测。使用的时候只需要在你项目运行的入口活动的创建中放入这段代码,那么整个项目程序都有用。不需要每个活动里面加入。
但是呢,从严格模式类的用途我们就可以知道这不是一个好方法。
2、一个比较稳妥的方法就是使用异步任务,这个类相信都不陌生。那代码就可以这样来写了:
包com。举例。net图像查看器。util
导入Java。io。inputstream
导入Java。网。网址;
导入安卓。图形。位图;
导入安卓。图形。bitmapfactory
导入安卓。OS。异步任务;
导入安卓。小部件。imageview
公共类向下图像扩展AsyncTask字符串、Void、位图{
私有图像视图图像视图
公共图像(图像视图图像视图){
this.imageView=imageView
@覆盖
受保护的位图背景(字符串.params) {
string URL=params[0];
位图位图=空
尝试{
输入流为=新URL(网址).openStream();
位图=位图工厂。解码流(is);
} catch(异常e) {
e。printstacktrace();
返回位图;
@覆盖
受保护的void onPostExecute(位图结果){
super.onPostExecute(结果);
imageView.setImageBitmap(结果);
那么主要活动的代码就应该是这样的了:
私有图像视图图像视图
私有字符串uri =http://img.cn/www/images/index_logo.gif?20121229;
@覆盖
受保护的void onCreate(Bundle saved instancestate){
超级棒。oncreate(savedInstanceState);
setContentView(r . layout。活动_主);
Button=(Button)这个。findviewbyid(r . id。按钮);
imageView=(imageView)this。findviewbyid(r . id。img);
按钮。setonclicklistener(new OnClickListener(){
@覆盖
公共void onClick(视图五){
新的向下图像(图像视图)。执行(uri );
@覆盖
public boolean onCreateOptionsMenu(菜单菜单){
getMenuInflater().inflate(R.menu.main,menu);
返回真实的
另外还有朋友建议使用线程、处理程序、可运行等来实现,当然这也可以,思维灵活,方法多多。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。