Android权威编程指南笔记 第二十六章 Looper, Handle, HandleThread(未完)

第二十六章 Looper, Handle, HandleThread

Looper

  • Looper可以对应一个或多个handler, handler可以对应一个或多个message.Looper拥有着整个message队列

Message

  • message的属性
  1. what: 标志消息的int型代码
  2. obj: 随消息发送的对象
  3. target: 所需设置的目标handler

Handler

  • 要处理消息及消息指定的任务, 就需要handler实例.
  1. 初始化handler, 并定义其在得到消息队列中的下载消息后应该执行的任务
    由于onLooperPrepared方法在Looper首次检查消息队列之前调用, 故onLooperPrepared是初始化handler的好地方.
        mRequestHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) { //在这里对消息进行处理
                if (msg.what == MESSAGE_DOWNLOAD){
                    T target = (T) msg.obj;
                    Log.i(TAG, "Got a request for URL: " + mRequestMap.get(target));
                    handleRequest(target);
                }
            }
        };
    private void handleRequest(final T target) {
        try{
            final String url = mRequestMap.get(target);

            if (url == null){
                return;
            }

            byte[] bitmapBytes = new FlickrFetchr().getUrlBytes(url);
            final Bitmap bitmap = BitmapFactory
                    .decodeByteArray(bitmapBytes, 0, bitmapBytes.length);
            Log.i(TAG, "Bitmap created");

            mResponseHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (!Objects.equals(mRequestMap.get(target), url) ||
                            mHasQuit){
                        return;
                    }

                    mRequestMap.remove(target);
                    mThumbnailDownloadListener.onThumbnailDownloaded(target, bitmap);
                }
            });

        } catch (IOException e) {
            Log.e(TAG, "Error downloading image", e);
        }
    }
  1. 创建消息
    1.从公共 回收池里获取消息, 而不用去反复创建新的message对象
    handle.obtainMessage(int what, Object obj)
    2..sendToTarget()将自身自动设置为目标handle. 不应手动设置消息的目标handler
            mRequestHandler.obtainMessage(MESSAGE_DOWNLOAD, target)
                    //what属性是用来标志下载请求消息
                    //obj属性是泛型参数对象
                    //取得消息,并自动设置目标Handler
                    .sendToTarget();//发送给目标handler

创建并启动后台线程

  1. 创建继承HandlerThread的类
  2. 在前台的onCreate()中实例化该类并启动它
  3. 调用HandlerThead.getLooper()方法
        mThumbnailDownloader = new ThumbnailDownloader<>();
        mThumbnailDownloader.start();//创建并启动线程
        mThumbnailDownloader.getLooper();//此方法返回与此线程关联的Looper。
        //如果线程启动,则此方法将直到Looper初始化后才能启用, 这样可以避免后续操作中, handler为空引发的异常
  • 前台往后台发送消息
  1. 在handler初始化完成的情况下
  2. 在上面提到的, 传递给Handler, 让其创建消息. 每次有新的任务, 就使用 handler.obtainMessage(int what, Object obj).sendToTarget();的方法
  • 后台发送给前台
    handleMessage(msg)中, 每次处理完都可以去实现向前台发送消息, 让其处理相关事物
  1. 在前台创建handler实例, 该handler与主线程的looper相关联.
  2. 将该handler传递到后台中, 然后利用handler.post(Runnable)方法. Runnable中的run法会直接执行
  3. 主线程可以实现相关的回调接口
            mResponseHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (!Objects.equals(mRequestMap.get(target), url) ||
                            mHasQuit){
                        return;
                    }

                    mRequestMap.remove(target);// ViewHolder是回收利用的
                    mThumbnailDownloadListener.onThumbnailDownloaded(target, bitmap);
                }
            });
        mThumbnailDownloader.setThumbnailDownloadListener(
                new ThumbnailDownloader.ThumbnailDownloaderListener<PhotoHolder>() {
            @Override
            public void onThumbnailDownloaded(PhotoHolder photoHolder, Bitmap bitmap) {
                if (bitmap != null){
                    Drawable drawable = new BitmapDrawable(getResources(), bitmap);
                    photoHolder.bindDrawable(drawable);
                }else{
                    photoHolder.bind();
                }

            }
        });

清理后台进程

  1. onDestory()中清理后台进程: 使用handlerThread.quit();
    @Override
    public void onDestroy() {
        super.onDestroy();
        mThumbnailDownloader.quit(); //结束线程,否则会一直运行下去
        Log.i(TAG, "Background thread destroyed");
    }
  1. 由于屏幕旋转, PhotoHolder视图失效, handlerThread会挂起, 从而会引发异常.
    故要在onDestoryView()中清除相关请求
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mThumbnailDownloader.clearQueue();
    }
    public void clearQueue(){
        mRequestHandler.removeMessages(MESSAGE_DOWNLOAD);//删除消息队列中代码为“what”的所有挂起消息
        mRequestMap.clear();
    }

相关小记

  • ConcurrentHashMap是一个线程安全的hashMap
    ConcurrentHashMap.put(K key, V value);
    ConcurrentHashMap.remove(Object key)

挑战练习

  1. 使用picasso库实现下载功能
  2. Android引入StrictMode帮助开发者探测代码问题
  3. 预加载与缓存
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值