当前位置:操作系统 > 安卓/Android >>

Android 3.0获取互联网资源时出现异常的原因分析以及解决方案

相信在很多使用最新版本Android系统开发网络程序的同学在入门的时候都会遇到后台抛出异常的问题。仔细查阅代码之后,发现和书上或者网络上的代码是一致的,而且也已经在AndroidManifest.xml中经过授权。但是,后台仍然抛出了如下异常:

 \

LogCat提示,系统抛出了android.os.NetworkOnMainThreadException异常。
经过反复实验,发现,当我们用数据流方式获取网络资源(比如一个页面的源文件)的时候,系统会抛出此异常,比如,下面这两条语句:
InputStream inStream =conn.getInputStream();
inStream.read(buffer)

此时,该异常被系统抛出。
通过查阅相关资料,发现,自从Android 2.3之后,系统增加了一个类:StrictMode。这个类对网络的访问方式进行了一定的改变。
Android的官方文档给出了这个类设置的目的:
StrictMode是一个系统提供的开发工具,用以检测在开发过程中因为偶然的事故从而造成的系统潜在的问题,进而提示开发者对其进行修复。

StrictMode通常用于捕获磁盘访问或者网络访问中与主进程之间交互产生的问题,因为在主进程中,UI操作和一些动作的执行是最经常用到的,它们之间会产生一定的冲突问题。将磁盘访问和网络访问从主线程中剥离可以使磁盘或者网络的访问更加流畅,提升响应度和用户体验。

显然,大多数初学者在进行网络开发时,会选择将访问网络的代码直接放到主进程中,由于和主进程的首要工作——UI交互——相矛盾,因此,必须设置一定的检测机制,以保证系统运行的流畅,所有的异常都可以被检测。
Android文档建议我们增加这两条命令:
StrictMode.setThreadPolicy(newStrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(newStrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());

现在让我们看看它们都是做什么的。
public static voidsetThreadPolicy(StrictMode.ThreadPolicy policy)
这个方法允许我们为当前应用设置一组线程运行策略机制。其中的参数是一个策略组(即一组策略)。
public static finalclass StrictMode.ThreadPolicy.Builder()
Builder是StrictMode中内嵌类ThreadPolicy的一个内嵌类,在此我们调用了它的默认构造方法。
detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build()

通过这种方式,我们设置了一组监控模式,我们要检测磁盘的读写,网络的访问, Log中的违规等。
第二条语句设置了虚拟机的一组监控策略,参数一致,因此不再赘述。
这样,在保证了网络和磁盘访问受控之后,主线程就允许我们对网络资源进行访问。
最后,需要说的是,策略限制只需要在主线程运行开始阶段,也就是onCreate刚被调用的时候使用添加,其后的所有方法都将遵循这一规则。

 
摘自 北京大学-Google Android实验室
 

补充:移动开发 , Android ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,