diff --git a/CHANGELOG.md b/CHANGELOG.md index 36cd26b..f767d2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# Monarchy 0.5.1 (2018-10-08) +- Remove `createDataSourceFactory(Query, boolean asAsync)` because it doesn't actually work with Sync. :( + +- Fix `PagedLiveResults.updateQuery()`. Now it re-creates the RealmResults as it was originally intended. + # Monarchy 0.5.0 (2018-09-14) - Add `openManually()` and `closeManually()` methods for people who use Sync and need their session to stay alive in a controlled manner. Please note that this increments the Realm ref count by one, and cannot be called multiple times. (So `openManually` called once, then `closeManually` called once). diff --git a/README.md b/README.md index e12aa8a..94c42c7 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ With that, you can use a singleton Monarchy instance to manage Realm queries, an To use `Monarchy`, you need to add as a dependency: - implementation 'com.github.Zhuinden:realm-monarchy:0.5.0' + implementation 'com.github.Zhuinden:realm-monarchy:0.5.1' And it's available on Jitpack, so you need to add diff --git a/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/managed/ManagedDogAdapter.java b/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/managed/ManagedDogAdapter.java index e9b1904..8ac5b50 100644 --- a/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/managed/ManagedDogAdapter.java +++ b/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/managed/ManagedDogAdapter.java @@ -39,7 +39,12 @@ public void onBindViewHolder(ManagedDogAdapter.ViewHolder holder, int position) @Override public int getItemCount() { - return items == null ? 0 : items.size(); + try { + return items == null ? 0 : items.size(); + } catch(IllegalStateException e) { + return 0; // I should check `RealmResults.isValid()` here, but I'm using List. + // RecyclerView is running the prefetch worker on the next Handler loop, but by then, Realm is closed. + } } public void updateData(List items, @Nullable CustomDiffResult diffResult) { diff --git a/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/managed/ManagedFragment.java b/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/managed/ManagedFragment.java index b088f40..1c0f89b 100644 --- a/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/managed/ManagedFragment.java +++ b/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/managed/ManagedFragment.java @@ -72,6 +72,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { @Override public void onDestroyView() { changes.removeObserver(observer); + managedDogAdapter.notifyDataSetChanged(); // if Realm is closed, then the item count becomes 0. Adapter does not know this while scrolling. super.onDestroyView(); } } diff --git a/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/paged/PagedFragment.java b/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/paged/PagedFragment.java index 8e7b511..d60a3e5 100644 --- a/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/paged/PagedFragment.java +++ b/monarchy-example/src/main/java/com/zhuinden/monarchyexample/features/paged/PagedFragment.java @@ -10,14 +10,17 @@ import android.support.annotation.Nullable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.text.Editable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.EditText; import com.zhuinden.monarchy.Monarchy; import com.zhuinden.monarchyexample.Dog; import com.zhuinden.monarchyexample.R; import com.zhuinden.monarchyexample.RealmDog; +import com.zhuinden.monarchyexample.RealmDogFields; import com.zhuinden.monarchyexample.application.CustomApplication; import com.zhuinden.monarchyexample.utils.BaseFragment; @@ -25,6 +28,10 @@ import butterknife.BindView; import butterknife.ButterKnife; +import butterknife.OnTextChanged; +import io.realm.Case; +import io.realm.Realm; +import io.realm.RealmQuery; /** * Created by Zhuinden on 2017.12.21.. @@ -35,6 +42,9 @@ public class PagedFragment @BindView(R.id.recycler_view) RecyclerView recyclerView; + @BindView(R.id.text_paged_search) + EditText searchText; + @Inject Monarchy monarchy; @@ -45,6 +55,21 @@ public class PagedFragment pagedDogAdapter.submitList(dogs); }; + Monarchy.RealmDataSourceFactory realmDataSourceFactory; + + @OnTextChanged(R.id.text_paged_search) + public void onSearchTextChanged(Editable editable) { + String text = editable.toString(); + realmDataSourceFactory.updateQuery(realm -> { + RealmQuery query = realm.where(RealmDog.class); + if(text.isEmpty()) { + return query; + } else { + return query.contains(RealmDogFields.NAME, text.trim(), Case.INSENSITIVE); + } + }); + } + @Override public void onAttach(Context context) { super.onAttach(context); @@ -65,8 +90,8 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); recyclerView.setAdapter(pagedDogAdapter); - DataSource.Factory realmDataSourceFactory = monarchy.createDataSourceFactory( - realm -> realm.where(RealmDog.class), true); + realmDataSourceFactory = monarchy.createDataSourceFactory( + realm -> realm.where(RealmDog.class)); dataSourceFactory = realmDataSourceFactory.map(input -> Dog.create(input.getName())); dogs = monarchy.findAllPagedWithChanges(realmDataSourceFactory, new LivePagedListBuilder<>(dataSourceFactory, 20)); diff --git a/monarchy-example/src/main/res/layout/fragment_paged.xml b/monarchy-example/src/main/res/layout/fragment_paged.xml index de5afb5..94b0abf 100644 --- a/monarchy-example/src/main/res/layout/fragment_paged.xml +++ b/monarchy-example/src/main/res/layout/fragment_paged.xml @@ -1,6 +1,6 @@ - @@ -8,20 +8,27 @@ + android:textSize="22sp" + android:textStyle="bold"/> + + , RealmResults void createAndObserveRealmQuery(final LiveResults liveResults) { + Realm realm = realmThreadLocal.get(); + checkRealmValid(realm); + if(liveResults == null) { + return; + } + RealmResults results = liveResults.createQuery(realm); + resultsRefs.get().put(liveResults, results); + results.addChangeListener(new RealmChangeListener>() { + @Override + public void onChange(@NonNull RealmResults realmResults) { + liveResults.updateResults(realmResults.createSnapshot()); + } + }); + } + + // CALL THIS SYNC ON MONARCHY THREAD + void destroyRealmQuery(final LiveResults liveResults) { + Realm realm = realmThreadLocal.get(); + checkRealmValid(realm); + if(liveResults == null) { + return; + } + RealmResults realmResults = resultsRefs.get().remove(liveResults); + if(realmResults != null) { + realmResults.removeAllChangeListeners(); + } + } + void startListening(@Nullable final LiveResults liveResults) { // build Realm instance if(refCount.getAndIncrement() == 0) { @@ -210,19 +240,7 @@ public void run() { handler.get().post(new Runnable() { @Override public void run() { - Realm realm = realmThreadLocal.get(); - checkRealmValid(realm); - if(liveResults == null) { - return; - } - RealmResults results = liveResults.createQuery(realm); - resultsRefs.get().put(liveResults, results); - results.addChangeListener(new RealmChangeListener>() { - @Override - public void onChange(@NonNull RealmResults realmResults) { - liveResults.updateResults(realmResults.createSnapshot()); - } - }); + createAndObserveRealmQuery(liveResults); } }); } @@ -236,15 +254,7 @@ void stopListening(@Nullable final LiveResults liveRes handler.post(new Runnable() { @Override public void run() { - Realm realm = realmThreadLocal.get(); - checkRealmValid(realm); - if(liveResults == null) { - return; - } - RealmResults realmResults = resultsRefs.get().remove(liveResults); - if(realmResults != null) { - realmResults.removeAllChangeListeners(); - } + destroyRealmQuery(liveResults); } }); // destroy Realm instance @@ -521,18 +531,8 @@ public void run() { * @param query the query */ public RealmDataSourceFactory createDataSourceFactory(Query query) { - return createDataSourceFactory(query, false); - } - - /** - * Creates a DataSource.Factory of (Integer, T) that can be used for creating a paged result set. - * - * @param query the query - * @param asAsync determines whether the created query uses the Async API. - */ - public RealmDataSourceFactory createDataSourceFactory(Query query, boolean asAsync) { assertMainThread(); - PagedLiveResults liveResults = new PagedLiveResults(this, query, asAsync); + PagedLiveResults liveResults = new PagedLiveResults(this, query, false); return new RealmDataSourceFactory<>(this, liveResults); } @@ -700,7 +700,7 @@ public void doWithRealm(Realm realm) { */ public static final class RealmDataSourceFactory extends DataSource.Factory { - Monarchy monarchy; + final Monarchy monarchy; final PagedLiveResults pagedLiveResults; RealmDataSourceFactory(Monarchy monarchy, PagedLiveResults pagedLiveResults) { @@ -718,10 +718,25 @@ public final DataSource create() { /** * Updates the query that the datasource is evaluated by. * + * Please note that this method runs asynchronously. + * * @param query the query */ - public final void updateQuery(Query query) { - pagedLiveResults.updateQuery(query); + public final void updateQuery(final Query query) { + Handler handler = monarchy.handler.get(); + if(handler == null) { + return; + } + handler.post(new Runnable() { + @Override + public void run() { + monarchy.destroyRealmQuery(pagedLiveResults); + pagedLiveResults.updateQuery(query); + monarchy.createAndObserveRealmQuery(pagedLiveResults); + pagedLiveResults.invalidateDatasource(); + } + }); + } } diff --git a/monarchy/src/main/java/com/zhuinden/monarchy/PagedLiveResults.java b/monarchy/src/main/java/com/zhuinden/monarchy/PagedLiveResults.java index cb05c78..999d84d 100644 --- a/monarchy/src/main/java/com/zhuinden/monarchy/PagedLiveResults.java +++ b/monarchy/src/main/java/com/zhuinden/monarchy/PagedLiveResults.java @@ -78,8 +78,12 @@ void setDataSource(Monarchy.RealmTiledDataSource dataSource) { this.dataSource = dataSource; } - public void updateQuery(Monarchy.Query query) { + // CALL THIS FROM MONARCHY THREAD + void updateQuery(Monarchy.Query query) { this.query.set(query); + } + + void invalidateDatasource() { if(dataSource != null) { dataSource.invalidate(); }