一、源码查看器

1.定义一个EditView用来输入网址,一个Button点击后查看,一个TextView来显示查看的源码

2.找到控件

et_path = (EditText) findViewById(R.id.et_path);
tv_result = (TextView) findViewById(R.id.tv_result);

3.定义将流转换为String的工具类

public class StreamTools {

    //把InputStream转换成String
    public static String  readStream(InputStream in) throws Exception{
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int len = -1;
        byte[] buffer = new byte[1024];
        while ((len=in.read(buffer))!=-1){
            baos.write(buffer,0,len);
        }
        in.close();
        String content = new String(baos.toByteArray());
        return content;
    }
}

4.定义点击事件

public void click(View v){
    try {
        //【2.1】获取路径
        String path = et_path.getText().toString().trim();
        if(path != null){
            //【2.2】创建URL对象指定我们要访问的网址(路径)
            URL url =new URL(path);
            //【2.3】拿到HttpURLConnection对象  用于发送或接受数据
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //【2.4】设置发送get请求
            conn.setRequestMethod("GET");       //GET大写
            //【2.5】设置超时时间
            conn.setConnectTimeout(5000);       //5秒钟
            //【2.6】获取服务器返回的状态码
            int code = conn.getResponseCode();
            //【2.7】如果code=200 说明请求成功
            if(code == 200){
                //【2.8】获取服务器返回的数据,是以流的形式返回的
                InputStream in = conn.getInputStream();//由于把流转换成字符串是一个非常常见的操作,所以抽成一个工具类(utils)
                //【2.9】使用我们定义的工具类把in转换成String
                String content = StreamTools.readStream(in);
                //【2.9.1】把流里面的数据展示到textview上
                tv_result.setText(content);
            }else {
                Toast.makeText(MainActivity.this,"请求失败",Toast.LENGTH_SHORT).show();
            }
        }else {
            Toast.makeText(MainActivity.this,"路径不能为空",Toast.LENGTH_SHORT).show();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

5.在Android4.0之后,这个程序是不能正常运行的,看三、四

二、ScrollView控件(可滚动)

1.只能有一个孩子

2.若想有多个孩子可用一个布局包含多个控件,然后把布局放到ScrollView中

三、主线程(UI线程)

1.ANR异常(Application not response):应用无响应

2.如果在主线程中进行了耗时的操作(比如连接网络、拷贝大的数据、Thread.sleep() )

3.在android4.0以后,谷歌强制要求连接网络不能放到主线程中

4.避免ANR,可以把耗时的操作放到子线程中,自己再创建一个线程

5.只有主线程才能更新ui

四、消息机制(handler)

0.使用步骤

      1)在主线程定义一个Handler

      2)使用hadler会重写handler里面的handleMessage方法

      3)拿着在主线程中创建的handler去子线程发消息

      4)handlemessage方法就会执行   在这个方法里面去更新ui

1.在主线程中创建一个handler(助手)并重写handleMessage()方法

private Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
    }
};

2.在点击事件中创建子线程,把链接网络的代码放到子线程中

public void click(View v){
    //【2.0】创建一个子线程
    new Thread(){public void run(){
            
    }}.start();
}

3.把读取的数据放到Message对象中传到主线程

if(code == 200){
    //【2.8】获取服务器返回的数据,是以流的形式返回的
    InputStream in = conn.getInputStream();//由于把流转换成字符串是一个非常常见的操作,所以抽成一个工具类(utils)
    //【2.9】使用我们定义的工具类把in转换成String
    String content = StreamTools.readStream(in);
                        
    //创建Message对象
    Message msg = new Message();
    msg.obj = content;
    handler.sendMessage(msg);//发了一条消息,把数据放到msg中,handlerMessage()方法就会执行

}

4.在主线程中更新ui

private Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        String content = (String) msg.obj;
        tv_result.setText(content);
    }
};

 5.原理

      handler的作用是用来发消息和处理消息的

      Looper 的作用是去消息队列里面取消息

      Looper主线程一创建 Looper就有了

6.规则,不管什么版本的手机,只要做耗时的操作(比如联网、拷贝大数据等等)就自己开一个子线程,获取数据后想要更新ui,就用Handler就可以了

五、图片查看器

1.把TextView控件换为ImageView控件

2.使用handler发消息为

InputStream in = conn.getInputStream();            //获取流
Bitmap bitmap = BitmapFactory.decodeStream(in);    //流转换为Bitmap
Message msg = Message.obtain();                    //获取Message对象
msg.obj = bitmap;
handler.sendMessage(msg);                          //发送消息

3.更新ui

Bitmap bitmap=(Bitmap) msg.obj;
iv.setImageBitmap(bitmap);

六、对图片进行缓存

1.创建一个文件存放图片

File file = new File(getCacheDir(),"text.png");

2.判断文件是否存在

if(file.exists() && file.length()>0){                //判断文件是否存在

    Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());    //如果存在,在文件中读取

    Message msg = Message.obtain();
    msg.obj = bitmap;
    handler.sendMessage(msg);
}

3.不存在获取图片放到文件中,然后读取文件

else {
    path = et_path.getText().toString().trim();
    URL url = new URL(path);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setConnectTimeout(5000);
    int code = conn.getResponseCode();
    if(code == 200){
        InputStream in = conn.getInputStream();
        
        //从流中读取然后写入文件
        FileOutputStream fos = new FileOutputStream(file);
        int len = -1;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer))!=-1){
            fos.write(buffer,0,len);
        }
        fos.close();
        in.close();
    
        //在文件中读取图片
        Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());

        Message msg = Message.obtain();
        msg.obj = bitmap;
        handler.sendMessage(msg);
    }
}

七、cache和filedir区别

用户可以在应用设置内清空缓存(cache) ,若存放图片等不是很重要的数据用cache,存放重要数据信息用filedir

八、runOnUIThread()

1.这句api,不论在什么位置上调用action都运行在UI线程里

runOnUiThread(new Runnable() {        //runOnUiThread接收的为Runable对象
    @Override
    public void run() {
        iv.setImageBitmap(bitmap);
    }
});

2.如果仅仅就是更新ui,就用runOnUiThread这个api就可以

  有的时候可以通过Handler发送消息,携带数据,这时候必须得用handler

九、postDelayed

//两个参数,第一个Runnable对象,第二个时间
new Handler().postDelayed(new Runnable(){        //多事时间后开始执行run方法
    @Override
    public void run(){
    
    }
},5000);