[Android] Fix empty view not displayed after deleting last Video

Nicolas Pomepuy git at videolan.org
Thu Jul 2 11:51:03 CEST 2020


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Thu Jul  2 09:31:01 2020 +0200| [5b021f2afcd165294ac46955e42c199dff6d4e20] | committer: Nicolas Pomepuy

Fix empty view not displayed after deleting last Video

Fixes #1382

> https://code.videolan.org/videolan/vlc-android/commit/5b021f2afcd165294ac46955e42c199dff6d4e20
---

 .../videolan/vlc/gui/video/VideoGridFragment.kt    |  4 ++
 .../src/org/videolan/vlc/util/Kextensions.kt       | 46 ++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.kt b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.kt
index 870356d8d..b4ad9f72e 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.kt
@@ -60,6 +60,7 @@ import org.videolan.vlc.media.getAll
 import org.videolan.vlc.providers.medialibrary.VideosProvider
 import org.videolan.vlc.reloadLibrary
 import org.videolan.vlc.util.launchWhenStarted
+import org.videolan.vlc.util.onAnyChange
 import org.videolan.vlc.util.share
 import org.videolan.vlc.viewmodels.mobile.VideoGroupingType
 import org.videolan.vlc.viewmodels.mobile.VideosViewModel
@@ -72,6 +73,7 @@ private const val TAG = "VLC/VideoListFragment"
 @ExperimentalCoroutinesApi
 class VideoGridFragment : MediaBrowserFragment<VideosViewModel>(), SwipeRefreshLayout.OnRefreshListener, CtxActionReceiver {
 
+    private lateinit var dataObserver: RecyclerView.AdapterDataObserver
     private lateinit var videoListAdapter: VideoListAdapter
     private lateinit var multiSelectHelper: MultiSelectHelper<MediaLibraryItem>
     private lateinit var binding: VideoGridBinding
@@ -92,6 +94,7 @@ class VideoGridFragment : MediaBrowserFragment<VideosViewModel>(), SwipeRefreshL
         if (!::videoListAdapter.isInitialized) {
             val seenMarkVisible = settings.getBoolean("media_seen", true)
             videoListAdapter = VideoListAdapter(seenMarkVisible)
+            dataObserver = videoListAdapter.onAnyChange { updateEmptyView() }
             multiSelectHelper = videoListAdapter.multiSelectHelper
             val folder = if (savedInstanceState != null) savedInstanceState.getParcelable<Folder>(KEY_FOLDER)
             else arguments?.getParcelable(KEY_FOLDER)
@@ -236,6 +239,7 @@ class VideoGridFragment : MediaBrowserFragment<VideosViewModel>(), SwipeRefreshL
         super.onDestroy()
         videoListAdapter.release()
         gridItemDecoration = null
+        if (::dataObserver.isInitialized) videoListAdapter.unregisterAdapterDataObserver(dataObserver)
     }
 
     override fun getTitle() = when(viewModel.groupingType) {
diff --git a/application/vlc-android/src/org/videolan/vlc/util/Kextensions.kt b/application/vlc-android/src/org/videolan/vlc/util/Kextensions.kt
index 2a04a6131..6c7824c73 100644
--- a/application/vlc-android/src/org/videolan/vlc/util/Kextensions.kt
+++ b/application/vlc-android/src/org/videolan/vlc/util/Kextensions.kt
@@ -25,6 +25,7 @@ import androidx.databinding.BindingAdapter
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentActivity
 import androidx.lifecycle.*
+import androidx.recyclerview.widget.RecyclerView
 import com.google.android.material.snackbar.Snackbar
 import kotlinx.coroutines.*
 import kotlinx.coroutines.flow.Flow
@@ -218,6 +219,51 @@ fun Context.getPendingIntent(iPlay: Intent): PendingIntent {
     else PendingIntent.getService(applicationContext, 0, iPlay, PendingIntent.FLAG_UPDATE_CURRENT)
 }
 
+/**
+ * Register an [RecyclerView.AdapterDataObserver] for the adapter.
+ *
+ * [listener] is called each time a change occurs in the adapter
+ *
+ * return the registered [RecyclerView.AdapterDataObserver]
+ *
+ * /!\ Make sure to unregister [RecyclerView.AdapterDataObserver]
+ */
+fun RecyclerView.Adapter<*>.onAnyChange(listener: ()->Unit): RecyclerView.AdapterDataObserver {
+    val dataObserver = object : RecyclerView.AdapterDataObserver() {
+        override fun onChanged() {
+            super.onChanged()
+            listener.invoke()
+        }
+
+        override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
+            super.onItemRangeChanged(positionStart, itemCount)
+            listener.invoke()
+        }
+
+        override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) {
+            super.onItemRangeChanged(positionStart, itemCount, payload)
+            listener.invoke()
+        }
+
+        override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
+            super.onItemRangeInserted(positionStart, itemCount)
+            listener.invoke()
+        }
+
+        override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
+            super.onItemRangeMoved(fromPosition, toPosition, itemCount)
+            listener.invoke()
+        }
+
+        override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
+            super.onItemRangeRemoved(positionStart, itemCount)
+            listener.invoke()
+        }
+    }
+    registerAdapterDataObserver(dataObserver)
+    return dataObserver
+}
+
 fun generateResolutionClass(width: Int, height: Int) : String? = if (width <= 0 || height <= 0) {
     null
 } else when {



More information about the Android mailing list