MediaProvider批量插入数据源码分析

Android手机开机过程中,MediaScanner会对手机上的文件进行扫描,然后把文件信息保存到数据库中;或者,当手机导入大量图片文件时,MediaScanner也会执行同样的操作。这过程涉及数据库的增删改查操作,我们直观地知道批量插入数据可以提高效率,但是细节是怎样的呢?所以本文主要探究批量插入数据的源码。
在MediaScanner.scanDirectories()方法中可以看到,当开启ENABLE_BULK_INSERTS进行批量插入的时候,会创建MediaInserter对象,该对象负责缓存待插入的数据,数据达到设定的bufferSize后,调用ContentProvider进行批量插入。MediaInserter使用的数据结构如下所示,比如,对于这样的Uri: “content://media/external/images/media”,它指向external.db的images 视图,如果新增并扫描出来100张图片,那么对应的List就有100条数据,MediaInserter就是这样把待插入的数据缓存起来的,下一步就是调用MediaProvider插入这100条数据。

private final HashMap> mRowMap =
new HashMap>();

ContentProvider是个抽象类,它的bulkInsert方法默认实现是逐条插入数据的,需要批量插入逻辑就得覆写这个方法。

public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
	int numValues = values.length;
	for (int i = 0; i < numValues; i++) {
		insert(uri, values[i]); //逐条插入数据
	}
	return numValues;
}

所以从源码中找到MediaProvider的bulkInsert方法,如下,其实它就是开启事务、循环调用db.insert()方法、提交事务、结束事务的过程。

@Override
public int bulkInsert(Uri uri, ContentValues values[]) {
	//......
	synchronized (mDirectoryCache) {
		db.beginTransaction();
		try {
			int len = values.length;
			for (int i = 0; i < len; i++) {
				if (values[i] != null) {
					insertInternal(uri, match, values[i], notifyRowIds);
				}
			}
			numInserted = len;
			db.setTransactionSuccessful();
		} finally {
			db.endTransaction();
		}
	}
	//......
}

为什么使用事务可以提高批量插入数据的效率呢?我想是因为减少了磁盘的写入次数。实验测试使用事务批量插入确实节省许多时间。

你可能感兴趣的:(Android开发技术)