赞
踩
- // 2.点击按钮进行查看,指定路径的源码
- public void click(View v) {
- try {
- // 2.1获取源码路径
- String path = et_path.getText().toString().trim();
- // 2.2创建URL对象,指定我们要访问的网址(路径)
- URL url = new URL(path);
- // 2.3拿到httpurlconnection对象,用于发送或者接收数据
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- // 2.4设置发送get请求
- conn.setRequestMethod("GET"); // get要求大写,默认是get请求
- // 2.5设置请求超时时间
- conn.setConnectTimeout(5000);
- // 2.6获取服务器返回的状态码
- int code = 0;
- code = conn.getResponseCode();
- // 2.7如果code==200说明请求成功
- Log.d(TAG, code + "====================================");
- if (code == 200) {
- // 2.8获取服务器返回的数据,是以流的形式返回的,由于把流转换成字符串是很常见的操作
- // 所以抽出一个工具类Utils
- InputStream in = conn.getInputStream();
- // 2.9使用定义的工具类把in转换城String
- String content = StreamTools.readStream(in);
- tv_result.setText(content);
- }
- } catch (MalformedURLException e) {
- Toast.makeText(MainActivity.this, "协议未找到", Toast.LENGTH_SHORT).show();
- e.printStackTrace();
- } catch (IOException e) {
- Toast.makeText(MainActivity.this, "您输入的网址有误", Toast.LENGTH_SHORT).show();
- e.printStackTrace();
- }
-
- }
抛异常:Caused by: android.os.NetworkOnMainThreadException
解决方案:在OnCreate()方法加上两句:
方案一:
- StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
- StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());
方案二:
开启一个新线程运行,如下:
- new Thread() {
- public void run() {
- try {
- // 2.1获取源码路径
- String path = et_path.getText().toString().trim();
- // 2.2创建URL对象,指定我们要访问的网址(路径)
- URL url = new URL(path);
- // 2.3拿到httpurlconnection对象,用于发送或者接收数据
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- // 2.4设置发送get请求
- conn.setRequestMethod("GET"); // get要求大写,默认是get请求
- // 2.5设置请求超时时间
- conn.setConnectTimeout(5000);
- // 2.6获取服务器返回的状态码
- int code = 0;
- code = conn.getResponseCode();
- // 2.7如果code==200说明请求成功
- Log.d(TAG, code + "====================================");
- if (code == 200) {
- // 2.8获取服务器返回的数据,是以流的形式返回的,由于把流转换成字符串是很常见的操作
- // 所以抽出一个工具类Utils
- InputStream in = conn.getInputStream();
- // 2.9使用定义的工具类把in转换城String
- String content = StreamTools.readStream(in);
- tv_result.setText(content);
- }
- } catch (MalformedURLException e) {
- Toast.makeText(MainActivity.this, "协议未找到", Toast.LENGTH_SHORT).show();
- e.printStackTrace();
- } catch (IOException e) {
- Toast.makeText(MainActivity.this, "您输入的网址有误", Toast.LENGTH_SHORT).show();
- e.printStackTrace();
- }
- }
- }.start();
点击按钮出现结果,但是闪退,抛异常android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.说明在错误的线程更新UI。
Android中相关的view和控件操作都不是线程安全的,所以Android才会禁止在非UI线程更新UI,对于显式的非法操作,比如说直接在Activity里创建子线程,然后直接在子线程中操作UI等,Android会直接异常退出,并提示should run on UIThread之类的错误日志信息。而对于隐式的非法操作,App不会直接简单粗暴地异常退出,只是出现奇怪的结果,Only the original thread that created a view hierarchy can touch its views便是一个例子,字面意思是只有创建视图层次结构的原始线程才能操作它的View,明显是线程安全相关的。
总结点:
不能在主线程(UI线程)进行耗时的操作,比如连接网络,拷贝大数据,睡眠等操作。
比如连接谷歌网络。warning:java.net.SocketTimeoutException: connect timed out
只要主线程超时 info:The application may be doing too much work on its main thread.
在4.0之后谷歌强制要求连接网络不能在主线程进行访问
只有主线程(UI线程)才可以更新UI
=================================Talk is cheap, show me the code===============================
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。