浅析Android MediaProvider之一
这段时间,我得一机会对 Android MediaProvider 进行了一番探究,奈何功力有限,不足以参悟其全部,简单记录下心得,已做“到此一游”之用。
认识新鲜事物,忌讳一头沉入细节,只见树木不见森林,宜先远远的看,从制高点一览全局,正所谓高屋建瓴。从事 Web Application 的时候,Web.xml可以帮助建立对系统运作流程的理解,对于 Android Application,则一样需要先找到这么一个制高点,这个制高点就是 AndroidManifest.xml。
统揽 AndroidManifest.xml,可以了解其由三个基础组件构成,分别是负责向外界提供数据访问的 MediaProvider,监听事件的 MediaScannerReceiver 和 实施扫描的 MediaScannerService。捏柿子要挑软的捏,看代码就挑短的先看,以免长篇累牍的代码让自己望而生畏,立马退避三舍,从代码量来看 MediaScannerReceiver 最小,这里就最先从 MediaScannerReceiver 来开始剖析。
简单梳理一下代码结构,整理出 MediaScannerReceiver 的类图如下,结合 AndroidManifest.xml 可以知道,在onReceive() 中,可以接收到三类 Intent,分别是:
![MediaScannerReceiver Class Diagram MediaScannerReceiver](http://www.poemcode.net/wp-content/uploads/2010/01/MediaScannerReceiver-Class-Diagram.png)
MediaScannerReceiver
- android.intent.action.BOOT_COMPLETED
- android.intent.action.MEDIA_MOUNTED
- android.intent.action.MEDIA_SCANNER_SCAN_FILE
这三个 Intent 均可以从 android.content.Intent 查看到定义,前两者顾名思义,比较好理解。第三个稍显复杂,据文档介绍其是请求 media scanner 扫描文件,并把它加入到 media database里,– 文件的路径就包含在 Intent.mData 中。
查看代码执行流程,可以发现对于第三个 Intent ,最后是进入到 scanFile,而前两者则是进入到scan,不同是是一个 internal,一个则是 external。但是最后殊途同归,统统进入到 MediaScannerService 处理。想来 BroadcastReceiver 也就是做个“传令官”的角色,所作的事情不多。
进入到 MediaScannerService 之后,根据其代码结构可整理出其类图如下。
![MediaScannerService Class Diagram MediaScannerService](http://www.poemcode.net/wp-content/uploads/2010/01/MediaScannerService-Class-Diagram.png)
MediaScannerService
乍一看,对于 MediaScannerService 实现 Runnable 感到不解,为什么要实现线程接口?为什么又要实现一个 Handler 的子类呢?这两者之间又是由着什么样的关系呢?
要理清第一个问题,需要从一行注释看起,在 onCreate 方法中看以这样的内容:
Start up the thread running the service. Note that we create a separate thread because the service normally runs in the process’s main thread, which we don’t want to block.
由此可以得知,实现 Runnable 的初衷是为了把扫描操作的动作放到主线程之外的线程上运行,因为如果是在主线程上运行扫描,那么最糟糕的结果就是阻塞了主线程。而根据 Handler 的文档,我们可以知道:
When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create.
主线程一旦阻塞,那么响应用户的动作就会非常缓慢,就会出现 ANR。但是在自己创建的线程上如何同主线程进行通信呢,这就需要使用到 Handler。根据 document 的解释,Handler 的用途有二:
(1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
这里我们显然是用到了第二个用途。到此第二个问题也就可以解释得通了。
好文章,应该讲得再多些,再仔细些就更好了。
讲的太简单了,能不能继续 源码的翻译版,能不能他为什么这么设计吗
谢谢提议