Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix transaction too large in channel tab fragments #10673

Merged
merged 1 commit into from
Dec 21, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.schabi.newpipe.fragments.list.channel;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
Expand All @@ -14,7 +15,9 @@
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabInfo;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.linkhandler.ReadyChannelTabListLinkHandler;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
import org.schabi.newpipe.fragments.list.playlist.PlaylistControlViewHolder;
Expand Down Expand Up @@ -114,6 +117,27 @@ public void setTitle(final String title) {
public void handleResult(@NonNull final ChannelTabInfo result) {
super.handleResult(result);

// FIXME this is a really hacky workaround, to avoid storing useless data in the fragment
// state. The problem is, `ReadyChannelTabListLinkHandler` might contain raw JSON data that
// uses a lot of memory (e.g. ~800KB for YouTube). While 800KB doesn't seem much, if
// you combine just a couple of channel tab fragments you easily go over the 1MB
// save&restore transaction limit, and get `TransactionTooLargeException`s. A proper
// solution would require rethinking about `ReadyChannelTabListLinkHandler`s.
if (tabHandler instanceof ReadyChannelTabListLinkHandler) {
try {
// once `handleResult` is called, the parsed data was already saved to cache, so
// we can discard any raw data in ReadyChannelTabListLinkHandler and create a
// link handler with identical properties, but without any raw data
tabHandler = result.getService()
.getChannelTabLHFactory()
.fromQuery(tabHandler.getId(), tabHandler.getContentFilters(),
tabHandler.getSortFilter());
Comment on lines +131 to +134
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes a crash. Use media.ccc.de service, open a channel / conference. getChannelTabLHFactory() is null for that service:

https://github.com/TeamNewPipe/NewPipeExtractor/blob/f276caf54a85a271904943e4aa6c57efd4249fec/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java#L53-L56

Exception

  • User Action: ui error
  • Request: ACRA report
  • Content Country: DE
  • Content Language: de-
  • App Language: en
  • Service: none
  • Version: 0.26.0
  • OS: Linux Android 12 - 32
Crash log

java.lang.NullPointerException: Attempt to invoke virtual method 'org.schabi.newpipe.extractor.linkhandler.ListLinkHandler org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory.fromQuery(java.lang.String, java.util.List, java.lang.String)' on a null object reference
	at org.schabi.newpipe.fragments.list.channel.ChannelTabFragment.handleResult(ChannelTabFragment.java:133)
	at org.schabi.newpipe.fragments.list.channel.ChannelTabFragment.handleResult(ChannelTabFragment.java:37)
	at org.schabi.newpipe.fragments.list.BaseListInfoFragment.lambda$startLoading$0(BaseListInfoFragment.java:150)
	at org.schabi.newpipe.fragments.list.BaseListInfoFragment.$r8$lambda$yX6S2nKGSbR70YowNdSpGemC7q4(BaseListInfoFragment.java:0)
	at org.schabi.newpipe.fragments.list.BaseListInfoFragment$$ExternalSyntheticLambda4.accept(R8$$SyntheticClass:0)
	at io.reactivex.rxjava3.internal.observers.ConsumerSingleObserver.onSuccess(ConsumerSingleObserver.java:62)
	at io.reactivex.rxjava3.internal.operators.single.SingleObserveOn$ObserveOnSingleObserver.run(SingleObserveOn.java:81)
	at io.reactivex.rxjava3.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:123)
	at android.os.Handler.handleCallback(Handler.java:938)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7870)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)


} catch (final ParsingException e) {
// silently ignore the error, as the app can continue to function normally
Log.w(TAG, "Could not recreate channel tab handler", e);
}
}

if (playlistControlBinding != null) {
// PlaylistControls should be visible only if there is some item in
// infoListAdapter other than header
Expand Down
Loading