From 760feb8723e50662f0a2aabf936a911ff10cb227 Mon Sep 17 00:00:00 2001 From: Yuriy Liskov Date: Mon, 19 May 2025 17:47:28 +0300 Subject: [PATCH] multiple rows layout errors fix 2 --- .../ui/browse/video/MultipleRowsFragment.java | 34 +++++++----- .../tv/ui/search/tags/SearchTagsFragment.java | 53 +++++++++++++++++-- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/browse/video/MultipleRowsFragment.java b/smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/browse/video/MultipleRowsFragment.java index 35655f45c..01cf9ddc2 100644 --- a/smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/browse/video/MultipleRowsFragment.java +++ b/smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/browse/video/MultipleRowsFragment.java @@ -168,17 +168,7 @@ public abstract class MultipleRowsFragment extends RowsSupportFragment implement return -1; } - @Override - public boolean isEmpty() { - if (mRowsAdapter == null) { - return mPendingUpdates.isEmpty(); - } - - return mRowsAdapter.size() == 0; - } - - @Override - public void update(VideoGroup group) { + private boolean isComputingLayout(VideoGroup group) { int action = group.getAction(); // Attempt to fix: IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling @@ -190,14 +180,30 @@ public abstract class MultipleRowsFragment extends RowsSupportFragment implement Object nestedRecyclerView = Helpers.getField(viewHolder, "mNestedRecyclerView"); if (nestedRecyclerView instanceof WeakReference) { Object recyclerView = ((WeakReference) nestedRecyclerView).get(); - if (recyclerView instanceof RecyclerView && ((RecyclerView) recyclerView).isComputingLayout()) { - return; - } + return recyclerView instanceof RecyclerView && ((RecyclerView) recyclerView).isComputingLayout(); } } } } + return false; + } + + @Override + public boolean isEmpty() { + if (mRowsAdapter == null) { + return mPendingUpdates.isEmpty(); + } + + return mRowsAdapter.size() == 0; + } + + @Override + public void update(VideoGroup group) { + if (isComputingLayout(group)) { + return; + } + freeze(true); updateInt(group); diff --git a/smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/search/tags/SearchTagsFragment.java b/smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/search/tags/SearchTagsFragment.java index d744c5ddd..76ce8fc76 100644 --- a/smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/search/tags/SearchTagsFragment.java +++ b/smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/search/tags/SearchTagsFragment.java @@ -8,6 +8,9 @@ import androidx.leanback.widget.HeaderItem; import androidx.leanback.widget.ListRow; import androidx.leanback.widget.ObjectAdapter; import androidx.leanback.widget.Presenter; +import androidx.recyclerview.widget.RecyclerView; + +import com.liskovsoft.sharedutils.helpers.Helpers; import com.liskovsoft.sharedutils.mylogger.Log; import com.liskovsoft.smartyoutubetv2.common.app.models.data.Video; import com.liskovsoft.smartyoutubetv2.common.app.models.data.VideoGroup; @@ -23,6 +26,7 @@ import com.liskovsoft.smartyoutubetv2.tv.ui.common.LeanbackActivity; import com.liskovsoft.smartyoutubetv2.tv.ui.search.tags.vineyard.SearchTagsFragmentBase; import com.liskovsoft.smartyoutubetv2.tv.util.ViewUtil; +import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.Map; @@ -87,8 +91,14 @@ public class SearchTagsFragment extends SearchTagsFragmentBase { @Override public void updateSearch(VideoGroup group) { + if (isComputingLayout(group)) { + return; + } + freeze(true); + update(group); + freeze(false); } @@ -319,11 +329,7 @@ public class SearchTagsFragment extends SearchTagsFragmentBase { } else { Log.d(TAG, "Continue row %s %s", group.getTitle(), System.currentTimeMillis()); - freeze(true); - existingAdapter.add(group); // continue row - - freeze(false); } } @@ -352,6 +358,45 @@ public class SearchTagsFragment extends SearchTagsFragmentBase { return isVoice; } + private int findPositionById(int id) { + if (getResultsAdapter() != null) { + VideoGroupObjectAdapter needed = mSearchGroupAdapters.get(id); + for (int i = 0; i < getResultsAdapter().size(); i++) { + Object row = getResultsAdapter().get(i); + + if (row instanceof ListRow) { + VideoGroupObjectAdapter adapter = (VideoGroupObjectAdapter) ((ListRow) row).getAdapter(); + if (adapter == needed) { + return i; + } + } + } + } + + return -1; + } + + private boolean isComputingLayout(VideoGroup group) { + int action = group.getAction(); + + // Attempt to fix: IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling + if (action == VideoGroup.ACTION_SYNC && getRowsSupportFragment() != null && getRowsSupportFragment().getVerticalGridView() != null) { + int position = findPositionById(group.getId()); + if (position != -1) { + RecyclerView.ViewHolder viewHolder = getRowsSupportFragment().getVerticalGridView().findViewHolderForAdapterPosition(position); + if (viewHolder != null) { + Object nestedRecyclerView = Helpers.getField(viewHolder, "mNestedRecyclerView"); + if (nestedRecyclerView instanceof WeakReference) { + Object recyclerView = ((WeakReference) nestedRecyclerView).get(); + return recyclerView instanceof RecyclerView && ((RecyclerView) recyclerView).isComputingLayout(); + } + } + } + } + + return false; + } + public void onFinish() { mSearchPresenter.onFinish(); }