import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.os.CancellationSignal;
import androidx.core.os.OperationCanceledException;
import androidx.loader.content.CursorLoader;
public class BundleCursorLoader extends CursorLoader {
ForceLoadContentObserver mObserver;
Uri mUri;
String[] mProjection;
Bundle mArgsBundle;
Cursor mCursor;
CancellationSignal mCancellationSignal;
public BundleCursorLoader(@NonNull Context context) {
super(context);
mObserver = new ForceLoadContentObserver();
}
public BundleCursorLoader(@NonNull Context context, @NonNull Uri uri, @Nullable String[] projection, @Nullable Bundle argsBundle) {
super(context);
mObserver = new ForceLoadContentObserver();
mUri = uri;
mProjection = projection;
mArgsBundle = argsBundle;
}
@Override
public Cursor loadInBackground() {
synchronized (this) {
if (isLoadInBackgroundCanceled()) {
throw new OperationCanceledException();
}
mCancellationSignal = new CancellationSignal();
}
try {
Cursor cursor = queryWithArgs(getContext().getContentResolver(),
mUri, mProjection, mArgsBundle,
mCancellationSignal);
if (cursor != null) {
try {
cursor.getCount();
cursor.registerContentObserver(mObserver);
} catch (RuntimeException ex) {
cursor.close();
throw ex;
}
}
return cursor;
}catch (Throwable ex){
ex.printStackTrace();
return null;
} finally {
synchronized (this) {
mCancellationSignal = null;
}
}
}
@Override
public void cancelLoadInBackground() {
synchronized (this) {
if (mCancellationSignal != null) {
mCancellationSignal.cancel();
}
}
}
@Override
public void deliverResult(Cursor cursor) {
if (isReset()) {
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();
}
}
@Override
protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}
@Override
protected void onStopLoading() {
cancelLoad();
}
@Override
public void onCanceled(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
@Override
protected void onReset() {
super.onReset();
onStopLoading();
if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
mCursor = null;
}
@NonNull
public Uri getUri() {
return mUri;
}
public void setUri(@NonNull Uri uri) {
mUri = uri;
}
@Nullable
public String[] getProjection() {
return mProjection;
}
public void setProjection(@Nullable String[] projection) {
mProjection = projection;
}
public Bundle getArgsBundle() {
return mArgsBundle;
}
public void setArgsBundle(Bundle argsBundle) {
mArgsBundle = argsBundle;
}
@Nullable
public static Cursor queryWithArgs(@NonNull ContentResolver resolver,
@NonNull Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable CancellationSignal cancellationSignal) {
final android.os.CancellationSignal cancellationSignalObj =
(android.os.CancellationSignal)
(cancellationSignal != null
? cancellationSignal.getCancellationSignalObject()
: null);
return resolver.query(uri, projection, queryArgs, cancellationSignalObj);
}
}