Android 기본 요약: (11) ContentResolver 와 ContentProvider 가 어떻게 연결 되 었 는 지

응용 프로그램 은 하나의 완전한 응용 프로그램 입 니 다. 예 를 들 어 특정한 apk 는 하나의 응용 프로그램 에 대응 합 니 다. 그 안에 n 개의 Activity 가 포 함 될 수 있 습 니 다.
관련 류
froyo/frameworks/base/core/java/android/app/ApplicationContext.java
froyo/frameworks/base/core/java/android/app/ActivityThread.java
froyo/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

우리 가 휴대 전 화 를 시작 한 후에 activity, Activity Thread 를 시작 해 야 한다 면 Activity Manager Service 가 역할 을 발휘 하기 시 작 했 습 니 다. 여기 서 자세히 설명 하지 않 습 니 다.
우리 가 진정 으로 activity 를 시작 할 때, 우 리 는 현재 응용 프로그램의 응용 프로그램 Context 를 전송 합 니 다. 응용 프로그램 Context 실례 는 mContext Resolver 대상 을 가지 고 있 습 니 다. 이 대상 은 응용 프로그램 Context 의 내부 클래스 응용 프로그램 ContentResolver 에 대응 합 니 다.
activity 가 getContentResolver () 를 호출 할 때 현재 applicationContext 의 mContextResolver 를 실제 호출 합 니 다.
효과 도 를 살 펴 보 자.
검은색 의 계승 관계 로 인해 우 리 는 빨간색 의 호출 관 계 를 얻 을 수 있 습 니 다. 우 리 는 효과 도 를 보면 알 수 있 습 니 다. 그들 두 사람 은 어떻게 파일 을 건 너 뛰 어 직접 연결 되 었 는 지 알 수 있 습 니 다.그러면 우 리 는 많은 부분 을 절약 하고 시간 도 절약 할 수 있 습 니 다. 그러면 우리 도 실 수 를 하기 쉽 지 않 습 니 다. 그러면 우 리 는 우리 의 업무 효율 을 크게 향상 시 킬 것 입 니 다.
코드 세 션 은 다음 과 같 습 니 다:
Activity 에서 ContextWrapper 를 호출 하 는 방법
getContentResolver() {
	mBase.getContentResolver();
}

그리고 Application Context 로 호출 되 는 방법 입 니 다.
getContentResolver() {
	return mContentResolver;
}

Java 코드:
mContentResolve r = new ApplicationContentResolver(this, mainThread);
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
	public boolean releaseProvider(IContentProvider provider) {
		return mMainThread.releaseProvider(provider);
	}
	private final ActivityThread mMainThread;
}

mContentResolver. query () 를 실행 할 때 부모 클래스 ContentResolver 의 query () 를 호출 합 니 다.
public final Cursor query(Uri uri, String[] projection, String selection,
		String[] selectionArgs, String sortOrder) {
	IContentProvider provider = acquireProvider(uri);
	if (provider == null) {
		return null;
	}
	try {
		Cursor qCursor = provider.query(uri, projection, selection,
				selectionArgs, sortOrder);
		if (qCursor == null) {
			releaseProvider(provider);
			return null;
		}
		// CursorWrapperInner    
		return new CursorWrapperInner(qCursor, provider);
	} catch (RemoteException e) {
		releaseProvider(provider);
		return null;
	} catch (RuntimeException e) {
		releaseProvider(provider);
		throw e;
	}
}
public final IContentProvider acquireProvider(Uri uri) {
	if (!SCHEME_CONTENT.equals(uri.getScheme())) {
		return null;
	}
	String auth = uri.getAuthority();
	if (auth != null) {
		return acquireProvider(mContext, uri.getAuthority());
	}
	return null;
}

이 때 하위 클래스 인 스 턴 스 aquire Provider (Context, name) 를 호출 합 니 다.
mMainThread.acquireProvider (context, name);

Java 코드:
public final IContentProvider acquireProvider(Context c, String name) {
	IContentProvider provider = getProvider(c, name);
	if (provider == null)
		return null;
	IBinder jBinder = provider.asBinder(); //   binder  ,       。
	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;
}
private final IContentProvider getProvider(Context context, String name) {
	synchronized (mProviderMap) {
		final ProviderRecord pr = mProviderMap.get(name); // ActivityThread      Provider   
		if (pr != null) {
			return pr.mProvider;
		}
	}
	//       ,   , install,          。
	IActivityManager.ContentProviderHolder holder = null;
	try {
		holder = ActivityManagerNative.getDefault().getContentProvider(
				getApplicationThread(), name);
	} catch (RemoteException ex) {
	}
	if (holder == null) {
		Log.e(TAG, "Failed to find provider info for " + name);
		return null;
	}
	if (holder.permissionFailure != null) {
		throw new SecurityException("Permission 
				+ holder.permissionFailure + " required for provider
				+ name);
	}
	IContentProvider prov = installProvider(context, holder.provider,
			holder.info, true);
	// Log.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
	if (holder.noReleaseNeeded || holder.provider == null) {
		// We are not going to release the provider if it is an external
		//    ,      ,     
		//           。
		// Log.i(TAG, "*** NO RELEASE NEEDED");
		synchronized (mProviderMap) {
			mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(
					10000));
		}
	}
	return prov;
}


위의 코드 if (provider = = null) 뒤에 반환 값 이 있 습 니 다. 이 반환 값 은 반드시 비어 있어 야 합 니 다. 다른 것 을 쓰 지 마 세 요. 뒤의 판단 도 모두 비어 있다 고 판단 합 니 다. 그러면 우 리 는 contentResolver 와 contentProvider 가 연결 되 어 있 습 니 다.

좋은 웹페이지 즐겨찾기