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
  • 相关阅读:
    linux内核分析第八周理解进程调度时机跟踪分析进程调度与进程切换的过程
    linux内核分析第六周分析Linux内核创建一个新进程的过程
    Linux内核学习总结
    Linux内核分析第一周通过分析汇编代码理解计算机是如何工作的
    linux内核分析第五周分析system_call中断处理过程
    linux内核分析第三周跟踪分析Linux内核的启动过程
    转载:Understanding WPF Application Lifecycle
    Quick Sort 快速排序
    C#中的Immutable(不变的)
    一个lock和一个deadlock的例子
  • 原文地址:https://www.cnblogs.com/lcy0515/p/10807883.html
Copyright © 2011-2022 走看看