zoukankan      html  css  js  c++  java
  • android学习笔记----网页源码查看器,图片查看器

    目录

    网页源码查看器:

    图片查看器:


     handler使用步骤
     1.在主线程定义了一个Handler
     private Handler handler = new Handler()
     2.使用handler会重写handler里面的handlerMessage方法
     public void handlerMessage(Message msg){}
     3.拿着我们在主线程创建的handler去子线程发消息
     handler.sendMessage(msg);
     4.handlerMessage方法就会执行,在这个方法里面去更新ui

    源码解读 Android 消息机制(Message MessageQueue Handler Looper)看这里:

    https://blog.csdn.net/u011240877/article/details/72892321

    网页源码查看器:

    以下是使用handler实现,AsyncTask实现的请见这里:https://github.com/liuchenyang0515/webcv_AsyncTask

    MainActivity.java

    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    
    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "MainActivity";
        private EditText et_path;
        private TextView tv_result;
    
        private Handler handler = new Handler() {
            // 这个方法是在主线程里面执行的
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                // 所以就可以在主线程里面更新ui了
                // 1.区分一下发送的是哪条消息
                switch (msg.what) {
                    case REQUESTSUCESS:
                        String content = (String) msg.obj;
                        tv_result.setText(content);
                        break;
                    case REQUESTNOTFOUND:
                        Toast.makeText(MainActivity.this, "请求资源不存在", Toast.LENGTH_SHORT).show();
                        break;
                    case REQUESTEXCEPTION:
                        Toast.makeText(MainActivity.this, "服务器忙,请稍候访问", Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        };
        private static final int REQUESTSUCESS = 0; // ctrl+shift+U切换大小写
        private static final int REQUESTNOTFOUND = 1; // 请求失败
        private static final int REQUESTEXCEPTION = 2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            et_path = (EditText) findViewById(R.id.et_path);
            tv_result = (TextView) findViewById(R.id.tv_result);
        }
    
        // 不能在主线程进行耗时的操作,比如连接网络,拷贝大数据,睡眠等操作。
        // 连接谷歌网络。warning:java.net.SocketTimeoutException: connect timed out
        // 只要主线程超时 info:The application may be doing too much work on its main thread.
        // 在4.0之后谷歌强制要求连接网络不能在主线程进行访问
        // 只有主线程(UI线程)才可以更新UI
        // 2.点击按钮进行查看,指定路径的源码
        public void click(View v) {
            // 只要不new Thread,全都属于主线程
            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
                            final String content = StreamTools.readStream(in);
                            // 2.9.0创建message对象
                            /*runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv_result.setText(content);
                                }
                            });*/
    
                            Message msg = Message.obtain();// 使用msg的静态方法可以减少对象的创建
                            msg.what = REQUESTSUCESS;
                            msg.obj = content;
                            // 2.9.1拿着我们创建的handler(助手) 告诉系统,我要更新ui
                            handler.sendMessage(msg);
                            // 发了一条消息,消息(msg)里把数据放到了msg里
                            // 接着handleMessage方法就会执行
                            /*// 更新UI的逻辑,写在这里会报错
                            tv_result.setText(content);*/
                        } else {
                            // 请求资源不存在  Toast就是一个view,相当于更新UI,不能在子线程更新UI,不能在子线程直接使用Toast
                            /*runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(MainActivity.this, "请求资源不存在", Toast.LENGTH_SHORT).show();
                                }
                            });*/
                            Message msg = Message.obtain();
                            msg.what = REQUESTNOTFOUND; // 代表哪条消息
                            handler.sendMessage(msg);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        /*runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "服务器忙,请稍候访问", Toast.LENGTH_SHORT).show();
                            }
                        });*/
                        Message msg = Message.obtain();
                        msg.what = REQUESTEXCEPTION; // 代表哪条消息
                        handler.sendMessage(msg);
                    }
                }
            }.start();
        }
    }
    

    运行效果:

    这里点击“查看”时为什么要选择另外开启一个线程?因为getResponseCode()会报错

    报错原因可以跳转到我的另一篇博客查看:https://blog.csdn.net/qq_34115899/article/details/81259485


    handler的作用是用来发消息和处理消息的
    Looper的作用是去消息队列里面取消息
    Looper是在主线程一创建Looper就有了

    还有一点:

    A toast is a view containing a quick little message for the user.

    Toast就是一个view,相当于更新UI,不能在子线程更新UI,不能在子线程直接使用Toast

    不管什么版本的手机,只要做耗时的操作(比如连接网络、拷贝大的数据等)就自己开一个子线程,获取数据后想要更新UI,就使用Handler就行。

    如果仅仅只是更新UI,那么用runOnUiThread就可以了。这是一个在android.app包下的Activity类里面的方法

    public final void runOnUiThread (Runnable action)

           在UI线程上运行指定的操作。如果当前线程是UI线程,则立即执行该操作。如果当前线程不是UI线程,则将操作发布到UI线程的事件队列。

    那Handler没用了吗?不是,有时候是可以通过Handler发送消息,携带数据这个时候就必须使用Handler了。

    用runOnUiThread操作如下,可以达到一样的效果。

    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "MainActivity";
        private EditText et_path;
        private TextView tv_result;
        
        private static final int REQUESTSUCESS = 0; // ctrl+shift+U切换大小写
        private static final int REQUESTNOTFOUND = 1; // 请求失败
        private static final int REQUESTEXCEPTION = 2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            et_path = (EditText) findViewById(R.id.et_path);
            tv_result = (TextView) findViewById(R.id.tv_result);
        }
    
    
        public void click(View v) {
            // 只要不new Thread,全都属于主线程
            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
                            final String content = StreamTools.readStream(in);
                            // 2.9.0创建message对象
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv_result.setText(content);
                                }
                            });
                        } else {
                            // 请求资源不存在  Toast就是一个view,相当于更新UI,不能在子线程更新UI,不能在子线程直接使用Toast
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(MainActivity.this, "请求资源不存在", Toast.LENGTH_SHORT).show();
                                }
                            });
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "服务器忙,请稍候访问", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                }
            }.start();
        }
    }

    图片查看器:

    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Base64;
    import android.util.Log;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.ImageView;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "MainActivity";
        private EditText et_path;
        private ImageView iv;
        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                Bitmap bitmap = (Bitmap) msg.obj;
                iv.setImageBitmap(bitmap);
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            // 1.找到我们关心的控件
            et_path = (EditText) findViewById(R.id.et_path);
            iv = (ImageView) findViewById(R.id.iv);
        }
    
        // 2.点击按钮进行查看指定路径的图片
        public void click(View view) {
            new Thread() {
                @Override
                public void run() {
                    try {
                        // 2.1获取图片路径
                        String path = et_path.getText().toString().trim();
                        // path不变,Base64加密写出的file路径,也就是改一下文件名字
                        File file = new File(getCacheDir(), Base64.encodeToString(path.getBytes(), Base64.DEFAULT));
                        Log.d(TAG, file.toString());// 可以看到全路径名,写出的file名已经加密
                        if (file.exists() && file.length() > 0) {
                            // 使用缓存的图片
                            Log.d(TAG, "使用缓存图片");
                            Bitmap cacheBitmap = BitmapFactory.decodeFile(file.getCanonicalPath());
                            // 把cacheBitmap显示到iv上
                            Message msg = Message.obtain();
                            msg.obj = cacheBitmap;
                            handler.sendMessage(msg);
                        } else {
                            Log.d(TAG, "第一次连接网络");
                            // 2.2创建URL对象
                            URL url = new URL(path);
                            // 2.3获取httpurlconnection
                            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                            // 2.4设置请求的方式
                            conn.setRequestMethod("GET");
                            // 2.5设置超时时间
                            conn.setConnectTimeout(5000);
                            // 2.6获取服务器返回的状态码
                            int code = conn.getResponseCode();
                            if (code == 200) {
                                // 2.7获取图片的数据,不管是什么数据(txt文本 图片数据)都是以流的形式返回
                                InputStream in = conn.getInputStream();
                                // 2.7.1缓存图片,谷歌提供了缓存目录
                                BufferedInputStream bis = new BufferedInputStream(in);
                                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
                                int len = -1;
                                byte[] buf = new byte[8192];
                                while ((len = bis.read(buf, 0, 8192)) != -1) {
                                    bos.write(buf, 0, len);
                                }
                                bis.close();
                                bos.close();
                                // 2.8通过位图工厂获取bitmap
                                //Bitmap bitmap = BitmapFactory.decodeStream(in);
                                Bitmap bitmap = BitmapFactory.decodeFile(file.getCanonicalPath());
                                // 2.9把bitmap显示到iv上
                                // 使用msg的静态方法可以减少对象的创建
                                Message msg = Message.obtain();
                                msg.obj = bitmap;
                                handler.sendMessage(msg);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    }
    

    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <EditText
            android:id="@+id/et_path"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="click"
            android:text="查看" />
    
        <ImageView
            android:id="@+id/iv"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </LinearLayout>

    运行结果:

    关于cache和files目录的区别可以看这里:

    https://blog.csdn.net/hxqneuq2012/article/details/53128572

    用runOnUiThread操作如下,可以达到一样的效果。

    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "MainActivity";
        private EditText et_path;
        private ImageView iv;
    /*    private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                Bitmap bitmap = (Bitmap) msg.obj;
                iv.setImageBitmap(bitmap);
            }
        };*/
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            // 1.找到我们关心的控件
            et_path = (EditText) findViewById(R.id.et_path);
            iv = (ImageView) findViewById(R.id.iv);
        }
    
        // 2.点击按钮进行查看指定路径的图片
        public void click(View view) {
            new Thread() {
                @Override
                public void run() {
                    try {
                        // 2.1获取图片路径
                        String path = et_path.getText().toString().trim();
                        // path不变,Base64加密写出的file路径,也就是改一下文件名字
                        File file = new File(getCacheDir(), Base64.encodeToString(path.getBytes(), Base64.DEFAULT));
                        Log.d(TAG, file.toString());// 可以看到全路径名,写出的file名已经加密
                        if (file.exists() && file.length() > 0) {
                            // 使用缓存的图片
                            Log.d(TAG, "使用缓存图片");
                            final Bitmap cacheBitmap = BitmapFactory.decodeFile(file.getCanonicalPath());
                            // 把cacheBitmap显示到iv上
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    iv.setImageBitmap(cacheBitmap);
                                }
                            });
                            /*Message msg = Message.obtain();
                            msg.obj = cacheBitmap;
                            handler.sendMessage(msg);*/
                        } else {
                            Log.d(TAG, "第一次连接网络");
                            // 2.2创建URL对象
                            URL url = new URL(path);
                            // 2.3获取httpurlconnection
                            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                            // 2.4设置请求的方式
                            conn.setRequestMethod("GET");
                            // 2.5设置超时时间
                            conn.setConnectTimeout(5000);
                            // 2.6获取服务器返回的状态码
                            int code = conn.getResponseCode();
                            if (code == 200) {
                                // 2.7获取图片的数据,不管是什么数据(txt文本 图片数据)都是以流的形式返回
                                InputStream in = conn.getInputStream();
                                // 2.7.1缓存图片,谷歌提供了缓存目录
                                BufferedInputStream bis = new BufferedInputStream(in);
                                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
                                int len = -1;
                                byte[] buf = new byte[8192];
                                while ((len = bis.read(buf, 0, 8192)) != -1) {
                                    bos.write(buf, 0, len);
                                }
                                bis.close();
                                bos.close();
                                // 2.8通过位图工厂获取bitmap
                                //Bitmap bitmap = BitmapFactory.decodeStream(in);
                                final Bitmap bitmap = BitmapFactory.decodeFile(file.getCanonicalPath());
                                // 2.9把bitmap显示到iv上
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        iv.setImageBitmap(bitmap);
                                    }
                                });
                                /*// 使用msg的静态方法可以减少对象的创建
                                Message msg = Message.obtain();
                                msg.obj = bitmap;
                                handler.sendMessage(msg);*/
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    }
    

    =================================Talk is cheap, show me the code===============================

    CSDN博客地址:https://blog.csdn.net/qq_34115899
  • 相关阅读:
    人月神话阅读笔记03
    学习进度十六
    计算最长英语链
    学习进度十五
    人月神话阅读笔记02
    找“水王”
    学习进度十四
    用户体验评价
    学习进度十三
    学习进度十二
  • 原文地址:https://www.cnblogs.com/lcy0515/p/10807883.html
Copyright © 2011-2022 走看看