Reverted to loading behavior of #7638 and improved it
The previous/reverted behavior caused unwanted data transmission: * Removed loading via handleResults/loadMoreItems-callback because the RecyclerView is apparently not immediately updated in the UI when the data is set which causes one load of data to much.
This commit is contained in:
parent
d3cd3d62b4
commit
ff7cfe4715
3 changed files with 68 additions and 80 deletions
|
@ -312,14 +312,74 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||||
});
|
});
|
||||||
|
|
||||||
itemsList.clearOnScrollListeners();
|
itemsList.clearOnScrollListeners();
|
||||||
itemsList.addOnScrollListener(new OnScrollBelowItemsListener() {
|
|
||||||
|
/*
|
||||||
|
* Add initial scroll listener - which tries to load more items when not enough
|
||||||
|
* are in the view (not scrollable) and more are available.
|
||||||
|
*
|
||||||
|
* Note: This method only works because "This callback will also be called if visible
|
||||||
|
* item range changes after a layout calculation. In that case, dx and dy will be 0."
|
||||||
|
* - which might be unexpected because no actual scrolling occurs...
|
||||||
|
*
|
||||||
|
* This listener will be replaced by DefaultItemListOnScrolledDownListener when
|
||||||
|
* * the view was actually scrolled
|
||||||
|
* * the view is scrollable
|
||||||
|
* * No more items can be loaded
|
||||||
|
*/
|
||||||
|
itemsList.addOnScrollListener(new DefaultItemListOnScrolledDownListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onScrolledDown(final RecyclerView recyclerView) {
|
public void onScrolled(final RecyclerView recyclerView, final int dx, final int dy) {
|
||||||
onScrollToBottom();
|
super.onScrolled(recyclerView, dx, dy);
|
||||||
|
|
||||||
|
if (dy != 0) {
|
||||||
|
log("Vertical scroll occurred");
|
||||||
|
|
||||||
|
useNormalScrollListener();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isLoading.get()) {
|
||||||
|
log("Still loading data -> Skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!hasMoreItems()) {
|
||||||
|
log("No more items to load");
|
||||||
|
|
||||||
|
useNormalScrollListener();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (itemsList.canScrollVertically(1)
|
||||||
|
|| itemsList.canScrollVertically(-1)) {
|
||||||
|
log("View is scrollable");
|
||||||
|
|
||||||
|
useNormalScrollListener();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log("Loading more data");
|
||||||
|
loadMoreItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void useNormalScrollListener() {
|
||||||
|
log("Unregistering and using normal listener");
|
||||||
|
itemsList.removeOnScrollListener(this);
|
||||||
|
itemsList.addOnScrollListener(new DefaultItemListOnScrolledDownListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void log(final String msg) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "itemListInitScrollListener - " + msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DefaultItemListOnScrolledDownListener extends OnScrollBelowItemsListener {
|
||||||
|
@Override
|
||||||
|
public void onScrolledDown(final RecyclerView recyclerView) {
|
||||||
|
onScrollToBottom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onStreamSelected(final StreamInfoItem selectedItem) {
|
private void onStreamSelected(final StreamInfoItem selectedItem) {
|
||||||
onItemSelected(selectedItem);
|
onItemSelected(selectedItem);
|
||||||
NavigationHelper.openVideoDetailFragment(requireContext(), getFM(),
|
NavigationHelper.openVideoDetailFragment(requireContext(), getFM(),
|
||||||
|
@ -407,66 +467,7 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||||
// Load and handle
|
// Load and handle
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
/**
|
protected abstract void loadMoreItems();
|
||||||
* If more items are loadable and the itemList is not scrollable -> load more data.
|
|
||||||
* <br/>
|
|
||||||
* Should be called once the initial items inside {@link #startLoading(boolean)}
|
|
||||||
* has been loaded and added to the {@link #itemsList}.
|
|
||||||
* <br/>
|
|
||||||
* Otherwise the loading indicator is always shown but no data can be loaded
|
|
||||||
* because the view is not scrollable; see also #1974.
|
|
||||||
*/
|
|
||||||
protected void ifMoreItemsLoadableLoadUntilScrollable() {
|
|
||||||
ifMoreItemsLoadableLoadUntilScrollable(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If more items are loadable and the itemList is not scrollable -> load more data.
|
|
||||||
*
|
|
||||||
* @param recursiveCallCount Amount of recursive calls that occurred
|
|
||||||
* @see #ifMoreItemsLoadableLoadUntilScrollable()
|
|
||||||
*/
|
|
||||||
protected void ifMoreItemsLoadableLoadUntilScrollable(final int recursiveCallCount) {
|
|
||||||
// Try to prevent malfunction / stackoverflow
|
|
||||||
if (recursiveCallCount > 100) {
|
|
||||||
Log.w(TAG, "loadEnoughInitialData - Too many recursive calls - Aborting");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!hasMoreItems()) {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, "loadEnoughInitialData - OK: No more items to load");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (itemsList.canScrollVertically(1)
|
|
||||||
|| itemsList.canScrollVertically(-1)) {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, "loadEnoughInitialData - OK: itemList is scrollable");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, "loadEnoughInitialData - View is not scrollable "
|
|
||||||
+ "but it could load more items -> Loading more");
|
|
||||||
}
|
|
||||||
loadMoreItems(() ->
|
|
||||||
ifMoreItemsLoadableLoadUntilScrollable(recursiveCallCount + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads more items.
|
|
||||||
* @param initialDataLoadCallback
|
|
||||||
* Callback used in {@link #ifMoreItemsLoadableLoadUntilScrollable()}.
|
|
||||||
* <br/>
|
|
||||||
* Execute it once the data was loaded and added to the {@link #itemsList}.
|
|
||||||
* <br/>
|
|
||||||
* Might be <code>null</code>.
|
|
||||||
*/
|
|
||||||
protected abstract void loadMoreItems(@Nullable Runnable initialDataLoadCallback);
|
|
||||||
|
|
||||||
protected void loadMoreItems() {
|
|
||||||
loadMoreItems(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract boolean hasMoreItems();
|
protected abstract boolean hasMoreItems();
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.error.ErrorInfo;
|
import org.schabi.newpipe.error.ErrorInfo;
|
||||||
import org.schabi.newpipe.error.UserAction;
|
import org.schabi.newpipe.error.UserAction;
|
||||||
|
@ -146,7 +145,6 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
|
||||||
currentInfo = result;
|
currentInfo = result;
|
||||||
currentNextPage = result.getNextPage();
|
currentNextPage = result.getNextPage();
|
||||||
handleResult(result);
|
handleResult(result);
|
||||||
ifMoreItemsLoadableLoadUntilScrollable();
|
|
||||||
}, throwable ->
|
}, throwable ->
|
||||||
showError(new ErrorInfo(throwable, errorUserAction,
|
showError(new ErrorInfo(throwable, errorUserAction,
|
||||||
"Start loading: " + url, serviceId)));
|
"Start loading: " + url, serviceId)));
|
||||||
|
@ -162,7 +160,7 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
|
||||||
protected abstract Single<ListExtractor.InfoItemsPage> loadMoreItemsLogic();
|
protected abstract Single<ListExtractor.InfoItemsPage> loadMoreItemsLogic();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadMoreItems(@Nullable final Runnable initialDataLoadCallback) {
|
protected void loadMoreItems() {
|
||||||
isLoading.set(true);
|
isLoading.set(true);
|
||||||
|
|
||||||
if (currentWorker != null) {
|
if (currentWorker != null) {
|
||||||
|
@ -178,9 +176,6 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
|
||||||
.subscribe(infoItemsPage -> {
|
.subscribe(infoItemsPage -> {
|
||||||
isLoading.set(false);
|
isLoading.set(false);
|
||||||
handleNextItems(infoItemsPage);
|
handleNextItems(infoItemsPage);
|
||||||
if (initialDataLoadCallback != null) {
|
|
||||||
initialDataLoadCallback.run();
|
|
||||||
}
|
|
||||||
}, (@NonNull Throwable throwable) ->
|
}, (@NonNull Throwable throwable) ->
|
||||||
dynamicallyShowErrorPanelOrSnackbar(new ErrorInfo(throwable,
|
dynamicallyShowErrorPanelOrSnackbar(new ErrorInfo(throwable,
|
||||||
errorUserAction, "Loading more items: " + url, serviceId)));
|
errorUserAction, "Loading more items: " + url, serviceId)));
|
||||||
|
|
|
@ -868,15 +868,12 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.doOnEvent((searchResult, throwable) -> isLoading.set(false))
|
.doOnEvent((searchResult, throwable) -> isLoading.set(false))
|
||||||
.subscribe(result -> {
|
.subscribe(this::handleResult, this::onItemError);
|
||||||
handleResult(result);
|
|
||||||
ifMoreItemsLoadableLoadUntilScrollable();
|
|
||||||
}, this::onItemError);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadMoreItems(@Nullable final Runnable initialDataLoadCallback) {
|
protected void loadMoreItems() {
|
||||||
if (!Page.isValid(nextPage)) {
|
if (!Page.isValid(nextPage)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -894,12 +891,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.doOnEvent((nextItemsResult, throwable) -> isLoading.set(false))
|
.doOnEvent((nextItemsResult, throwable) -> isLoading.set(false))
|
||||||
.subscribe(itemsPage -> {
|
.subscribe(this::handleNextItems, this::onItemError);
|
||||||
handleNextItems(itemsPage);
|
|
||||||
if (initialDataLoadCallback != null) {
|
|
||||||
initialDataLoadCallback.run();
|
|
||||||
}
|
|
||||||
}, this::onItemError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in a new issue