从服务端下载图片(主线程阻塞,消息队列机制,从网上下载图片)

看着大神的技术各种高大上,自己怎么能落后呢?
好好加油吧,骚年。对昨天的从服务端下载图片进行复习。

主线程阻塞:

1,UI停止刷新,应用无法响应用户的操作。
2,耗时操作不应该放在主线程中。
3,ANR
application not responding
应用无响应异常
主线程阻塞时间过长,就会抛出ANR
4,主线程又称为是UI线程,因为只有在主线程,才能刷新UI

消息队列机制

这里接触到了消息队列机制:
主线程创建的时候,系统会同时创建消息队列对象(MessageQueue)和消息轮询器对象(Looper)。
消息轮询器的作用是:不停的检测消息队列中是否有消息(Message),
消息队列一旦有消息,轮询器就会把消息对象传给消息处理器(Handler),
消息处理器就会调用handlerMessage方法来处理这条消息,handlerMessage方法运行在主线程,所以可以刷新UI

总结:只要有消息队列有消息,handlerMessage方法就会调用,
子线程如果需要刷新UI,只要往队列中发送一条消息,触发handlerMessage方法即可,,子线程使用处理器对象的sendMessage方法发送消息。

实验的代码:
package com.example.xm.imageview;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

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 {
    ImageView iv;
    Handler handler = new Handler(){
        //此方法在主线程中调用,可以用来刷新UI
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 1:
                    //把位图对象显示在imageview
                    iv.setImageBitmap((Bitmap) msg.obj);
                    break;
                case 0:
                    Toast.makeText(MainActivity.this,"请求失败",Toast.LENGTH_LONG).show();
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv = (ImageView) findViewById(R.id.iv);
    }
public void click(View view){
        //下载图片
        /*
        1,确定网站,1,确定网站,,原来模拟器默认把127.0.0.1和localhost当做本身了,
        在模拟器上可以用10.0.2.2代替127.0.0.1和localhost,另外如果是在局域网环境可以用
         192.168.0.x或者192.168.1.x(根据具体配置)连接本机,这样应该就不会报错了
        */
        final String path = "http://10.0.2.2:8080/liu.png";

        final File file = new File(getCacheDir(),getFileName(path));

        //判断缓存中是否存在
        if (file.exists()){
            //如果缓存中存在,就从缓存中取
            System.out.println("从缓存中取出");
            Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
            iv.setImageBitmap(bm);

        }else{
            //如果缓存不存在,就从网上下载
            System.out.println("从网上下载");
            Thread t = new Thread(){
                @Override
                public void run() {
                    try {
                        //2,把网址封装成一个url对象
                        URL url = new URL(path);
                        //3,获取客户端和服务端的连接对象,此时ahi没有建立连接
                        HttpURLConnection connection =(HttpURLConnection) url.openConnection();
                        //4,对连接进行初始化
                        //设置请求方法,注意是大写
                        connection.setRequestMethod("GET");
                        //设置连接超时
                        connection.setConnectTimeout(5000);
                        //设置读取超时
                        connection.setReadTimeout(5000);
                        //5,发送请求,与服务器建立连接
                        connection.connect();
                        //如果响应码是200,说明请求成功
                        if (connection.getResponseCode() == 200){
                            //获取服务器响应头中的流,流中的数据就是客户端请求的数据
                            InputStream is = connection.getInputStream();

                            //读取服务器返回流中的数据,然后写入到本地的文件中,缓存起来
                            FileOutputStream fos = new FileOutputStream(file);
                            byte [] b = new byte[10024];
                            int len = 0;
                            while ((len = is.read(b)) != -1){
                                fos.write(b,0,len);
                            }
                            fos.close();

                            //读取出流中的数据,并构成位图
                            //Bitmap bm = BitmapFactory.decodeStream(is);
                            Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());


                            Message message = new Message();
                            //消息对象可以携带数据,这里把bm放在message.obj中
                            message.obj = bm;
                            //把消息发送至主线程的消息队列中
                            message.what =1;
                            handler.sendMessage(message);
                        }else {
                            Message message = handler.obtainMessage();
                            message.what = 0;
                            handler.sendMessage(message);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            t.start();

        }

    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值