Skip to content

Instantly share code, notes, and snippets.

@koush
Last active January 12, 2024 18:00
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koush/6f2b9ef007e82d67f7effacef9f34ea8 to your computer and use it in GitHub Desktop.
Save koush/6f2b9ef007e82d67f7effacef9f34ea8 to your computer and use it in GitHub Desktop.
ArrayList<WeakReference<ContentObserver>> observers = new ArrayList<WeakReference<ContentObserver>>();
public void loadCursor(final BetterCursorAdapter adapter, final Uri uri, final String[] projection, final String selection, final String[] selectionArgs, final String sortOrder) {
final FutureCallback<BetterCursorAdapter> callback = new FutureCallback<BetterCursorAdapter>() {
@Override
public void onCompleted(Exception e, BetterCursorAdapter result) {
if (e != null)
return;
View view = getView();
if (view == null)
return;
getRecyclerView().setEmptyView(view.findViewById(R.id.empty));
view.findViewById(R.id.loading).setVisibility(View.GONE);
onLoaded();
}
};
final ContentObserver observer = new ContentObserver(handler) {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
if (getActivity() == null)
return;
adapter.changeCursor(getActivity(), uri, projection, selection, selectionArgs, sortOrder)
.setCallback(callback);
}
};
getActivity().getContentResolver().registerContentObserver(uri, false, observer);
observers.add(new WeakReference<ContentObserver>(observer));
adapter.changeCursor(getActivity(), uri, projection, selection, selectionArgs, sortOrder)
.setCallback(callback);
}
@Override
public void onDestroy() {
for (WeakReference<ContentObserver> ref: observers) {
ContentObserver observer = ref.get();
if (observer != null)
getActivity().getContentResolver().unregisterContentObserver(observer);
}
super.onDestroy();
}
package com.koushikdutta.cast;
import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import com.koushikdutta.async.future.Future;
import com.koushikdutta.async.future.HandlerFuture;
import java.util.ArrayList;
import java.util.List;
/**
* Created by koush on 3/2/14.
*/
public abstract class BetterCursorAdapter extends RecyclerView.Adapter<BetterCursorAdapter.BetterCursorViewHolder> {
protected final Handler handler = new Handler(Looper.getMainLooper());
ArrayList<ContentValues> currentItems = new ArrayList<>();
OnItemClickListener onClick;
OnItemLongClickListener onLongClick;
private int cursorSet;
public ArrayList<ContentValues> getItems() {
return new ArrayList<>(currentItems);
}
@Override
public void onBindViewHolder(BetterCursorAdapter.BetterCursorViewHolder holder, int position) {
holder.values = currentItems.get(position);
holder.position = position;
holder.bind(holder, holder.values);
}
public ContentValues getItem(int position) {
return currentItems.get(position);
}
@Override
public abstract BetterCursorAdapter.BetterCursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType);
@Override
public int getItemCount() {
return currentItems.size();
}
public void clear() {
currentItems.clear();
notifyDataSetChanged();
}
public void addAll(List<ContentValues> add) {
currentItems.addAll(add);
notifyDataSetChanged();
}
protected void flush(final int c, final ArrayList<ContentValues> values, final boolean clear) {
handler.post(new Runnable() {
@Override
public void run() {
if (c != cursorSet)
return;
if (clear)
clear();
addAll(values);
}
});
}
synchronized private void swapCursor(final Cursor c, final HandlerFuture<BetterCursorAdapter> ret, final Exception fe) {
final int currentCursor = ++this.cursorSet;
if (c == null) {
ret.setComplete(fe, this);
return;
}
new Thread() {
@Override
public void run() {
try {
ArrayList<ContentValues> values = new ArrayList<ContentValues>();
while (currentCursor == cursorSet && c.moveToNext()) {
ContentValues cv = new ContentValues();
DatabaseUtils.cursorRowToContentValues(c, cv);
values.add(cv);
}
flush(currentCursor, values, true);
}
catch (Exception e) {
// cursor can get closed
}
finally {
c.close();
ret.setComplete(fe, BetterCursorAdapter.this);
}
}
}.start();
}
public Future<BetterCursorAdapter> changeCursor(final Activity context, final Uri uri, final String[] projection,
final String selection, final String[] selectionArgs, final String sortOrder) {
final HandlerFuture<BetterCursorAdapter> ret = new HandlerFuture<BetterCursorAdapter>();
final ContentResolver resolver = context.getContentResolver();
new Thread() {
@Override
public void run() {
final Runnable query = new Runnable() {
@Override
public void run() {
Cursor c;
Exception ex;
try {
c = resolver.query(uri, projection, selection, selectionArgs, sortOrder);
if (c == null)
throw new Exception("cursor null");
ex = null;
}
catch (Exception e) {
c = null;
ex = e;
}
final Cursor cursor = c;
final Exception fe = ex;
handler.post(new Runnable() {
@Override
public void run() {
swapCursor(cursor, ret, fe);
}
});
}
};
query.run();
}
}.start();
return ret;
}
public interface OnItemClickListener {
void onClick(View view, ContentValues values, int position);
}
public interface OnItemLongClickListener {
boolean onLongClick(View view, ContentValues values, int position);
}
public void setOnClickListener(OnItemClickListener listener) {
onClick = listener;
}
public void setOnLongClickListener(OnItemLongClickListener listener) {
onLongClick = listener;
}
public abstract class BetterCursorViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
ContentValues values;
int position;
public BetterCursorViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (onClick != null)
onClick.onClick(v, values, position);
}
@Override
public boolean onLongClick(View v) {
if (onLongClick == null)
return false;
return onLongClick.onLongClick(v, values, position);
}
public abstract void bind(BetterCursorViewHolder holder, ContentValues values);
}
}
https://github.com/Germanunkol/OgreOculusSample/blob/master/WTFP-LICENSE.txt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment