-
Notifications
You must be signed in to change notification settings - Fork 134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fine grained notification for RecyclerViewAdapter #83
Changes from 5 commits
7f8e368
b3a90d6
45980f5
4f88f71
8bb149d
624f7cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,14 @@ | ||
## 2.0.0 (YYYY-MM-DD) | ||
|
||
### Breaking changes | ||
|
||
* Removed `RealmBaseAdapter(@Nonnull Context context, @Nullable OrderedRealmCollection<T> data)`. | ||
* Removed `RealmRecyclerViewAdapter(@NonNull Context context, @Nullable OrderedRealmCollection<T> data, boolean autoUpdate)`. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that removing |
||
### Enhancements | ||
|
||
* Added fine grained notification support to `RealmRecyclerViewAdapter` (requires Realm Java version >= v3.0.0). | ||
|
||
## 1.5.0 | ||
|
||
### Deprecated | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,10 +16,8 @@ | |
|
||
package io.realm; | ||
|
||
import android.content.Context; | ||
import android.support.annotation.NonNull; | ||
import android.support.annotation.Nullable; | ||
import android.view.LayoutInflater; | ||
import android.widget.BaseAdapter; | ||
|
||
/** | ||
|
@@ -33,48 +31,18 @@ | |
* closed. Trying to access Realm objects will at this point also result in a {@code IllegalStateException}. | ||
*/ | ||
public abstract class RealmBaseAdapter<T extends RealmModel> extends BaseAdapter { | ||
@Nullable | ||
@Deprecated | ||
protected LayoutInflater inflater; | ||
@Nullable | ||
protected OrderedRealmCollection<T> adapterData; | ||
@Nullable | ||
@Deprecated | ||
protected Context context; | ||
private final RealmChangeListener<? extends BaseRealm> listener; | ||
|
||
@Deprecated | ||
public RealmBaseAdapter(@NonNull Context context, @Nullable OrderedRealmCollection<T> data) { | ||
if (data != null && !data.isManaged()) | ||
throw new IllegalStateException("Only use this adapter with managed list, " + | ||
"for un-managed lists you can just use the BaseAdapter"); | ||
//noinspection ConstantConditions | ||
if (context == null) { | ||
throw new IllegalArgumentException("Context cannot be null"); | ||
} | ||
this.context = context; | ||
this.adapterData = data; | ||
this.inflater = LayoutInflater.from(context); | ||
this.listener = new RealmChangeListener<BaseRealm>() { | ||
@Override | ||
public void onChange(BaseRealm results) { | ||
notifyDataSetChanged(); | ||
} | ||
}; | ||
|
||
if (data != null) { | ||
addListener(data); | ||
} | ||
} | ||
private final RealmChangeListener<Object> listener; | ||
|
||
public RealmBaseAdapter(@Nullable OrderedRealmCollection<T> data) { | ||
if (data != null && !data.isManaged()) | ||
throw new IllegalStateException("Only use this adapter with managed list, " + | ||
"for un-managed lists you can just use the BaseAdapter"); | ||
this.adapterData = data; | ||
this.listener = new RealmChangeListener<BaseRealm>() { | ||
this.listener = new RealmChangeListener<Object>() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree. I think it's OK to use raw type ( |
||
@Override | ||
public void onChange(BaseRealm results) { | ||
public void onChange(Object results) { | ||
notifyDataSetChanged(); | ||
} | ||
}; | ||
|
@@ -86,23 +54,27 @@ public void onChange(BaseRealm results) { | |
|
||
private void addListener(@NonNull OrderedRealmCollection<T> data) { | ||
if (data instanceof RealmResults) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check for instance of RealmCollectionObservable instead? and collapse the two if sections? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ignore this after removing this interface |
||
RealmResults realmResults = (RealmResults) data; | ||
realmResults.realm.handlerController.addChangeListenerAsWeakReference(listener); | ||
RealmResults<T> results = (RealmResults<T>) data; | ||
//noinspection unchecked | ||
results.addChangeListener((RealmChangeListener) listener); | ||
} else if (data instanceof RealmList) { | ||
RealmList realmList = (RealmList) data; | ||
realmList.realm.handlerController.addChangeListenerAsWeakReference(listener); | ||
RealmList<T> list = (RealmList<T>) data; | ||
//noinspection unchecked | ||
list.addChangeListener((RealmChangeListener)listener); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need a space after cast |
||
} else { | ||
throw new IllegalArgumentException("RealmCollection not supported: " + data.getClass()); | ||
} | ||
} | ||
|
||
private void removeListener(@NonNull OrderedRealmCollection<T> data) { | ||
if (data instanceof RealmResults) { | ||
RealmResults realmResults = (RealmResults) data; | ||
realmResults.realm.handlerController.removeWeakChangeListener(listener); | ||
RealmResults<T> results = (RealmResults<T>) data; | ||
//noinspection unchecked | ||
results.removeChangeListener((RealmChangeListener)listener); | ||
} else if (data instanceof RealmList) { | ||
RealmList realmList = (RealmList) data; | ||
realmList.realm.handlerController.removeWeakChangeListener(listener); | ||
RealmList<T> list = (RealmList<T>) data; | ||
//noinspection unchecked | ||
list.removeChangeListener((RealmChangeListener)listener); | ||
} else { | ||
throw new IllegalArgumentException("RealmCollection not supported: " + data.getClass()); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,63 +16,57 @@ | |
|
||
package io.realm; | ||
|
||
import android.content.Context; | ||
import android.support.annotation.NonNull; | ||
import android.support.annotation.Nullable; | ||
import android.support.v7.widget.RecyclerView; | ||
import android.view.LayoutInflater; | ||
|
||
/** | ||
* The RealmBaseRecyclerAdapter class is an abstract utility class for binding RecyclerView UI elements to Realm data. | ||
* <p> | ||
* This adapter will automatically handle any updates to its data and call notifyDataSetChanged() as appropriate. | ||
* Currently there is no support for RecyclerView's data callback methods like notifyItemInserted(int), notifyItemRemoved(int), | ||
* notifyItemChanged(int) etc. | ||
* It means that, there is no possibility to use default data animations. | ||
* This adapter will automatically handle any updates to its data and call {@code notifyDataSetChanged()}, | ||
* {@code notifyItemInserted()}, {@code notifyItemRemoved()} or {@code notifyItemRangeChanged(} as appropriate. | ||
* <p> | ||
* The RealmAdapter will stop receiving updates if the Realm instance providing the {@link OrderedRealmCollection} is | ||
* closed. | ||
* | ||
* @param <T> type of {@link RealmModel} stored in the adapter. | ||
* @param <VH> type of RecyclerView.ViewHolder used in the adapter. | ||
* @param <S> type of RecyclerView.ViewHolder used in the adapter. | ||
*/ | ||
public abstract class RealmRecyclerViewAdapter<T extends RealmModel, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { | ||
public abstract class RealmRecyclerViewAdapter<T extends RealmModel, S extends RecyclerView.ViewHolder> | ||
extends RecyclerView.Adapter<S> { | ||
|
||
@Nullable | ||
@Deprecated | ||
protected LayoutInflater inflater; | ||
@Nullable | ||
@Deprecated | ||
protected Context context; | ||
private final boolean hasAutoUpdates; | ||
private final RealmChangeListener listener; | ||
private final OrderedRealmCollectionChangeListener listener; | ||
@Nullable | ||
private OrderedRealmCollection<T> adapterData; | ||
|
||
@Deprecated | ||
public RealmRecyclerViewAdapter(@NonNull Context context, @Nullable OrderedRealmCollection<T> data, boolean autoUpdate) { | ||
if (data != null && !data.isManaged()) | ||
throw new IllegalStateException("Only use this adapter with managed list, " + | ||
"for un-managed lists you can just use the BaseAdapter"); | ||
//noinspection ConstantConditions | ||
if (context == null) { | ||
throw new IllegalArgumentException("Context can not be null"); | ||
} | ||
|
||
this.context = context; | ||
this.adapterData = data; | ||
this.inflater = LayoutInflater.from(context); | ||
this.hasAutoUpdates = autoUpdate; | ||
|
||
// Right now don't use generics, since we need maintain two different | ||
// types of listeners until RealmList is properly supported. | ||
// See https://github.com/realm/realm-java/issues/989 | ||
this.listener = hasAutoUpdates ? new RealmChangeListener() { | ||
private OrderedRealmCollectionChangeListener createListener() { | ||
return new OrderedRealmCollectionChangeListener() { | ||
@Override | ||
public void onChange(Object results) { | ||
notifyDataSetChanged(); | ||
public void onChange(Object collection, OrderedCollectionChangeSet changeSet) { | ||
// null Changes means the async query returns the first time. | ||
if (changeSet == null) { | ||
notifyDataSetChanged(); | ||
return; | ||
} | ||
// For deletions, the adapter has to be notified in reverse order. | ||
OrderedCollectionChangeSet.Range[] deletions = changeSet.getDeletionRanges(); | ||
for (int i = deletions.length - 1; i >= 0; i--) { | ||
OrderedCollectionChangeSet.Range range = deletions[i]; | ||
notifyItemRangeRemoved(range.startIndex, range.length); | ||
} | ||
|
||
OrderedCollectionChangeSet.Range[] insertions = changeSet.getInsertionRanges(); | ||
for (OrderedCollectionChangeSet.Range range : insertions) { | ||
notifyItemRangeInserted(range.startIndex, range.length); | ||
} | ||
|
||
OrderedCollectionChangeSet.Range[] modifications = changeSet.getChangeRanges(); | ||
for (OrderedCollectionChangeSet.Range range : modifications) { | ||
notifyItemRangeChanged(range.startIndex, range.length); | ||
} | ||
} | ||
} : null; | ||
}; | ||
} | ||
|
||
public RealmRecyclerViewAdapter(@Nullable OrderedRealmCollection<T> data, boolean autoUpdate) { | ||
|
@@ -85,12 +79,7 @@ public RealmRecyclerViewAdapter(@Nullable OrderedRealmCollection<T> data, boolea | |
// Right now don't use generics, since we need maintain two different | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we need to |
||
// types of listeners until RealmList is properly supported. | ||
// See https://github.com/realm/realm-java/issues/989 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is the above assumption still valid? realm/realm-java#989 is closed now? |
||
this.listener = hasAutoUpdates ? new RealmChangeListener() { | ||
@Override | ||
public void onChange(Object results) { | ||
notifyDataSetChanged(); | ||
} | ||
} : null; | ||
this.listener = hasAutoUpdates ? createListener() : null; | ||
} | ||
|
||
@Override | ||
|
@@ -177,26 +166,27 @@ public void updateData(@Nullable OrderedRealmCollection<T> data) { | |
|
||
private void addListener(@NonNull OrderedRealmCollection<T> data) { | ||
if (data instanceof RealmResults) { | ||
RealmResults realmResults = (RealmResults) data; | ||
RealmResults<T> results = (RealmResults<T>) data; | ||
//noinspection unchecked | ||
realmResults.addChangeListener(listener); | ||
results.addChangeListener(listener); | ||
} else if (data instanceof RealmList) { | ||
RealmList realmList = (RealmList) data; | ||
RealmList<T> list = (RealmList<T>) data; | ||
//noinspection unchecked | ||
realmList.realm.handlerController.addChangeListenerAsWeakReference(listener); | ||
list.addChangeListener(listener); | ||
} else { | ||
throw new IllegalArgumentException("RealmCollection not supported: " + data.getClass()); | ||
} | ||
} | ||
|
||
private void removeListener(@NonNull OrderedRealmCollection<T> data) { | ||
if (data instanceof RealmResults) { | ||
RealmResults realmResults = (RealmResults) data; | ||
realmResults.removeChangeListener(listener); | ||
RealmResults<T> results = (RealmResults<T>) data; | ||
//noinspection unchecked | ||
results.removeChangeListener(listener); | ||
} else if (data instanceof RealmList) { | ||
RealmList realmList = (RealmList) data; | ||
RealmList<T> list = (RealmList<T>) data; | ||
//noinspection unchecked | ||
realmList.realm.handlerController.removeWeakChangeListener(listener); | ||
list.removeChangeListener(listener); | ||
} else { | ||
throw new IllegalArgumentException("RealmCollection not supported: " + data.getClass()); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,15 +4,18 @@ buildscript { | |
ext { | ||
sdkVersion = 25 | ||
buildTools = '25.0.0' | ||
realmVersion = '2.1.1' | ||
supportLibraryVersion = '25.0.0' | ||
realmVersion = '3.0.0-SNAPSHOT' | ||
supportLibraryVersion = '25.2.0' | ||
} | ||
|
||
repositories { | ||
jcenter() | ||
maven { | ||
url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' | ||
} | ||
} | ||
dependencies { | ||
classpath 'com.android.tools.build:gradle:2.2.2' // Android Build tools | ||
classpath 'com.android.tools.build:gradle:2.2.3' // Android Build tools | ||
classpath 'ch.netzwerg:gradle-release-plugin:1.2.0' // Manage Release tags / versioning | ||
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' // Allows you to install AAR's locally | ||
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:4.0.1' // OJO integration | ||
|
@@ -22,11 +25,19 @@ buildscript { | |
} | ||
} | ||
|
||
// Don't cache SNAPSHOT (changing) dependencies. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remember to remove when releasing |
||
configurations.all { | ||
resolutionStrategy.cacheChangingModulesFor 0, 'seconds' | ||
} | ||
|
||
allprojects { | ||
group = 'io.realm' | ||
version = file("${rootDir}/version.txt").text.trim(); | ||
repositories { | ||
jcenter() | ||
maven { | ||
url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,19 +15,30 @@ | |
*/ | ||
package io.realm.examples.adapters.model; | ||
|
||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
import io.realm.RealmObject; | ||
|
||
public class TimeStamp extends RealmObject { | ||
public class Counter extends RealmObject { | ||
public static final String FIELD_COUNT = "count"; | ||
|
||
private static AtomicInteger integerCounter = new AtomicInteger(0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why static? can't we use a member counter with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this is in order to have a global counter while the app is running so the list will have ever increasing numbers. |
||
|
||
public static final String TIMESTAMP = "timeStamp"; | ||
private int count; | ||
|
||
private String timeStamp; | ||
public int getCount() { | ||
return count; | ||
} | ||
|
||
public void setCount(int count) { | ||
this.count = count; | ||
} | ||
|
||
public String getTimeStamp() { | ||
return timeStamp; | ||
public String getCountString() { | ||
return Integer.toString(count); | ||
} | ||
|
||
public void setTimeStamp(String timeStamp) { | ||
this.timeStamp = timeStamp; | ||
public void setAndIncrease() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
this.count = integerCounter.getAndIncrement(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should state supporting Realm-Java version at the beginning of each version entry in Changelog
now 3.x?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like a good idea.