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

来源:互联网 发布:红外线空调遥控器软件 编辑:程序博客网 时间:2024/05/09 12:16

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

主线程阻塞:

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();        }    }
0 0
原创粉丝点击