[Android] [PATCH v2] Keep search filter on screen rotation

Romain Vimont rom1v at videolabs.io
Thu Apr 12 11:00:29 CEST 2018


Save and restore the search query state along with the activity.

Fixes #404
---
Changes from v1:
 - store the saved query in the view model
 - apply the filter on restore (in case the view model has been recreated)
 - filter only if the query changes (so that it does nothing on restore if the
   view model was kept)
 - move the "ignore small query check" to the view model, to prevent
   unnecessary restore when the query changes but still have less than 3
   chars

 .../org/videolan/vlc/gui/ContentActivity.java | 42 ++++++++++++++++++-
 .../org/videolan/vlc/util/FilterDelegate.kt   |  4 ++
 .../org/videolan/vlc/viewmodels/BaseModel.kt  | 15 ++++---
 3 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/vlc-android/src/org/videolan/vlc/gui/ContentActivity.java b/vlc-android/src/org/videolan/vlc/gui/ContentActivity.java
index 2da5bca3b..c577b72e1 100644
--- a/vlc-android/src/org/videolan/vlc/gui/ContentActivity.java
+++ b/vlc-android/src/org/videolan/vlc/gui/ContentActivity.java
@@ -48,6 +48,7 @@ import org.videolan.vlc.gui.video.VideoGridFragment;
 import org.videolan.vlc.interfaces.Filterable;
 import org.videolan.vlc.util.AndroidDevices;
 import org.videolan.vlc.util.Util;
+import org.videolan.vlc.viewmodels.BaseModel;
 
 import java.util.List;
 
@@ -55,9 +56,37 @@ import java.util.List;
 public class ContentActivity extends AudioPlayerContainerActivity implements SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener {
     public static final String TAG = "VLC/ContentActivity";
 
+    private static final String KEY_SEARCH_QUERY = "org.videolan.vlc.SEARCH_QUERY";
+
     private SearchView mSearchView;
     private boolean showRenderers = !AndroidDevices.isChromeBook && !Util.isListEmpty(RendererDelegate.INSTANCE.getRenderers().getValue());
 
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        if (mSearchView != null) {
+            outState.putString(KEY_SEARCH_QUERY, mSearchView.getQuery().toString());
+        }
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+        String query = savedInstanceState.getString(KEY_SEARCH_QUERY);
+        BaseModel<?> viewModel = getViewModel();
+        if (viewModel != null) {
+            viewModel.filter(query);
+        }
+    }
+
+    protected BaseModel<?> getViewModel() {
+        Fragment fragment = getCurrentFragment();
+        if (fragment instanceof MediaBrowserFragment) {
+            return ((MediaBrowserFragment)fragment).getProvider();
+        }
+        return null;
+    }
+
     @Override
     protected void initAudioPlayerContainerActivity() {
         super.initAudioPlayerContainerActivity();
@@ -101,6 +130,16 @@ public class ContentActivity extends AudioPlayerContainerActivity implements Sea
             final MenuItem searchItem = menu.findItem(R.id.ml_menu_filter);
             mSearchView = (SearchView) searchItem.getActionView();
             mSearchView.setQueryHint(getString(R.string.search_list_hint));
+            BaseModel<?> viewModel = getViewModel();
+            if (viewModel != null) {
+                // restore the current filter text, if any
+                String filterQuery = viewModel.getFilterQuery();
+                if (filterQuery != null) {
+                    searchItem.expandActionView();
+                    mSearchView.setQuery(filterQuery, false);
+                    setSearchVisibility(true);
+                }
+            }
             mSearchView.setOnQueryTextListener(this);
             searchItem.setOnActionExpandListener(this);
         }
@@ -141,8 +180,7 @@ public class ContentActivity extends AudioPlayerContainerActivity implements Sea
     public boolean onQueryTextChange(String filterQueryString) {
         final Fragment current = getCurrentFragment();
         if (current instanceof Filterable) {
-            if (filterQueryString.length() < 3) ((Filterable) current).restoreList();
-            else ((Filterable) current).filter(filterQueryString);
+            ((Filterable) current).filter(filterQueryString);
             return true;
         }
         return false;
diff --git a/vlc-android/src/org/videolan/vlc/util/FilterDelegate.kt b/vlc-android/src/org/videolan/vlc/util/FilterDelegate.kt
index c1778a305..d234e772f 100644
--- a/vlc-android/src/org/videolan/vlc/util/FilterDelegate.kt
+++ b/vlc-android/src/org/videolan/vlc/util/FilterDelegate.kt
@@ -43,6 +43,10 @@ open class FilterDelegate<T : MediaLibraryItem>(protected val dataset: MutableLi
             }
         }
     }
+
+    companion object {
+        fun getEffectiveFilter(query: String?) = if (query?.length ?: 0 > 2) query else null
+    }
 }
 
 class PlaylistFilterDelegate(dataset: MutableLiveData<out List<MediaWrapper>>) : FilterDelegate<MediaWrapper>(dataset) {
diff --git a/vlc-android/src/org/videolan/vlc/viewmodels/BaseModel.kt b/vlc-android/src/org/videolan/vlc/viewmodels/BaseModel.kt
index d93c862d9..533205b3b 100644
--- a/vlc-android/src/org/videolan/vlc/viewmodels/BaseModel.kt
+++ b/vlc-android/src/org/videolan/vlc/viewmodels/BaseModel.kt
@@ -38,7 +38,8 @@ abstract class BaseModel<T : MediaLibraryItem> : ViewModel(), RefreshModel {
 
     var sort = Medialibrary.SORT_ALPHA
     var desc = false
-    private var filtering = false
+    var filterQuery: String? = null
+        private set
     protected open val sortKey = this.javaClass.simpleName!!
 
     open fun canSortByName() = true
@@ -105,13 +106,17 @@ abstract class BaseModel<T : MediaLibraryItem> : ViewModel(), RefreshModel {
     fun remove(mw: T) = updateActor.offer(Remove(mw))
 
     fun filter(query: String?) {
-        filtering = true
-        updateActor.offer(Filter(query))
+        var effectiveFilter = FilterDelegate.getEffectiveFilter(query)
+        if (effectiveFilter != FilterDelegate.getEffectiveFilter(filterQuery))
+             updateActor.offer(Filter(effectiveFilter))
+        filterQuery = query
     }
 
     fun restore() {
-        if (filtering) updateActor.offer(Filter(null))
-        filtering = false
+        if (filterQuery != null) {
+            updateActor.offer(Filter(null))
+            filterQuery = null
+        }
     }
 
     protected open fun removeMedia(media: T) = dataset.remove(media)
-- 
2.17.0



More information about the Android mailing list