Load enough initial data into BaseListFragment
This commit is contained in:
parent
2814ae6d3c
commit
fb362022f7
3 changed files with 85 additions and 11 deletions
|
@ -271,7 +271,7 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
|||
@Override
|
||||
protected void initListeners() {
|
||||
super.initListeners();
|
||||
infoListAdapter.setOnStreamSelectedListener(new OnClickGesture<StreamInfoItem>() {
|
||||
infoListAdapter.setOnStreamSelectedListener(new OnClickGesture<>() {
|
||||
@Override
|
||||
public void selected(final StreamInfoItem selectedItem) {
|
||||
onStreamSelected(selectedItem);
|
||||
|
@ -418,7 +418,66 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
|||
// 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, "loadEnoughInitial - 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();
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.util.Log;
|
|||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.schabi.newpipe.error.ErrorInfo;
|
||||
import org.schabi.newpipe.error.UserAction;
|
||||
|
@ -65,7 +66,7 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
|
|||
super.onResume();
|
||||
// Check if it was loading when the fragment was stopped/paused,
|
||||
if (wasLoading.getAndSet(false)) {
|
||||
if (hasMoreItems() && infoListAdapter.getItemsList().size() > 0) {
|
||||
if (hasMoreItems() && !infoListAdapter.getItemsList().isEmpty()) {
|
||||
loadMoreItems();
|
||||
} else {
|
||||
doInitialLoadLogic();
|
||||
|
@ -105,6 +106,7 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
|
|||
// Load and handle
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
protected void doInitialLoadLogic() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "doInitialLoadLogic() called");
|
||||
|
@ -144,6 +146,7 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
|
|||
currentInfo = result;
|
||||
currentNextPage = result.getNextPage();
|
||||
handleResult(result);
|
||||
ifMoreItemsLoadableLoadUntilScrollable();
|
||||
}, throwable ->
|
||||
showError(new ErrorInfo(throwable, errorUserAction,
|
||||
"Start loading: " + url, serviceId)));
|
||||
|
@ -158,7 +161,8 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
|
|||
*/
|
||||
protected abstract Single<ListExtractor.InfoItemsPage> loadMoreItemsLogic();
|
||||
|
||||
protected void loadMoreItems() {
|
||||
@Override
|
||||
protected void loadMoreItems(@Nullable final Runnable initialDataLoadCallback) {
|
||||
isLoading.set(true);
|
||||
|
||||
if (currentWorker != null) {
|
||||
|
@ -171,9 +175,12 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
|
|||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doFinally(this::allowDownwardFocusScroll)
|
||||
.subscribe((@NonNull ListExtractor.InfoItemsPage InfoItemsPage) -> {
|
||||
.subscribe(infoItemsPage -> {
|
||||
isLoading.set(false);
|
||||
handleNextItems(InfoItemsPage);
|
||||
handleNextItems(infoItemsPage);
|
||||
if (initialDataLoadCallback != null) {
|
||||
initialDataLoadCallback.run();
|
||||
}
|
||||
}, (@NonNull Throwable throwable) ->
|
||||
dynamicallyShowErrorPanelOrSnackbar(new ErrorInfo(throwable,
|
||||
errorUserAction, "Loading more items: " + url, serviceId)));
|
||||
|
@ -223,7 +230,7 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
|
|||
setTitle(name);
|
||||
|
||||
if (infoListAdapter.getItemsList().isEmpty()) {
|
||||
if (result.getRelatedItems().size() > 0) {
|
||||
if (!result.getRelatedItems().isEmpty()) {
|
||||
infoListAdapter.addInfoItemList(result.getRelatedItems());
|
||||
showListFooter(hasMoreItems());
|
||||
} else {
|
||||
|
@ -240,7 +247,7 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
|
|||
final List<Throwable> errors = new ArrayList<>(result.getErrors());
|
||||
// handling ContentNotSupportedException not to show the error but an appropriate string
|
||||
// so that crashes won't be sent uselessly and the user will understand what happened
|
||||
errors.removeIf(throwable -> throwable instanceof ContentNotSupportedException);
|
||||
errors.removeIf(ContentNotSupportedException.class::isInstance);
|
||||
|
||||
if (!errors.isEmpty()) {
|
||||
dynamicallyShowErrorPanelOrSnackbar(new ErrorInfo(result.getErrors(),
|
||||
|
|
|
@ -868,12 +868,15 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnEvent((searchResult, throwable) -> isLoading.set(false))
|
||||
.subscribe(this::handleResult, this::onItemError);
|
||||
.subscribe(result -> {
|
||||
handleResult(result);
|
||||
ifMoreItemsLoadableLoadUntilScrollable();
|
||||
}, this::onItemError);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadMoreItems() {
|
||||
protected void loadMoreItems(@Nullable final Runnable initialDataLoadCallback) {
|
||||
if (!Page.isValid(nextPage)) {
|
||||
return;
|
||||
}
|
||||
|
@ -891,7 +894,12 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnEvent((nextItemsResult, throwable) -> isLoading.set(false))
|
||||
.subscribe(this::handleNextItems, this::onItemError);
|
||||
.subscribe(itemsPage -> {
|
||||
handleNextItems(itemsPage);
|
||||
if (initialDataLoadCallback != null) {
|
||||
initialDataLoadCallback.run();
|
||||
}
|
||||
}, this::onItemError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue