ContentResolver 가 어떻게 ContentProvider 를 이용하는지 살펴보자. 좀 더 포괄적인 글은 See Also 를 참고하자.
Provider 의 등록
provider 는 AndroidManifest.xml 에 등록하게 되어 있다.<application android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:theme="@android:style/Theme.NoTitleBar"> <!-----> ... <provider android:name="com.namh.utils.provider.ChartDatabaseProvider" android:authorities="com.muchart" android:exported="false" android:grantUriPermissions="true" android:label="ChartDatabaseProvider" android:readPermission="com.muchart.READ" android:writePermission="com.muchart.WRITE" /> </application>
이 등록한 Provider 를 사용하기 위해서 우리는 ContentResolver 를 사용한다. ContentResolver 내부에서 Provider 를 호출하는 구조이다.
이 ContentProvider 의 query() 를 이용하려고 하면 아래처럼 Resolver 를 통해서 query() 를 호출한다.
context.getContentResolver().query()아래 stack 과 source 들을 살펴보면, ContentResolver 가 ContentProvider 를 가져와서 그 ContentProvider.query() 를 호출하고 있다.
Stack trace
context.getContentResolver().query()
query():51, ChartDatabaseProvider {com.namh.utils.provider}
query():652, ContentProvider {android.content}
query():189, ContentProvider$Transport {android.content}
query():372, ContentResolver {android.content}
query():315, ContentResolver {android.content}
Source flow
// ContentResolover IContentProvider unstableProvider = acquireUnstableProvider(uri); ... qCursor = unstableProvider.query(uri, projection, selection, selectionArgs, sortOrder, remoteCancellationSignal); // ContentProvider$Transport enforceReadPermission(uri); ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder, CancellationSignal.fromTransport(cancellationSignal)); // MyContetProvider
acquireExistingProvider
그럼 이 ContentResolver 는 어떻게 우리가 등록한 ContentProvider 를 가져올까?acquireUnstableProvider 에서 시작해서 따라가 보면,에서 ActivityThread.mProviderMap 에 등록해 놓은 Provider 를 찾아서 가져오게 된다. key 는 auth 와 user id 로 결정된다. 자세한 것은 코드를 참고하자.
아마도, AndroidManifest.xml 에 등록하면 app 이 실행될 때 mProviderMap 에 등록되는 듯 하다.(확인 필요)
Stack trace
acquireProvider():4449, ActivityThread {android.app}
acquireUnstableProvider():2002, ContextImpl$ApplicationContentResolver {android.app}
acquireUnstableProvider():1101, ContentResolver {android.content}
query():356, ContentResolver {android.content}
Source flow
// ContentResolver public final IContentProvider acquireUnstableProvider(Uri uri) { if (!SCHEME_CONTENT.equals(uri.getScheme())) { // uri.getScheme() = "content" return null; } String auth = uri.getAuthority(); if (auth != null) { return acquireUnstableProvider(mContext, uri.getAuthority()); } return null; }
// ContextImpl$ApplicationContentResolver protected IContentProvider acquireUnstableProvider(Context c, String auth) { return mMainThread.acquireProvider(c, auth, mUser.getIdentifier(), false); } // ActivityThread public final IContentProvider acquireProvider(...){ final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable); if (provider != null) { return provider; } ... } public final IContentProvider acquireExistingProvider( Context c, String auth, int userId, boolean stable) { synchronized (mProviderMap) { final ProviderKey key = new ProviderKey(auth, userId); final ProviderClientRecord pr = mProviderMap.get(key); if (pr == null) { return null; } ... return provider; } }
See Also
- Content Providers & Content Resolvers | Android Design Patterns from http://www.androiddesignpatterns.com/2012/06/content-resolvers-and-content-providers.html
댓글 없음:
댓글 쓰기