Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c52f488 authored by Steve Elliott's avatar Steve Elliott
Browse files

Defer MessagingMessage#recycle until bind ends

See ag/17158486 for context.

Fixes: 216202070
Test: manual
Change-Id: I924f917fbf757d2c3866fcd60de2fbfccae2eb6a
Merged-In: I924f917fbf757d2c3866fcd60de2fbfccae2eb6a
(cherry picked from commit 88f4dbce)
parent a4b205e2
Loading
Loading
Loading
Loading
+9 −8
Original line number Original line Diff line number Diff line
@@ -66,7 +66,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.Objects;
import java.util.Objects;
import java.util.function.Consumer;


/**
/**
 * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal
 * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal
@@ -76,8 +75,6 @@ import java.util.function.Consumer;
public class ConversationLayout extends FrameLayout
public class ConversationLayout extends FrameLayout
        implements ImageMessageConsumer, IMessagingLayout {
        implements ImageMessageConsumer, IMessagingLayout {


    private static final Consumer<MessagingMessage> REMOVE_MESSAGE
            = MessagingMessage::removeMessage;
    public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f);
    public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f);
    public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
    public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
    public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
    public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
@@ -150,7 +147,7 @@ public class ConversationLayout extends FrameLayout
    private Icon mShortcutIcon;
    private Icon mShortcutIcon;
    private View mAppNameDivider;
    private View mAppNameDivider;
    private TouchDelegateComposite mTouchDelegate = new TouchDelegateComposite(this);
    private TouchDelegateComposite mTouchDelegate = new TouchDelegateComposite(this);
    private ArrayList<MessagingGroup> mToRecycle = new ArrayList<>();
    private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>();


    public ConversationLayout(@NonNull Context context) {
    public ConversationLayout(@NonNull Context context) {
        super(context);
        super(context);
@@ -463,8 +460,12 @@ public class ConversationLayout extends FrameLayout
        removeGroups(oldGroups);
        removeGroups(oldGroups);


        // Let's remove the remaining messages
        // Let's remove the remaining messages
        mMessages.forEach(REMOVE_MESSAGE);
        for (MessagingMessage message : mMessages) {
        mHistoricMessages.forEach(REMOVE_MESSAGE);
            message.removeMessage(mToRecycle);
        }
        for (MessagingMessage historicMessage : mHistoricMessages) {
            historicMessage.removeMessage(mToRecycle);
        }


        mMessages = messages;
        mMessages = messages;
        mHistoricMessages = historicMessages;
        mHistoricMessages = historicMessages;
@@ -475,8 +476,8 @@ public class ConversationLayout extends FrameLayout
        updateConversationLayout();
        updateConversationLayout();


        // Recycle everything at the end of the update, now that we know it's no longer needed.
        // Recycle everything at the end of the update, now that we know it's no longer needed.
        for (MessagingGroup group : mToRecycle) {
        for (MessagingLinearLayout.MessagingChild child : mToRecycle) {
            group.recycle();
            child.recycle();
        }
        }
        mToRecycle.clear();
        mToRecycle.clear();
    }
    }
+7 −7
Original line number Original line Diff line number Diff line
@@ -263,7 +263,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
        return createdGroup;
        return createdGroup;
    }
    }


    public void removeMessage(MessagingMessage messagingMessage) {
    public void removeMessage(MessagingMessage messagingMessage,
            ArrayList<MessagingLinearLayout.MessagingChild> toRecycle) {
        View view = messagingMessage.getView();
        View view = messagingMessage.getView();
        boolean wasShown = view.isShown();
        boolean wasShown = view.isShown();
        ViewGroup messageParent = (ViewGroup) view.getParent();
        ViewGroup messageParent = (ViewGroup) view.getParent();
@@ -271,15 +272,14 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
            return;
            return;
        }
        }
        messageParent.removeView(view);
        messageParent.removeView(view);
        Runnable recycleRunnable = () -> {
            messageParent.removeTransientView(view);
            messagingMessage.recycle();
        };
        if (wasShown && !MessagingLinearLayout.isGone(view)) {
        if (wasShown && !MessagingLinearLayout.isGone(view)) {
            messageParent.addTransientView(view, 0);
            messageParent.addTransientView(view, 0);
            performRemoveAnimation(view, recycleRunnable);
            performRemoveAnimation(view, () -> {
                messageParent.removeTransientView(view);
                messagingMessage.recycle();
            });
        } else {
        } else {
            recycleRunnable.run();
            toRecycle.add(messagingMessage);
        }
        }
    }
    }


+18 −11
Original line number Original line Diff line number Diff line
@@ -51,7 +51,6 @@ import com.android.internal.util.ContrastColorUtil;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.function.Consumer;


/**
/**
 * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal
 * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal
@@ -62,8 +61,6 @@ public class MessagingLayout extends FrameLayout
        implements ImageMessageConsumer, IMessagingLayout {
        implements ImageMessageConsumer, IMessagingLayout {


    private static final float COLOR_SHIFT_AMOUNT = 60;
    private static final float COLOR_SHIFT_AMOUNT = 60;
    private static final Consumer<MessagingMessage> REMOVE_MESSAGE
            = MessagingMessage::removeMessage;
    public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f);
    public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f);
    public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
    public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
    public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
    public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
@@ -89,6 +86,7 @@ public class MessagingLayout extends FrameLayout
    private boolean mIsCollapsed;
    private boolean mIsCollapsed;
    private ImageResolver mImageResolver;
    private ImageResolver mImageResolver;
    private CharSequence mConversationTitle;
    private CharSequence mConversationTitle;
    private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>();


    public MessagingLayout(@NonNull Context context) {
    public MessagingLayout(@NonNull Context context) {
        super(context);
        super(context);
@@ -212,8 +210,12 @@ public class MessagingLayout extends FrameLayout
        removeGroups(oldGroups);
        removeGroups(oldGroups);


        // Let's remove the remaining messages
        // Let's remove the remaining messages
        mMessages.forEach(REMOVE_MESSAGE);
        for (MessagingMessage message : mMessages) {
        mHistoricMessages.forEach(REMOVE_MESSAGE);
            message.removeMessage(mToRecycle);
        }
        for (MessagingMessage historicMessage : mHistoricMessages) {
            historicMessage.removeMessage(mToRecycle);
        }


        mMessages = messages;
        mMessages = messages;
        mHistoricMessages = historicMessages;
        mHistoricMessages = historicMessages;
@@ -223,6 +225,12 @@ public class MessagingLayout extends FrameLayout
        // after groups are finalized, hide the first sender name if it's showing as the title
        // after groups are finalized, hide the first sender name if it's showing as the title
        mPeopleHelper.maybeHideFirstSenderName(mGroups, mIsOneToOne, mConversationTitle);
        mPeopleHelper.maybeHideFirstSenderName(mGroups, mIsOneToOne, mConversationTitle);
        updateImageMessages();
        updateImageMessages();

        // Recycle everything at the end of the update, now that we know it's no longer needed.
        for (MessagingLinearLayout.MessagingChild child : mToRecycle) {
            child.recycle();
        }
        mToRecycle.clear();
    }
    }


    private void updateImageMessages() {
    private void updateImageMessages() {
@@ -263,18 +271,17 @@ public class MessagingLayout extends FrameLayout
            MessagingGroup group = oldGroups.get(i);
            MessagingGroup group = oldGroups.get(i);
            if (!mGroups.contains(group)) {
            if (!mGroups.contains(group)) {
                List<MessagingMessage> messages = group.getMessages();
                List<MessagingMessage> messages = group.getMessages();
                Runnable endRunnable = () -> {
                    mMessagingLinearLayout.removeTransientView(group);
                    group.recycle();
                };


                boolean wasShown = group.isShown();
                boolean wasShown = group.isShown();
                mMessagingLinearLayout.removeView(group);
                mMessagingLinearLayout.removeView(group);
                if (wasShown && !MessagingLinearLayout.isGone(group)) {
                if (wasShown && !MessagingLinearLayout.isGone(group)) {
                    mMessagingLinearLayout.addTransientView(group, 0);
                    mMessagingLinearLayout.addTransientView(group, 0);
                    group.removeGroupAnimated(endRunnable);
                    group.removeGroupAnimated(() -> {
                        mMessagingLinearLayout.removeTransientView(group);
                        group.recycle();
                    });
                } else {
                } else {
                    endRunnable.run();
                    mToRecycle.add(group);
                }
                }
                mMessages.removeAll(messages);
                mMessages.removeAll(messages);
                mHistoricMessages.removeAll(messages);
                mHistoricMessages.removeAll(messages);
+1 −0
Original line number Original line Diff line number Diff line
@@ -365,6 +365,7 @@ public class MessagingLinearLayout extends ViewGroup {
        default int getExtraSpacing() {
        default int getExtraSpacing() {
            return 0;
            return 0;
        }
        }
        void recycle();
    }
    }


    public static class LayoutParams extends MarginLayoutParams {
    public static class LayoutParams extends MarginLayoutParams {
+3 −2
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.app.ActivityManager;
import android.app.Notification;
import android.app.Notification;
import android.view.View;
import android.view.View;


import java.util.ArrayList;
import java.util.Objects;
import java.util.Objects;


/**
/**
@@ -96,8 +97,8 @@ public interface MessagingMessage extends MessagingLinearLayout.MessagingChild {
        return sameAs(message.getMessage());
        return sameAs(message.getMessage());
    }
    }


    default void removeMessage() {
    default void removeMessage(ArrayList<MessagingLinearLayout.MessagingChild> toRecycle) {
        getGroup().removeMessage(this);
        getGroup().removeMessage(this, toRecycle);
    }
    }


    default void setMessagingGroup(MessagingGroup group) {
    default void setMessagingGroup(MessagingGroup group) {