关于getResponseCode()出现的一些错误

2023-05-06 18:56:52 浏览数 (1)

代码语言:javascript复制
// 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()方法加上两句:

方案一:

代码语言:javascript复制
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());

方案二:

开启一个新线程运行,如下:

代码语言:javascript复制
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

0 人点赞