Skip to content

Commit 80f33da

Browse files
committed
Fix OutOfMemory when fetching feed
Reduced memory footprint of FeedUpdateInfo objects. Those objects might stay around for a while and accumulate (up to BUFFER_COUNT_BEFORE_INSERT = 20 at the moment), so in order not to fill up the memory it's better to keep as little data as possible. Previously ChannelInfo data was stored, causing ReadyChannelTabLinkHandler objects to be also stored uselessly (and those channel tabs contain prefetched JSON data which used ~700KB of memory).
1 parent 35c1dfd commit 80f33da

4 files changed

Lines changed: 41 additions & 27 deletions

File tree

app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class NotificationHelper(val context: Context) {
5858
.setAutoCancel(true)
5959
.setCategory(NotificationCompat.CATEGORY_SOCIAL)
6060
.setGroupSummary(true)
61-
.setGroup(data.originalInfo.url)
61+
.setGroup(data.url)
6262
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
6363

6464
// Build a summary notification for Android versions < 7.0
@@ -73,7 +73,7 @@ class NotificationHelper(val context: Context) {
7373
context,
7474
data.pseudoId,
7575
NavigationHelper
76-
.getChannelIntent(context, data.originalInfo.serviceId, data.originalInfo.url)
76+
.getChannelIntent(context, data.serviceId, data.url)
7777
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
7878
0,
7979
false
@@ -88,7 +88,7 @@ class NotificationHelper(val context: Context) {
8888

8989
// Show individual stream notifications, set channel icon only if there is actually
9090
// one
91-
showStreamNotifications(newStreams, data.originalInfo.serviceId, bitmap)
91+
showStreamNotifications(newStreams, data.serviceId, bitmap)
9292
// Show summary notification
9393
manager.notify(data.pseudoId, summaryBuilder.build())
9494

@@ -97,7 +97,7 @@ class NotificationHelper(val context: Context) {
9797

9898
override fun onBitmapFailed(e: Exception, errorDrawable: Drawable) {
9999
// Show individual stream notifications
100-
showStreamNotifications(newStreams, data.originalInfo.serviceId, null)
100+
showStreamNotifications(newStreams, data.serviceId, null)
101101
// Show summary notification
102102
manager.notify(data.pseudoId, summaryBuilder.build())
103103
iconLoadingTargets.remove(this) // allow it to be garbage-collected

app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,14 +277,14 @@ class FeedLoadManager(private val context: Context) {
277277
notification.value!!.newStreams = filterNewStreams(info.streams)
278278

279279
feedDatabaseManager.upsertAll(info.uid, info.streams)
280-
subscriptionManager.updateFromInfo(info.uid, info.originalInfo)
280+
subscriptionManager.updateFromInfo(info)
281281

282282
if (info.errors.isNotEmpty()) {
283283
feedResultsHolder.addErrors(
284284
info.errors.map {
285285
FeedLoadService.RequestException(
286286
info.uid,
287-
"${info.originalInfo.serviceId}:${info.originalInfo.url}",
287+
"${info.serviceId}:${info.url}",
288288
it
289289
)
290290
}

app/src/main/java/org/schabi/newpipe/local/feed/service/FeedUpdateInfo.kt

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,48 @@ package org.schabi.newpipe.local.feed.service
33
import org.schabi.newpipe.database.subscription.NotificationMode
44
import org.schabi.newpipe.database.subscription.SubscriptionEntity
55
import org.schabi.newpipe.extractor.Info
6+
import org.schabi.newpipe.extractor.channel.ChannelInfo
67
import org.schabi.newpipe.extractor.stream.StreamInfoItem
8+
import org.schabi.newpipe.util.image.ImageStrategy
79

10+
/**
11+
* Instances of this class might stay around in memory for some time while fetching the feed,
12+
* because of [FeedLoadManager.BUFFER_COUNT_BEFORE_INSERT]. Therefore this class should contain
13+
* as little data as possible to avoid out of memory errors. In particular, avoid storing whole
14+
* [ChannelInfo] objects, as they might contain raw JSON info in ready channel tabs link handlers.
15+
*/
816
data class FeedUpdateInfo(
917
val uid: Long,
1018
@NotificationMode
1119
val notificationMode: Int,
1220
val name: String,
1321
val avatarUrl: String,
14-
val originalInfo: Info,
22+
val url: String,
23+
val serviceId: Int,
24+
// description and subscriberCount are null if the constructor info is from the fast feed method
25+
val description: String?,
26+
val subscriberCount: Long?,
1527
val streams: List<StreamInfoItem>,
1628
val errors: List<Throwable>,
1729
) {
1830
constructor(
1931
subscription: SubscriptionEntity,
20-
originalInfo: Info,
32+
info: Info,
2133
streams: List<StreamInfoItem>,
2234
errors: List<Throwable>,
2335
) : this(
2436
uid = subscription.uid,
2537
notificationMode = subscription.notificationMode,
26-
name = subscription.name,
27-
avatarUrl = subscription.avatarUrl,
28-
originalInfo = originalInfo,
38+
name = info.name,
39+
avatarUrl = (info as? ChannelInfo)?.avatars?.let {
40+
// if the newly fetched info is not from fast feed, then it contains updated avatars
41+
ImageStrategy.imageListToDbUrl(it)
42+
} ?: subscription.avatarUrl,
43+
url = info.url,
44+
serviceId = info.serviceId,
45+
// there is no description and subscriberCount in the fast feed
46+
description = (info as? ChannelInfo)?.description,
47+
subscriberCount = (info as? ChannelInfo)?.subscriberCount,
2948
streams = streams,
3049
errors = errors,
3150
)
@@ -34,7 +53,7 @@ data class FeedUpdateInfo(
3453
* Integer id, can be used as notification id, etc.
3554
*/
3655
val pseudoId: Int
37-
get() = originalInfo.url.hashCode()
56+
get() = url.hashCode()
3857

3958
lateinit var newStreams: List<StreamInfoItem>
4059
}

app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ import org.schabi.newpipe.database.stream.model.StreamEntity
1212
import org.schabi.newpipe.database.subscription.NotificationMode
1313
import org.schabi.newpipe.database.subscription.SubscriptionDAO
1414
import org.schabi.newpipe.database.subscription.SubscriptionEntity
15-
import org.schabi.newpipe.extractor.Info
1615
import org.schabi.newpipe.extractor.channel.ChannelInfo
1716
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabInfo
18-
import org.schabi.newpipe.extractor.feed.FeedInfo
1917
import org.schabi.newpipe.extractor.stream.StreamInfoItem
2018
import org.schabi.newpipe.local.feed.FeedDatabaseManager
19+
import org.schabi.newpipe.local.feed.service.FeedUpdateInfo
2120
import org.schabi.newpipe.util.ExtractorHelper
2221
import org.schabi.newpipe.util.image.ImageStrategy
2322

@@ -97,19 +96,15 @@ class SubscriptionManager(context: Context) {
9796
}
9897
}
9998

100-
fun updateFromInfo(subscriptionId: Long, info: Info) {
101-
val subscriptionEntity = subscriptionTable.getSubscription(subscriptionId)
102-
103-
if (info is FeedInfo) {
104-
subscriptionEntity.name = info.name
105-
} else if (info is ChannelInfo) {
106-
subscriptionEntity.setData(
107-
info.name,
108-
ImageStrategy.imageListToDbUrl(info.avatars),
109-
info.description,
110-
info.subscriberCount
111-
)
112-
}
99+
fun updateFromInfo(info: FeedUpdateInfo) {
100+
val subscriptionEntity = subscriptionTable.getSubscription(info.uid)
101+
102+
subscriptionEntity.name = info.name
103+
subscriptionEntity.avatarUrl = info.avatarUrl
104+
105+
// these two fields are null if the feed info was fetched using the fast feed method
106+
info.description?.let { subscriptionEntity.description = it }
107+
info.subscriberCount?.let { subscriptionEntity.subscriberCount = it }
113108

114109
subscriptionTable.update(subscriptionEntity)
115110
}

0 commit comments

Comments
 (0)