ContentProvider없이 CursorLoader 사용
Android SDK 설명서에 따르면 startManagingCursor()
메서드가 더 이상 사용되지 않습니다.
이 방법은 더 이상 사용되지 않습니다. 대신 LoaderManager와 함께 새 CursorLoader 클래스를 사용하십시오. Android 호환성 패키지를 통해 이전 플랫폼에서도 사용할 수 있습니다. 이 방법을 사용하면 활동이 활동의 수명주기를 기반으로 지정된 커서의 수명주기를 관리 할 수 있습니다. 즉, 활동이 중지되면 주어진 Cursor에서 자동으로 deactivate ()를 호출하고 나중에 다시 시작할 때 requery ()를 호출합니다. 활동이 파괴되면 모든 관리 커서가 자동으로 닫힙니다. HONEYCOMB 이상을 대상으로하는 경우 대신 getLoaderManager ()를 통해 사용할 수있는 LoaderManager를 사용하는 것이 좋습니다.
그래서 저는 CursorLoader
. 하지만 생성자에서 URI가 필요할 때 사용자 지정 CursorAdapter
및 사용하지 않고 어떻게 사용할 수 있습니까?ContentProvider
CursorLoader
콘텐츠 공급자가 필요없는 간단한 CursorLoader 를 작성했습니다 .
import android.content.Context;
import android.database.Cursor;
import android.support.v4.content.AsyncTaskLoader;
/**
* Used to write apps that run on platforms prior to Android 3.0. When running
* on Android 3.0 or above, this implementation is still used; it does not try
* to switch to the framework's implementation. See the framework SDK
* documentation for a class overview.
*
* This was based on the CursorLoader class
*/
public abstract class SimpleCursorLoader extends AsyncTaskLoader<Cursor> {
private Cursor mCursor;
public SimpleCursorLoader(Context context) {
super(context);
}
/* Runs on a worker thread */
@Override
public abstract Cursor loadInBackground();
/* Runs on the UI thread */
@Override
public void deliverResult(Cursor cursor) {
if (isReset()) {
// An async query came in while the loader is stopped
if (cursor != null) {
cursor.close();
}
return;
}
Cursor oldCursor = mCursor;
mCursor = cursor;
if (isStarted()) {
super.deliverResult(cursor);
}
if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
oldCursor.close();
}
}
/**
* Starts an asynchronous load of the contacts list data. When the result is ready the callbacks
* will be called on the UI thread. If a previous load has been completed and is still valid
* the result may be passed to the callbacks immediately.
* <p/>
* Must be called from the UI thread
*/
@Override
protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}
/**
* Must be called from the UI thread
*/
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
@Override
public void onCanceled(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
mCursor = null;
}
}
AsyncTaskLoader
수업 만 필요합니다 . Android 3.0 이상 또는 호환성 패키지와 함께 제공되는 것입니다.
나는 또한와ListLoader
호환되는을 썼으며LoadManager
일반 java.util.List
컬렉션 을 검색하는 데 사용됩니다 .
콘텐츠 공급자 대신 데이터베이스 클래스를 사용하는 고유 한 로더를 작성하십시오. 가장 쉬운 방법은 CursorLoader
호환성 라이브러리에서 클래스 의 소스를 가져 와서 공급자 쿼리를 자신의 db 도우미 클래스에 대한 쿼리로 바꾸는 것입니다.
The SimpleCursorLoader is a simple solution, however it doesn't support updating the loader when the data changes. CommonsWare has a loaderex library that adds a SQLiteCursorLoader and supports re-query on data changes.
https://github.com/commonsguy/cwac-loaderex
A third option would be to simply override loadInBackground
:
public class CustomCursorLoader extends CursorLoader {
private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();
@Override
public Cursor loadInBackground() {
Cursor cursor = ... // get your cursor from wherever you like
if (cursor != null) {
// Ensure the cursor window is filled
cursor.getCount();
cursor.registerContentObserver(mObserver);
}
return cursor;
}
};
This will also take care of re-querying your cursor when the database changes.
Only caveat: You'll have to define another observer, since Google in it's infinite wisdom decided to make theirs package private. If you put the class into the same package as the original one (or the compat one) you can actually use the original observer. The observer is a very lightweight object and isn't used anywhere else, so this doesn't make much of a difference.
The third option proposed by Timo Ohr, together with the comments by Yeung, provide the simplest answer (Occam's razor). Below is an example of a complete class that works for me. There are two rules for using this class.
- Extend this abstract class and implement methods getCursor() and getContentUri().
Any time that the underlying database changes (e.g., after an insert or delete), make sure to call
getContentResolver().notifyChange(myUri, null);
where myUri is the same one returned from your implementation of method getContentUri().
Here is the code for the class that I used:
package com.example.project;
import android.content.Context;
import android.database.Cursor;
import android.content.CursorLoader;
import android.content.Loader;
public abstract class AbstractCustomCursorLoader extends CursorLoader
{
private final Loader.ForceLoadContentObserver mObserver = new Loader.ForceLoadContentObserver();
public AbstractCustomCursorLoader(Context context)
{
super(context);
}
@Override
public Cursor loadInBackground()
{
Cursor cursor = getCursor();
if (cursor != null)
{
// Ensure the cursor window is filled
cursor.getCount();
cursor.registerContentObserver(mObserver);
}
cursor.setNotificationUri(getContext().getContentResolver(), getContentUri());
return cursor;
}
protected abstract Cursor getCursor();
protected abstract Uri getContentUri();
}
참고URL : https://stackoverflow.com/questions/7182485/cursorloader-usage-without-contentprovider
'program story' 카테고리의 다른 글
RegEx-가변 길이의 숫자 일치 (0) | 2020.08.07 |
---|---|
문자열에 대한 해시 함수 (0) | 2020.08.07 |
ASP.Net Core의 JSON 직렬화 / 역 직렬화 (0) | 2020.08.07 |
"git pull"이 자동으로 숨겨지고 보류중인 변경 사항을 팝 할 수 있습니까? (0) | 2020.08.07 |
Spark DataFrame에 상수 열을 추가하는 방법은 무엇입니까? (0) | 2020.08.07 |