mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-19 08:09:12 +01:00
only load partial conversation by default
Closes #4252 Fixes #3911 // FREEBIE
This commit is contained in:
committed by
Moxie Marlinspike
parent
4a3faf9086
commit
ae97495c47
@@ -20,17 +20,34 @@ import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.DataSetObserver;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.thoughtcrime.securesms.util.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* RecyclerView.Adapter that manages a Cursor, comparable to the CursorAdapter usable in ListView/GridView.
|
||||
*/
|
||||
public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
|
||||
private final Context context;
|
||||
public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
private final Context context;
|
||||
private final DataSetObserver observer = new AdapterDataSetObserver();
|
||||
|
||||
private Cursor cursor;
|
||||
private boolean valid;
|
||||
@VisibleForTesting final static int HEADER_TYPE = Integer.MIN_VALUE;
|
||||
@VisibleForTesting final static int FOOTER_TYPE = Integer.MIN_VALUE + 1;
|
||||
|
||||
private Cursor cursor;
|
||||
private boolean valid;
|
||||
private @Nullable View header;
|
||||
private @Nullable View footer;
|
||||
|
||||
private static class HeaderFooterViewHolder extends RecyclerView.ViewHolder {
|
||||
public HeaderFooterViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
protected CursorRecyclerViewAdapter(Context context, Cursor cursor) {
|
||||
this.context = context;
|
||||
@@ -39,18 +56,32 @@ public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHold
|
||||
valid = true;
|
||||
cursor.registerDataSetObserver(observer);
|
||||
}
|
||||
|
||||
setHasStableIds(false);
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
protected @NonNull Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public Cursor getCursor() {
|
||||
public @Nullable Cursor getCursor() {
|
||||
return cursor;
|
||||
}
|
||||
|
||||
public void setHeaderView(@Nullable View header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public void setFooterView(@Nullable View footer) {
|
||||
this.footer = footer;
|
||||
}
|
||||
|
||||
public boolean hasHeaderView() {
|
||||
return header != null;
|
||||
}
|
||||
|
||||
public boolean hasFooterView() {
|
||||
return footer != null;
|
||||
}
|
||||
|
||||
public void changeCursor(Cursor cursor) {
|
||||
Cursor old = swapCursor(cursor);
|
||||
if (old != null) {
|
||||
@@ -78,29 +109,50 @@ public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHold
|
||||
return oldCursor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return isActiveCursor() ? cursor.getCount() : 0;
|
||||
if (!isActiveCursor()) return 0;
|
||||
|
||||
return cursor.getCount()
|
||||
+ (hasHeaderView() ? 1 : 0)
|
||||
+ (hasFooterView() ? 1 : 0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return isActiveCursor() && cursor.moveToPosition(position)
|
||||
? cursor.getLong(cursor.getColumnIndexOrThrow("_id"))
|
||||
: 0;
|
||||
public final void onViewRecycled(ViewHolder holder) {
|
||||
if (!(holder instanceof HeaderFooterViewHolder)) {
|
||||
onItemViewRecycled((VH)holder);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void onBindViewHolder(VH viewHolder, @NonNull Cursor cursor);
|
||||
public void onItemViewRecycled(VH holder) {}
|
||||
|
||||
@Override public final ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
switch (viewType) {
|
||||
case HEADER_TYPE: return new HeaderFooterViewHolder(header);
|
||||
case FOOTER_TYPE: return new HeaderFooterViewHolder(footer);
|
||||
default: return onCreateItemViewHolder(parent, viewType);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract VH onCreateItemViewHolder(ViewGroup parent, int viewType);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void onBindViewHolder(VH viewHolder, int position) {
|
||||
moveToPositionOrThrow(position);
|
||||
onBindViewHolder(viewHolder, cursor);
|
||||
public final void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
|
||||
if (!isHeaderPosition(position) && !isFooterPosition(position)) {
|
||||
moveToPositionOrThrow(getCursorPosition(position));
|
||||
onBindItemViewHolder((VH)viewHolder, cursor);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void onBindItemViewHolder(VH viewHolder, @NonNull Cursor cursor);
|
||||
|
||||
@Override public int getItemViewType(int position) {
|
||||
moveToPositionOrThrow(position);
|
||||
if (isHeaderPosition(position)) return HEADER_TYPE;
|
||||
if (isFooterPosition(position)) return FOOTER_TYPE;
|
||||
moveToPositionOrThrow(getCursorPosition(position));
|
||||
return getItemViewType(cursor);
|
||||
}
|
||||
|
||||
@@ -125,6 +177,18 @@ public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHold
|
||||
return valid && cursor != null;
|
||||
}
|
||||
|
||||
private boolean isFooterPosition(int position) {
|
||||
return hasFooterView() && position == getItemCount() - 1;
|
||||
}
|
||||
|
||||
private boolean isHeaderPosition(int position) {
|
||||
return hasHeaderView() && position == 0;
|
||||
}
|
||||
|
||||
private int getCursorPosition(int position) {
|
||||
return hasHeaderView() ? position - 1 : position;
|
||||
}
|
||||
|
||||
private class AdapterDataSetObserver extends DataSetObserver {
|
||||
@Override
|
||||
public void onChanged() {
|
||||
|
||||
Reference in New Issue
Block a user