在第一次使用,也就是刚得到cursor对象的时候,使用这两个方法都能得到一样的效果,就是把游标记录指定到第一行记录.
从源码中可以看出端倪
cursor是个接口,具体的实现类是AbstractCursor
abstract class AbstractCursor implements CrossProcessCursor
public interface CrossProcessCursor extends Cursor在AbstractCursor中实现了这两个方法:
@Override
public final boolean moveToFirst() {
return moveToPosition(0);
}
@Override
public final boolean moveToNext() {
return moveToPosition(mPos + 1);
}
可以看出,最终是调用了moveToPosition定位到绝对位置,而这里的mPos初始值是-1;
public AbstractCursor() {
mPos = -1;
}
这里再补充一下调用contentResolver的过程,一般是这样调用的getContext.getContentResolver 得到一个ContentResolve(抽象类)对象.
而getContentResolver这个方法是在具体的ContextImpl类中实现的.
@Override
public ContentResolver getContentResolver() {
return mContentResolver;
}
private ApplicationContentResolver mContentResolver;
ApplicationContentResolver是ContextImpl的内部类,
private static final class ApplicationContentResolver extends ContentResolver {
public ApplicationContentResolver(Context context, ActivityThread mainThread) {
super(context);
mMainThread = mainThread;
}
@Override
protected IContentProvider acquireProvider(Context context, String name) {
return mMainThread.acquireProvider(context, name);
}
@Override
protected IContentProvider acquireExistingProvider(Context context, String name) {
return mMainThread.acquireExistingProvider(context, name);
}
@Override
public boolean releaseProvider(IContentProvider provider) {
return mMainThread.releaseProvider(provider);
}
private final ActivityThread mMainThread;
}
执行contentResolver的query方法,会先去查找contentProvider在客户端的代理ContentProviderProxy(该类实现了IContentProvider接口,所以会直接返回这个接口)
public final Cursor query(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder) {
IContentProvider provider = acquireProvider(uri);
if (provider == null) {
return null;
}
try {
long startTime = SystemClock.uptimeMillis();
Cursor qCursor = provider.query(uri, projection, selection, selectionArgs, sortOrder);
if (qCursor == null) {
releaseProvider(provider);
return null;
}
// force query execution
qCursor.getCount();
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
// Wrap the cursor object into CursorWrapperInner object
return new CursorWrapperInner(qCursor, provider);
} catch (RemoteException e) {
releaseProvider(provider);
return null;
} catch(RuntimeException e) {
releaseProvider(provider);
throw e;
}
}
最终会调用ActivityThread的同名的方法,去通过跨进程获取provider的代理.跟进去看一下acquireProvider方法:
public final IContentProvider acquireProvider(Context c, String name) {
IContentProvider provider = getProvider(c, name);
if(provider == null)
return null;
IBinder jBinder = provider.asBinder();
synchronized(mProviderMap) {
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
if(prc == null) {
mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
} else {
prc.count++;
} //end else
} //end synchronized
return provider;
实际上拿到的这个IContentProvider对象,是binder服务端的具体实现类ContentProviderNative
该类中的query方法:
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sortOrder) throws RemoteException {
//TODO make a pool of windows so we can reuse memory dealers
CursorWindow window = new CursorWindow(false /* window will be used remotely */);
BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
IBulkCursor bulkCursor = bulkQueryInternal(
url, projection, selection, selectionArgs, sortOrder,
adaptor.getObserver(), window,
adaptor);
if (bulkCursor == null) {
return null;
}
return adaptor;
}
返回了一个BulkCursorToCursorAdatper对象,
public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor
public abstract class AbstractWindowedCursor extends AbstractCursor