当前位置: 首页 > news >正文

Picasso源码阅读笔记九

CleanThread

Picasso在构造函数中,开启了CleanThread。CleanThread在后台运行,当内存不足时回收Action的Target并取消请求。

private static class CleanupThread extends Thread {
  private final ReferenceQueue<Object> referenceQueue; //弱引用的队列
  private final Handler handler; //主线程的Handler

  CleanupThread(ReferenceQueue<Object> referenceQueue, Handler handler) {
    this.referenceQueue = referenceQueue;
    this.handler = handler;
    setDaemon(true); //设置为守护线程
    setName(THREAD_PREFIX + "refQueue"); //设置线程名
  }

  @Override public void run() {
    Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND); //设置优先级
    // 不停查询弱引用队列中是否有可回收的引用
    while (true) {
      try {
        // 在Android 5.0以前,尽管没有了本地变量,但是remove()和obtainMessage()方法返回的结果还是保留在栈中。
        // 通过每隔1秒不停地循环来替换清除引用。
        RequestWeakReference<?> remove =
            (RequestWeakReference<?>) referenceQueue.remove(THREAD_LEAK_CLEANING_MS);
        Message message = handler.obtainMessage();
        if (remove != null) {
          // 给主线程发送REQUEST_GCED消息,让其清楚弱引用并取消请求。
          message.what = REQUEST_GCED;
          message.obj = remove.action;
          handler.sendMessage(message);
        } else {
          message.recycle();
        }
      } catch (InterruptedException e) {
        break;
      } catch (final Exception e) {
        handler.post(new Runnable() {
          @Override public void run() {
            throw new RuntimeException(e);
          }
        });
        break;
      }
    }
  }

  //当Picasso被关闭时会调用该方法停止该线程。
  void shutdown() {
    interrupt();
  }
}
复制代码
Stats

Stats负责记录内存缓存的状态。Stats在构造函数中启动一个HandlerThread,通过该线程接收消息,然后执行performXXX方法记录内存状态。

Stats(Cache cache) {
  this.cache = cache;
  // 这里的逻辑和Dispatcher的差不多。
  this.statsThread = new HandlerThread(STATS_THREAD_NAME, THREAD_PRIORITY_BACKGROUND);
  this.statsThread.start();
  Utils.flushStackLocalLeaks(statsThread.getLooper());
  this.handler = new StatsHandler(statsThread.getLooper(), this);
}

// 内存缓存读取成功
void performCacheHit() {
  cacheHits++;
}

// 内存缓存读取失败
void performCacheMiss() {
  cacheMisses++;
}

// 下载成功,下载数+1, 计算下载的总大小和平均下载大小
void performDownloadFinished(Long size) {
  downloadCount++;
  totalDownloadSize += size;
  averageDownloadSize = getAverage(downloadCount, totalDownloadSize);
}

// Bitmap解码,初始Bitmap数+1,计算初始Bitmap的总大小和平均Bitmap大小
void performBitmapDecoded(long size) {
  originalBitmapCount++;
  totalOriginalBitmapSize += size;
  averageOriginalBitmapSize = getAverage(originalBitmapCount, totalOriginalBitmapSize);
}

// Bitmap转化,转化Bitmap数+1,计算转化Bitmap的总大小和平均大小
void performBitmapTransformed(long size) {
  transformedBitmapCount++;
  totalTransformedBitmapSize += size;
  averageTransformedBitmapSize = getAverage(originalBitmapCount, totalTransformedBitmapSize);
}

// 返回内存状态的快照
StatsSnapshot createSnapshot() {
  return new StatsSnapshot(cache.maxSize(), cache.size(), cacheHits, cacheMisses,
      totalDownloadSize, totalOriginalBitmapSize, totalTransformedBitmapSize, averageDownloadSize,
      averageOriginalBitmapSize, averageTransformedBitmapSize, downloadCount, originalBitmapCount,
      transformedBitmapCount, System.currentTimeMillis());
}

private void processBitmap(Bitmap bitmap, int what) {
  // 不要把Bitmap发送给Handler,因为Bitmap可能在Handler处理前就被回收了。
  int bitmapSize = Utils.getBitmapBytes(bitmap);
  handler.sendMessage(handler.obtainMessage(what, bitmapSize, 0));
}
复制代码

相关文章:

  • 《Python编程快速上手》第8.9.2实践练习
  • Intel发布P4500、P4600 NVMe SSD:规格释疑
  • Gradle:Gradle入门
  • 超简便安装mysql
  • 个人开发—进度记录(十)
  • 【技巧】从键盘读入一串字符并输出
  • [转] Webpack 打包优化之体积篇
  • Java并发编程实战系列16之Java内存模型(JMM)
  • [20180224]expdp query 写法问题.txt
  • Android SDK Manager 和 AVD Manager使用
  • Ubuntu 开机挂载分区
  • SQL自动审核工具archer
  • django生产环节部署
  • 设计模式 代理模式(Proxy)
  • Python GIL(Global Interpreter Lock)
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  •  D - 粉碎叛乱F - 其他起义
  • git 常用命令
  • Java比较器对数组,集合排序
  • Java程序员幽默爆笑锦集
  • java概述
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • SpriteKit 技巧之添加背景图片
  • STAR法则
  • 给Prometheus造假数据的方法
  • 给第三方使用接口的 URL 签名实现
  • 关于Java中分层中遇到的一些问题
  • 关于使用markdown的方法(引自CSDN教程)
  • 聊聊flink的TableFactory
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 人脸识别最新开发经验demo
  • 山寨一个 Promise
  • 我的zsh配置, 2019最新方案
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • Semaphore
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • (BFS)hdoj2377-Bus Pass
  • (八)c52学习之旅-中断实验
  • (超详细)语音信号处理之特征提取
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (区间dp) (经典例题) 石子合并
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (一)UDP基本编程步骤
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • .apk文件,IIS不支持下载解决
  • .NET BackgroundWorker
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .NET delegate 委托 、 Event 事件
  • .NET Framework 4.6.2改进了WPF和安全性
  • .net 无限分类
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .NET企业级应用架构设计系列之应用服务器