我们这里主要讲本地sd卡的数据,pisaca看情况后续再作分析。

数据操作设计的类包括:CacheService,MediaFeed,LocalDataSource,DiskCache,MediaItem, MediaSet,MediaClustering。

数据操作包括几个方面:寻找媒体源(图片、视频),cache媒体源,将cache数据导出,将cache的媒体渲染到屏幕。

首先是找图片或者视频:

1. 如果当前cache文件不存在,或者当前cache文件记录的语言、国家和变量代码与系统的不一致的场景时,首先将所有cache文件(index和chunk文件)删除,接着将语言、国家和变量代码写入local-album-cachechunk0的文件中。

2. 启动一个线程,寻找图片或者视频,并将相册信息cache。

3. 再启动一个线程,将图片缩略图化,并cache。

4. 如果上一次还有一部分数据cache,执行步骤2和3。

5. 如果这一次有新的媒体文件需要cache,启动一个线程,将新的媒体文件cache。再执行步骤3。

关键的代码如下:

@Overrideprotected void onHandleIntent(final Intent intent) {Log.i(TAG, "CacheService, onHandleIntent, Starting CacheService");if (Environment.getExternalStorageState() == Environment.MEDIA_BAD_REMOVAL) {sAlbumCache.deleteAll();putLocaleForAlbumCache(Locale.getDefault());}Locale locale = getLocaleForAlbumCache();if (locale != null && locale.equals(Locale.getDefault())) {// The cache is in the same locale as the system locale.if (!isCacheReady(false)) {// The albums and their items have not yet been cached, we need// to run the service.Log.i(TAG, "CacheService, onHandleIntent, start new cache thread");startNewCacheThread();} else {Log.i(TAG, "CacheService, onHandleIntent, start new cache thread for dirty sets");startNewCacheThreadForDirtySets();}} else {// The locale has changed, we need to regenerate the strings.Log.i(TAG, "CacheService, onHandleIntent, delete all");sAlbumCache.deleteAll();putLocaleForAlbumCache(Locale.getDefault());startNewCacheThread();}if (intent.getBooleanExtra("checkthumbnails", false)) {Log.i(TAG, "CacheService, onHandleIntent, start new thumbnail thread");startNewThumbnailThread(this);} else {final Thread existingThread = THUMBNAIL_THREAD.getAndSet(null);if (existingThread != null) {existingThread.interrupt();}}}

先看这个函数:

private static final Locale getLocaleForAlbumCache() {Log.i(TAG, "CacheService, getLocaleForAlbumCache");final byte[] data = sAlbumCache.get(ALBUM_CACHE_LOCALE_INDEX, 0);if (data != null && data.length > 0) {ByteArrayInputStream bis = new ByteArrayInputStream(data);DataInputStream dis = new DataInputStream(bis);try {String country = Utils.readUTF(dis);if (country == null)country = "";String language = Utils.readUTF(dis);if (language == null)language = "";String variant = Utils.readUTF(dis);if (variant == null)variant = "";final Locale locale = new Locale(language, country, variant);dis.close();bis.close();return locale;} catch (IOException e) {// Could not read locale in cache.Log.i(TAG, "Error reading locale from cache.");return null;}}return null;}

我们看到 sAlbumCache这个变量,这个变量的定义是这样的:

public static final DiskCache sAlbumCache = new DiskCache("local-album-cache");

我们来看看DiskCache的构造函数做了什么?

public DiskCache(String cacheDirectoryName) {String cacheDirectoryPath = CacheService.getCachePath(cacheDirectoryName);// Create the cache directory if needed.File cacheDirectory = new File(cacheDirectoryPath);if (!cacheDirectory.isDirectory() && !cacheDirectory.mkdirs()) {Log.e(TAG, "Unable to create cache directory " + cacheDirectoryPath);}mCacheDirectoryPath = cacheDirectoryPath;loadIndex();}
public static final String getCachePath(final String subFolderName) {return Environment.getExternalStorageDirectory() + "/Android/data/com.luowei.media/cache/" + subFolderName;}

原来如此,在sd卡建立了一个目录/Android/data/com.luowei.media/cache/local-album-cache。

建立目录后呢?

private void loadIndex() {final String indexFilePath = getIndexFilePath();try {// Open the input stream.final FileInputStream fileInput = new FileInputStream(indexFilePath);final BufferedInputStream bufferedInput = new BufferedInputStream(fileInput, 1024);final DataInputStream dataInput = new DataInputStream(bufferedInput);// Read the header.final int magic = dataInput.readInt();//4final int version = dataInput.readInt();//4boolean valid = true;if (magic != INDEX_HEADER_MAGIC) {Log.e(TAG, "Index file appears to be corrupt (" + magic + " != " + INDEX_HEADER_MAGIC + "), " + indexFilePath);valid = false;}if (valid && version != INDEX_HEADER_VERSION) {// Future versions can implement upgrade in this case.Log.e(TAG, "Index file version " + version + " not supported");valid = false;}if (valid) {mTailChunk = dataInput.readShort();//2}// Read the entries.if (valid) {// Parse the index file body into the in-memory map.final int numEntries = dataInput.readInt();//4mIndexMap = new LongSparseArray<Record>(numEntries);synchronized (mIndexMap) {for (int i = 0; i < numEntries; ++i) {final long key = dataInput.readLong();//8final int chunk = dataInput.readShort();//2final int offset = dataInput.readInt();//4final int size = dataInput.readInt();//4final int sizeOnDisk = dataInput.readInt();//4final long timestamp = dataInput.readLong();//8mIndexMap.append(key, new Record(chunk, offset, size, sizeOnDisk, timestamp));}}}dataInput.close();if (!valid) {deleteAll();}} catch (FileNotFoundException e) {// If the file does not exist the cache is empty, so just continue.} catch (IOException e) {Log.e(TAG, "Unable to read the index file " + indexFilePath);} finally {if (mIndexMap == null) {mIndexMap = new LongSparseArray<Record>();}}}

首先找索引文件,索引文件路径是什么?

 private String getIndexFilePath() {return mCacheDirectoryPath + INDEX_FILE_NAME;}

具体路径是 sd卡下/Android/data/com.luowei.media/cache/local-album-cacheindex。如果文件不存在,就只做一件事,将mIndexMap初始化;如果文件存在,读取文件头,如果文件头是00 00 CA FE 00 00 00 02这个格式,说明是标准的索引文件,继续分析此文件,将数据写入mIndexMap映射表。

接着继续分析getLocaleForAlbumCache函数,sAlbumCache.get做了什么?

public byte[] get(long key, long timestamp) {// Look up the record for the given key.Record record = null;synchronized (mIndexMap) {record = mIndexMap.get(key);}if (record != null) {// Read the chunk from the file.if (record.timestamp != timestamp) {return null;}try {RandomAccessFile chunkFile = getChunkFile(record.chunk);if (chunkFile != null) {byte[] data = new byte[record.size];chunkFile.seek(record.offset);chunkFile.readFully(data);return data;}} catch (Exception e) {Log.e(TAG, "Unable to read from chunk file");}}return null;}

如果mIndexMap没有ALBUM_CACHE_LOCALE_INDEX这个key的数据,返回null;如果有,接着比较。如果记录的时间戳也不一致,返回null。那getChunkFile又有什么呢?

private RandomAccessFile getChunkFile(int chunk) {RandomAccessFile chunkFile = null;synchronized (mChunkFiles) {chunkFile = mChunkFiles.get(chunk);}if (chunkFile == null) {final String chunkFilePath = mCacheDirectoryPath + CHUNK_FILE_PREFIX + chunk;Log.i(TAG, "DiskCache, chunkFilePath:"+chunkFilePath);try {chunkFile = new RandomAccessFile(chunkFilePath, "rw");} catch (FileNotFoundException e) {Log.e(TAG, "Unable to create or open the chunk file " + chunkFilePath);}synchronized (mChunkFiles) {mChunkFiles.put(chunk, chunkFile);}}return chunkFile;}

mChunkFiles也是一个chunk映射表,local-album-cache对应的chunk文件路径对应为/Android/data/com.luowei.media/cache/local-album-cachechunk0。如果chunk文件不存在,需要建立这个文件,同时将这个文件加入mChunkFiles映射表。
 
回到getLocaleForAlbumCache这个函数,发现这个chunk文件的头记录语言、地区和变量代码。再返回onHandleIntent函数,如果getLocaleForAlbumCache取回的代码是空的或者跟本机的代码不一致,就需要做三件事情:

1. 将/Android/data/com.luowei.media/cache/local-album-cache目录下所有文件,其实这里面有个bug,请读者自行发现;

2. 创建chunk和index文件,并将语言、地区和变量代码写入chunk文件,这就是putLocaleForAlbumCache函数所作的事情;

3. 开启新的cache线程:startNewCacheThread。

galler3d的源码分析——数据来源相关推荐

  1. android+小米文件管理器源码,[MediaStore]小米文件管理器android版源码分析——数据来源...

    打开小米的文件管理器,我们很快会看到如下图所示的界面: 其中,会把各种文件分类显示.并且显示出每种文件的个数. 这是怎么做到的呢?当然不是每次启动都查询sdcard和应用程序data目录文件啦,那样实 ...

  2. 【VUE】源码分析 - 数据劫持的基本原理

    tips:本系列博客的代码部分(示例等除外),均出自vue源码内容,版本为2.6.14.但是为了增加易读性,会对不相关内容做选择性省略.如果大家想了解完整的源码,建议自行从官方下载.https://g ...

  3. 风讯dotNETCMS源码分析—数据存取篇

    前几天突然对CMS感兴趣,就去下载了风讯dotNETCMS源码.当前版本是dotnetcms1.0 sp5免费版,风讯的官方主页上可以下载. 用Visual Studio 2008打开后,初步分析了它 ...

  4. Nginx源码分析--数据对齐posix_memalign和memalign函数

    posix_memalign函数() /*  * 背景:  *      1)POSIX 1003.1d  *      2)POSIX 标明了通过malloc( ), calloc( ), 和 re ...

  5. Beanstalk源码分析--数据结构设计

    概述 beanstalk是多年前使用过的一个分布式任务队列,通过C实现,十分高效.和Redis(默认)的事件驱动框架一样,都是通过异步的epoll来实现,所以,能够高效的处理大量请求. 但不知什么原因 ...

  6. ConcurrentHashMap的源码分析-数据迁移阶段的实现分析

    通过分配好迁移的区间之后,开始对数据进行迁移.在看这段代码之前,先来了解一下原理 synchronized (f) {//对数组该节点位置加锁,开始处理数组该位置的迁移工作 if (tabAt(tab ...

  7. 你真的了解lambda吗?一文让你明白lambda用法与源码分析

    本文作者: cmlanche 本文链接: http://www.cmlanche.com/2018/07/22/lambda用法与源码分析/ 转载来源:cmlanche.com 用法 示例:最普遍的一 ...

  8. Memcached源码分析 - 内存存储机制Slabs(5)

    Memcached源码分析 - 网络模型(1) Memcached源码分析 - 命令解析(2) Memcached源码分析 - 数据存储(3) Memcached源码分析 - 增删改查操作(4) Me ...

  9. Influxdb源码分析-TSM Engine WAL

    前言 influxdb安装和使用 influxdb概念详解1 influxdb概念详解2 influxdb源码编译 influxdb启动分析 influxdb源码分析-meta部分 infludb源码 ...

最新文章

  1. uint8_t uint16_t uint32_t uint64_t 解析
  2. 科学家发现鱼会数学,5以内的加减法难不倒它,网友:要多吃鱼了
  3. Java编译分类:前端编译和后端编译
  4. C++设计模式——适配器模式(对象适配器、类适配器)
  5. 使用 Mesos 管理虚拟机
  6. u-boot 详细介绍 .
  7. Sql Server之旅——第十二站 对锁的初步认识
  8. python,pytorch:读取,保存,显示图片
  9. dir函数_PHP dir()函数与示例
  10. axios学习笔记(一):学习HTTP相关的技术知识点
  11. vue 在js 文件中使用store_vue 如何在 .js 文件引入 store
  12. UTF-8 Unicode ANSI网页编码的区别
  13. Adblock 插件规则语法实现B 站动态黑名单 - 隐藏特定用户的图文动态
  14. windows下的git配置,puttygen.exe生成公钥
  15. 海康8700等联网网关通过GB28181接入LiveGBS流媒体服务实现web端无插件直播
  16. Latex文档中 插入符号和编号
  17. 分享:淘宝客完全开源程序。
  18. 给在读研究生的一封信
  19. Linux-lsxxx
  20. leetcode之雪糕的最大数量(C++)

热门文章

  1. datahub文档_实现datahub
  2. 计算机系军训口号四句霸气,军训口号四句霸气「推荐」
  3. cleanmymac要不要下载装机?好不好用
  4. 面经——1,万得电话面试
  5. python网站安全(一): XSS注入
  6. 攻防世界—APK-逆向2
  7. “云周边服务商”逸云科技携手英特尔,推进云计算的落地应用
  8. python的优点有哪些-Python语言的特点有哪些?
  9. java变长参数_Java可变长度参数
  10. 职称考试计算机基础知识,中级职称计算机考试题「附答案」