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).
This commit is contained in:
parent
35c1dfd145
commit
80f33daeeb
|
@ -58,7 +58,7 @@ class NotificationHelper(val context: Context) {
|
|||
.setAutoCancel(true)
|
||||
.setCategory(NotificationCompat.CATEGORY_SOCIAL)
|
||||
.setGroupSummary(true)
|
||||
.setGroup(data.originalInfo.url)
|
||||
.setGroup(data.url)
|
||||
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
|
||||
|
||||
// Build a summary notification for Android versions < 7.0
|
||||
|
@ -73,7 +73,7 @@ class NotificationHelper(val context: Context) {
|
|||
context,
|
||||
data.pseudoId,
|
||||
NavigationHelper
|
||||
.getChannelIntent(context, data.originalInfo.serviceId, data.originalInfo.url)
|
||||
.getChannelIntent(context, data.serviceId, data.url)
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
|
||||
0,
|
||||
false
|
||||
|
@ -88,7 +88,7 @@ class NotificationHelper(val context: Context) {
|
|||
|
||||
// Show individual stream notifications, set channel icon only if there is actually
|
||||
// one
|
||||
showStreamNotifications(newStreams, data.originalInfo.serviceId, bitmap)
|
||||
showStreamNotifications(newStreams, data.serviceId, bitmap)
|
||||
// Show summary notification
|
||||
manager.notify(data.pseudoId, summaryBuilder.build())
|
||||
|
||||
|
@ -97,7 +97,7 @@ class NotificationHelper(val context: Context) {
|
|||
|
||||
override fun onBitmapFailed(e: Exception, errorDrawable: Drawable) {
|
||||
// Show individual stream notifications
|
||||
showStreamNotifications(newStreams, data.originalInfo.serviceId, null)
|
||||
showStreamNotifications(newStreams, data.serviceId, null)
|
||||
// Show summary notification
|
||||
manager.notify(data.pseudoId, summaryBuilder.build())
|
||||
iconLoadingTargets.remove(this) // allow it to be garbage-collected
|
||||
|
|
|
@ -277,14 +277,14 @@ class FeedLoadManager(private val context: Context) {
|
|||
notification.value!!.newStreams = filterNewStreams(info.streams)
|
||||
|
||||
feedDatabaseManager.upsertAll(info.uid, info.streams)
|
||||
subscriptionManager.updateFromInfo(info.uid, info.originalInfo)
|
||||
subscriptionManager.updateFromInfo(info)
|
||||
|
||||
if (info.errors.isNotEmpty()) {
|
||||
feedResultsHolder.addErrors(
|
||||
info.errors.map {
|
||||
FeedLoadService.RequestException(
|
||||
info.uid,
|
||||
"${info.originalInfo.serviceId}:${info.originalInfo.url}",
|
||||
"${info.serviceId}:${info.url}",
|
||||
it
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,29 +3,48 @@ package org.schabi.newpipe.local.feed.service
|
|||
import org.schabi.newpipe.database.subscription.NotificationMode
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity
|
||||
import org.schabi.newpipe.extractor.Info
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfo
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
||||
import org.schabi.newpipe.util.image.ImageStrategy
|
||||
|
||||
/**
|
||||
* Instances of this class might stay around in memory for some time while fetching the feed,
|
||||
* because of [FeedLoadManager.BUFFER_COUNT_BEFORE_INSERT]. Therefore this class should contain
|
||||
* as little data as possible to avoid out of memory errors. In particular, avoid storing whole
|
||||
* [ChannelInfo] objects, as they might contain raw JSON info in ready channel tabs link handlers.
|
||||
*/
|
||||
data class FeedUpdateInfo(
|
||||
val uid: Long,
|
||||
@NotificationMode
|
||||
val notificationMode: Int,
|
||||
val name: String,
|
||||
val avatarUrl: String,
|
||||
val originalInfo: Info,
|
||||
val url: String,
|
||||
val serviceId: Int,
|
||||
// description and subscriberCount are null if the constructor info is from the fast feed method
|
||||
val description: String?,
|
||||
val subscriberCount: Long?,
|
||||
val streams: List<StreamInfoItem>,
|
||||
val errors: List<Throwable>,
|
||||
) {
|
||||
constructor(
|
||||
subscription: SubscriptionEntity,
|
||||
originalInfo: Info,
|
||||
info: Info,
|
||||
streams: List<StreamInfoItem>,
|
||||
errors: List<Throwable>,
|
||||
) : this(
|
||||
uid = subscription.uid,
|
||||
notificationMode = subscription.notificationMode,
|
||||
name = subscription.name,
|
||||
avatarUrl = subscription.avatarUrl,
|
||||
originalInfo = originalInfo,
|
||||
name = info.name,
|
||||
avatarUrl = (info as? ChannelInfo)?.avatars?.let {
|
||||
// if the newly fetched info is not from fast feed, then it contains updated avatars
|
||||
ImageStrategy.imageListToDbUrl(it)
|
||||
} ?: subscription.avatarUrl,
|
||||
url = info.url,
|
||||
serviceId = info.serviceId,
|
||||
// there is no description and subscriberCount in the fast feed
|
||||
description = (info as? ChannelInfo)?.description,
|
||||
subscriberCount = (info as? ChannelInfo)?.subscriberCount,
|
||||
streams = streams,
|
||||
errors = errors,
|
||||
)
|
||||
|
@ -34,7 +53,7 @@ data class FeedUpdateInfo(
|
|||
* Integer id, can be used as notification id, etc.
|
||||
*/
|
||||
val pseudoId: Int
|
||||
get() = originalInfo.url.hashCode()
|
||||
get() = url.hashCode()
|
||||
|
||||
lateinit var newStreams: List<StreamInfoItem>
|
||||
}
|
||||
|
|
|
@ -12,12 +12,11 @@ import org.schabi.newpipe.database.stream.model.StreamEntity
|
|||
import org.schabi.newpipe.database.subscription.NotificationMode
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionDAO
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity
|
||||
import org.schabi.newpipe.extractor.Info
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfo
|
||||
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabInfo
|
||||
import org.schabi.newpipe.extractor.feed.FeedInfo
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
||||
import org.schabi.newpipe.local.feed.FeedDatabaseManager
|
||||
import org.schabi.newpipe.local.feed.service.FeedUpdateInfo
|
||||
import org.schabi.newpipe.util.ExtractorHelper
|
||||
import org.schabi.newpipe.util.image.ImageStrategy
|
||||
|
||||
|
@ -97,19 +96,15 @@ class SubscriptionManager(context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
fun updateFromInfo(subscriptionId: Long, info: Info) {
|
||||
val subscriptionEntity = subscriptionTable.getSubscription(subscriptionId)
|
||||
fun updateFromInfo(info: FeedUpdateInfo) {
|
||||
val subscriptionEntity = subscriptionTable.getSubscription(info.uid)
|
||||
|
||||
if (info is FeedInfo) {
|
||||
subscriptionEntity.name = info.name
|
||||
} else if (info is ChannelInfo) {
|
||||
subscriptionEntity.setData(
|
||||
info.name,
|
||||
ImageStrategy.imageListToDbUrl(info.avatars),
|
||||
info.description,
|
||||
info.subscriberCount
|
||||
)
|
||||
}
|
||||
subscriptionEntity.name = info.name
|
||||
subscriptionEntity.avatarUrl = info.avatarUrl
|
||||
|
||||
// these two fields are null if the feed info was fetched using the fast feed method
|
||||
info.description?.let { subscriptionEntity.description = it }
|
||||
info.subscriberCount?.let { subscriptionEntity.subscriberCount = it }
|
||||
|
||||
subscriptionTable.update(subscriptionEntity)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue