mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-11-03 16:53:00 +00:00 
			
		
		
		
	Load enough initial data into BaseListFragment
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user