android报错android.os.NetworkOnMainThreadException
程序员文章站
2022-05-31 14:10:02
...
菜鸟新手写android应用demo,遇到android.os.NetworkOnMainThreadException异常,根据大神的指示,去查了一下官方文档,上面是这样说的:
The exception that is thrown when an application attempts to perform a networking operation on its main thread.
在主线程中试图进行网络操作会抛出此异常。
This is only thrown for applications targeting the Honeycomb SDK or higher.
Applications targeting earlier SDK versions are allowed to do networking on
their main event loop threads, but it's heavily discouraged.
这个异常只会在使用Honeycomb SDK或更高版本应用上才会抛出(这个版本应该是api level 11 android 3.0),
早于此版本的sdk允许在主线程中进行网络操作,当然,谷歌工程师强烈不建议这么做
英语水平有限,就只能翻译到这种程度了,见谅。
查阅了一下诸位大神的指南,总结以下两种解决方法:
1.简单粗暴型
//修改系统策略,放开所有的权限
//代码添加到onCreate回调方法中即可
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
ps:这种方式非常不被推荐,这种做法有点矫枉过正,放开所有的限制,看一下源码中的permitAll的方法与解释,如同为了怕麻烦而取消安检一样,危险等级较高,不推荐
/** Disable the detection of everything. */
/*取消所有检测*/
public Builder permitAll() {
return disable(ALL_THREAD_DETECT_BITS);
}
2.采用独立线程处理网络请求
将网络请求等耗时操作放在独立的线程中,主线程通过handler获取数据。
代码如下
/**
* 处理网络请求的线程
*/
private class RequestThread extends Thread {
@Override
public void run() {
Message msg = new Message();
Bundle data = new Bundle();
//耗时操作
//为节省篇幅,此处省略网络请求和处理数据的代码
data.putString("value", string);
msg.setData(data);
msg.what = 1;
handler.sendMessage(msg);
}
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
Bundle data = msg.getData();
String val = data.getString("value");
//获取到数据后,进行修改UI等操作
//请注意,如需要修改主线程的UI,需要再handler中进行,否在会抛出异常。
tvCode.setText(val);
}
}
};
然后可以在按钮点击等其他事件中开启线程,处理网络请求等耗时操作。需要注意的是,修改主UI必须在主线程中,否则会抛出异常。
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.