Skip to content

Commit fb36202

Browse files
committed
Load enough initial data into BaseListFragment
1 parent 2814ae6 commit fb36202

3 files changed

Lines changed: 85 additions & 11 deletions

File tree

app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ protected void onItemSelected(final InfoItem selectedItem) {
271271
@Override
272272
protected void initListeners() {
273273
super.initListeners();
274-
infoListAdapter.setOnStreamSelectedListener(new OnClickGesture<StreamInfoItem>() {
274+
infoListAdapter.setOnStreamSelectedListener(new OnClickGesture<>() {
275275
@Override
276276
public void selected(final StreamInfoItem selectedItem) {
277277
onStreamSelected(selectedItem);
@@ -418,7 +418,66 @@ public void onCreateOptionsMenu(@NonNull final Menu menu,
418418
// Load and handle
419419
//////////////////////////////////////////////////////////////////////////*/
420420

421-
protected abstract void loadMoreItems();
421+
/**
422+
* If more items are loadable and the itemList is not scrollable -> load more data.
423+
* <br/>
424+
* Should be called once the initial items inside {@link #startLoading(boolean)}
425+
* has been loaded and added to the {@link #itemsList}.
426+
* <br/>
427+
* Otherwise the loading indicator is always shown but no data can be loaded
428+
* because the view is not scrollable; see also #1974.
429+
*/
430+
protected void ifMoreItemsLoadableLoadUntilScrollable() {
431+
ifMoreItemsLoadableLoadUntilScrollable(0);
432+
}
433+
434+
/**
435+
* If more items are loadable and the itemList is not scrollable -> load more data.
436+
*
437+
* @param recursiveCallCount Amount of recursive calls that occurred
438+
* @see #ifMoreItemsLoadableLoadUntilScrollable()
439+
*/
440+
protected void ifMoreItemsLoadableLoadUntilScrollable(final int recursiveCallCount) {
441+
// Try to prevent malfunction / stackoverflow
442+
if (recursiveCallCount > 100) {
443+
Log.w(TAG, "loadEnoughInitialData - Too many recursive calls - Aborting");
444+
return;
445+
}
446+
if (!hasMoreItems()) {
447+
if (DEBUG) {
448+
Log.d(TAG, "loadEnoughInitialData - OK: No more items to load");
449+
}
450+
return;
451+
}
452+
if (itemsList.canScrollVertically(1)
453+
|| itemsList.canScrollVertically(-1)) {
454+
if (DEBUG) {
455+
Log.d(TAG, "loadEnoughInitial - OK: itemList is scrollable");
456+
}
457+
return;
458+
}
459+
if (DEBUG) {
460+
Log.d(TAG, "loadEnoughInitialData - View is not scrollable "
461+
+ "but it could load more items -> Loading more");
462+
}
463+
loadMoreItems(() ->
464+
ifMoreItemsLoadableLoadUntilScrollable(recursiveCallCount + 1));
465+
}
466+
467+
/**
468+
* Loads more items.
469+
* @param initialDataLoadCallback
470+
* Callback used in {@link #ifMoreItemsLoadableLoadUntilScrollable()}.
471+
* <br/>
472+
* Execute it once the data was loaded and added to the {@link #itemsList}.
473+
* <br/>
474+
* Might be <code>null</code>.
475+
*/
476+
protected abstract void loadMoreItems(@Nullable Runnable initialDataLoadCallback);
477+
478+
protected void loadMoreItems() {
479+
loadMoreItems(null);
480+
}
422481

423482
protected abstract boolean hasMoreItems();
424483

app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import android.view.View;
77

88
import androidx.annotation.NonNull;
9+
import androidx.annotation.Nullable;
910

1011
import org.schabi.newpipe.error.ErrorInfo;
1112
import org.schabi.newpipe.error.UserAction;
@@ -65,7 +66,7 @@ public void onResume() {
6566
super.onResume();
6667
// Check if it was loading when the fragment was stopped/paused,
6768
if (wasLoading.getAndSet(false)) {
68-
if (hasMoreItems() && infoListAdapter.getItemsList().size() > 0) {
69+
if (hasMoreItems() && !infoListAdapter.getItemsList().isEmpty()) {
6970
loadMoreItems();
7071
} else {
7172
doInitialLoadLogic();
@@ -105,6 +106,7 @@ public void readFrom(@NonNull final Queue<Object> savedObjects) throws Exception
105106
// Load and handle
106107
//////////////////////////////////////////////////////////////////////////*/
107108

109+
@Override
108110
protected void doInitialLoadLogic() {
109111
if (DEBUG) {
110112
Log.d(TAG, "doInitialLoadLogic() called");
@@ -144,6 +146,7 @@ public void startLoading(final boolean forceLoad) {
144146
currentInfo = result;
145147
currentNextPage = result.getNextPage();
146148
handleResult(result);
149+
ifMoreItemsLoadableLoadUntilScrollable();
147150
}, throwable ->
148151
showError(new ErrorInfo(throwable, errorUserAction,
149152
"Start loading: " + url, serviceId)));
@@ -158,7 +161,8 @@ public void startLoading(final boolean forceLoad) {
158161
*/
159162
protected abstract Single<ListExtractor.InfoItemsPage> loadMoreItemsLogic();
160163

161-
protected void loadMoreItems() {
164+
@Override
165+
protected void loadMoreItems(@Nullable final Runnable initialDataLoadCallback) {
162166
isLoading.set(true);
163167

164168
if (currentWorker != null) {
@@ -171,9 +175,12 @@ protected void loadMoreItems() {
171175
.subscribeOn(Schedulers.io())
172176
.observeOn(AndroidSchedulers.mainThread())
173177
.doFinally(this::allowDownwardFocusScroll)
174-
.subscribe((@NonNull ListExtractor.InfoItemsPage InfoItemsPage) -> {
178+
.subscribe(infoItemsPage -> {
175179
isLoading.set(false);
176-
handleNextItems(InfoItemsPage);
180+
handleNextItems(infoItemsPage);
181+
if (initialDataLoadCallback != null) {
182+
initialDataLoadCallback.run();
183+
}
177184
}, (@NonNull Throwable throwable) ->
178185
dynamicallyShowErrorPanelOrSnackbar(new ErrorInfo(throwable,
179186
errorUserAction, "Loading more items: " + url, serviceId)));
@@ -223,7 +230,7 @@ public void handleResult(@NonNull final I result) {
223230
setTitle(name);
224231

225232
if (infoListAdapter.getItemsList().isEmpty()) {
226-
if (result.getRelatedItems().size() > 0) {
233+
if (!result.getRelatedItems().isEmpty()) {
227234
infoListAdapter.addInfoItemList(result.getRelatedItems());
228235
showListFooter(hasMoreItems());
229236
} else {
@@ -240,7 +247,7 @@ public void handleResult(@NonNull final I result) {
240247
final List<Throwable> errors = new ArrayList<>(result.getErrors());
241248
// handling ContentNotSupportedException not to show the error but an appropriate string
242249
// so that crashes won't be sent uselessly and the user will understand what happened
243-
errors.removeIf(throwable -> throwable instanceof ContentNotSupportedException);
250+
errors.removeIf(ContentNotSupportedException.class::isInstance);
244251

245252
if (!errors.isEmpty()) {
246253
dynamicallyShowErrorPanelOrSnackbar(new ErrorInfo(result.getErrors(),

app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -868,12 +868,15 @@ public void startLoading(final boolean forceLoad) {
868868
.subscribeOn(Schedulers.io())
869869
.observeOn(AndroidSchedulers.mainThread())
870870
.doOnEvent((searchResult, throwable) -> isLoading.set(false))
871-
.subscribe(this::handleResult, this::onItemError);
871+
.subscribe(result -> {
872+
handleResult(result);
873+
ifMoreItemsLoadableLoadUntilScrollable();
874+
}, this::onItemError);
872875

873876
}
874877

875878
@Override
876-
protected void loadMoreItems() {
879+
protected void loadMoreItems(@Nullable final Runnable initialDataLoadCallback) {
877880
if (!Page.isValid(nextPage)) {
878881
return;
879882
}
@@ -891,7 +894,12 @@ protected void loadMoreItems() {
891894
.subscribeOn(Schedulers.io())
892895
.observeOn(AndroidSchedulers.mainThread())
893896
.doOnEvent((nextItemsResult, throwable) -> isLoading.set(false))
894-
.subscribe(this::handleNextItems, this::onItemError);
897+
.subscribe(itemsPage -> {
898+
handleNextItems(itemsPage);
899+
if (initialDataLoadCallback != null) {
900+
initialDataLoadCallback.run();
901+
}
902+
}, this::onItemError);
895903
}
896904

897905
@Override

0 commit comments

Comments
 (0)