Fix conversation memory leak.
This commit is contained in:
parent
65dc0d3f34
commit
057ffdbaaf
5 changed files with 17 additions and 63 deletions
|
@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.conversation.v2.items
|
|||
|
||||
import android.net.Uri
|
||||
import android.view.View
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.Observer
|
||||
import com.bumptech.glide.RequestManager
|
||||
import io.mockk.mockk
|
||||
|
@ -203,8 +204,8 @@ class V2ConversationItemShapeTest {
|
|||
|
||||
private val colorizer = Colorizer()
|
||||
|
||||
override val lifecycleOwner: LifecycleOwner = mockk(relaxed = true)
|
||||
override val displayMode: ConversationItemDisplayMode = ConversationItemDisplayMode.Standard
|
||||
|
||||
override val clickListener: ConversationAdapter.ItemClickListener = FakeConversationItemClickListener
|
||||
override val selectedItems: Set<MultiselectPart> = emptySet()
|
||||
override val isMessageRequestAccepted: Boolean = true
|
||||
|
|
|
@ -66,7 +66,7 @@ import java.util.Locale
|
|||
import java.util.Optional
|
||||
|
||||
class ConversationAdapterV2(
|
||||
private val lifecycleOwner: LifecycleOwner,
|
||||
override val lifecycleOwner: LifecycleOwner,
|
||||
override val requestManager: RequestManager,
|
||||
override val clickListener: ItemClickListener,
|
||||
private var hasWallpaper: Boolean,
|
||||
|
@ -356,34 +356,6 @@ class ConversationAdapterV2(
|
|||
}
|
||||
}
|
||||
|
||||
private inner class OutgoingTextOnlyViewHolder(itemView: View) : ConversationViewHolder<OutgoingTextOnly>(itemView) {
|
||||
override fun bind(model: OutgoingTextOnly) {
|
||||
bindable.setEventListener(clickListener)
|
||||
|
||||
if (bindPayloadsIfAvailable()) {
|
||||
return
|
||||
}
|
||||
|
||||
bindable.bind(
|
||||
lifecycleOwner,
|
||||
model.conversationMessage,
|
||||
previousMessage,
|
||||
nextMessage,
|
||||
requestManager,
|
||||
Locale.getDefault(),
|
||||
_selected,
|
||||
model.conversationMessage.threadRecipient,
|
||||
searchQuery,
|
||||
false,
|
||||
hasWallpaper && displayMode.displayWallpaper(),
|
||||
isMessageRequestAccepted,
|
||||
model.conversationMessage == inlineContent,
|
||||
colorizer,
|
||||
displayMode
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class OutgoingMediaViewHolder(itemView: View) : ConversationViewHolder<OutgoingMedia>(itemView) {
|
||||
override fun bind(model: OutgoingMedia) {
|
||||
bindable.setEventListener(clickListener)
|
||||
|
@ -413,34 +385,6 @@ class ConversationAdapterV2(
|
|||
}
|
||||
}
|
||||
|
||||
private inner class IncomingTextOnlyViewHolder(itemView: View) : ConversationViewHolder<IncomingTextOnly>(itemView) {
|
||||
override fun bind(model: IncomingTextOnly) {
|
||||
bindable.setEventListener(clickListener)
|
||||
|
||||
if (bindPayloadsIfAvailable()) {
|
||||
return
|
||||
}
|
||||
|
||||
bindable.bind(
|
||||
lifecycleOwner,
|
||||
model.conversationMessage,
|
||||
previousMessage,
|
||||
nextMessage,
|
||||
requestManager,
|
||||
Locale.getDefault(),
|
||||
_selected,
|
||||
model.conversationMessage.threadRecipient,
|
||||
searchQuery,
|
||||
false,
|
||||
hasWallpaper && displayMode.displayWallpaper(),
|
||||
isMessageRequestAccepted,
|
||||
model.conversationMessage == inlineContent,
|
||||
colorizer,
|
||||
displayMode
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class IncomingMediaViewHolder(itemView: View) : ConversationViewHolder<IncomingMedia>(itemView) {
|
||||
override fun bind(model: IncomingMedia) {
|
||||
bindable.setEventListener(clickListener)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
package org.thoughtcrime.securesms.conversation.v2.items
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.bumptech.glide.RequestManager
|
||||
import org.thoughtcrime.securesms.conversation.ConversationAdapter
|
||||
import org.thoughtcrime.securesms.conversation.ConversationItemDisplayMode
|
||||
|
@ -17,6 +18,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord
|
|||
* visible to an inner class.
|
||||
*/
|
||||
interface V2ConversationContext {
|
||||
val lifecycleOwner: LifecycleOwner
|
||||
val requestManager: RequestManager
|
||||
val displayMode: ConversationItemDisplayMode
|
||||
val clickListener: ConversationAdapter.ItemClickListener
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.signal.core.util.StringUtil
|
||||
import org.signal.core.util.dp
|
||||
|
@ -44,7 +45,6 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
|||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientForeverObserver
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.InterceptableLongClickCopyLinkSpan
|
||||
import org.thoughtcrime.securesms.util.LongClickMovementMethod
|
||||
|
@ -70,7 +70,7 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
|
|||
private val binding: V2ConversationItemTextOnlyBindingBridge,
|
||||
private val conversationContext: V2ConversationContext,
|
||||
footerDelegate: V2FooterPositionDelegate = V2FooterPositionDelegate(binding)
|
||||
) : V2ConversationItemViewHolder<Model>(binding.root, conversationContext), Multiselectable, InteractiveConversationElement, RecipientForeverObserver {
|
||||
) : V2ConversationItemViewHolder<Model>(binding.root, conversationContext), Multiselectable, InteractiveConversationElement, Observer<Recipient> {
|
||||
|
||||
companion object {
|
||||
private val STYLE_FACTORY = SearchUtil.StyleFactory { arrayOf<CharacterStyle>(BackgroundColorSpan(Color.YELLOW), ForegroundColorSpan(Color.BLACK)) }
|
||||
|
@ -210,12 +210,12 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
|
|||
check(model is ConversationMessageElement)
|
||||
|
||||
if (this::conversationMessage.isInitialized) {
|
||||
conversationMessage.messageRecord.fromRecipient.live().removeForeverObserver(this)
|
||||
conversationMessage.messageRecord.fromRecipient.live().removeObserver(this)
|
||||
}
|
||||
|
||||
conversationMessage = model.conversationMessage
|
||||
if (conversationMessage.threadRecipient.isGroup) {
|
||||
conversationMessage.messageRecord.fromRecipient.live().observeForever(this)
|
||||
conversationMessage.messageRecord.fromRecipient.live().observe(conversationContext.lifecycleOwner, this)
|
||||
}
|
||||
|
||||
shape = shapeDelegate.setMessageShape(
|
||||
|
@ -790,7 +790,7 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onRecipientChanged(recipient: Recipient) {
|
||||
override fun onChanged(recipient: Recipient) {
|
||||
presentSender()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,6 +102,13 @@ public final class LiveRecipient {
|
|||
ThreadUtil.postToMain(() -> observableLiveData.observe(owner, observer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes observer of this data.
|
||||
*/
|
||||
public void removeObserver(@NonNull Observer<Recipient> observer) {
|
||||
ThreadUtil.runOnMain(() -> observableLiveData.removeObserver(observer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all observers of this data registered for the given LifecycleOwner.
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue