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

Commit 654c615c authored by Steve Elliott's avatar Steve Elliott
Browse files

Defer MessagingGroup#recycle until bind completes

There is a "race condition" where a MessagingGroup is recycled while the
contents of that group are being used elsewhere in the
ConversationLayout, namely in the "image message container" used to show
the most recent image message in the collapsed state.

This state isn't cleared until later in the bind() process, which
unfortunately depends on the groups being updated. For that reason, we
defer all synchronous calls to recycle() until the end of bind(), which
will ensure that the old groups are still around as long as necessary.

Fixes: 216202070
Test: manual
Change-Id: Idef815d54690544615512bd2bd1006f172403e18
(cherry picked from commit 2a68270c)
parent 68afc54a
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -150,6 +150,7 @@ public class ConversationLayout extends FrameLayout
    private Icon mShortcutIcon;
    private View mAppNameDivider;
    private TouchDelegateComposite mTouchDelegate = new TouchDelegateComposite(this);
    private ArrayList<MessagingGroup> mToRecycle = new ArrayList<>();

    public ConversationLayout(@NonNull Context context) {
        super(context);
@@ -472,6 +473,12 @@ public class ConversationLayout extends FrameLayout
        updateTitleAndNamesDisplay();

        updateConversationLayout();

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

    /**
@@ -745,18 +752,18 @@ public class ConversationLayout extends FrameLayout
            MessagingGroup group = oldGroups.get(i);
            if (!mGroups.contains(group)) {
                List<MessagingMessage> messages = group.getMessages();
                Runnable endRunnable = () -> {
                    mMessagingLinearLayout.removeTransientView(group);
                    group.recycle();
                };

                boolean wasShown = group.isShown();
                mMessagingLinearLayout.removeView(group);
                if (wasShown && !MessagingLinearLayout.isGone(group)) {
                    mMessagingLinearLayout.addTransientView(group, 0);
                    group.removeGroupAnimated(endRunnable);
                    group.removeGroupAnimated(() -> {
                        mMessagingLinearLayout.removeTransientView(group);
                        group.recycle();
                    });
                } else {
                    endRunnable.run();
                    // Defer recycling until after the update is done, since we may still need the
                    // old group around to perform other updates.
                    mToRecycle.add(group);
                }
                mMessages.removeAll(messages);
                mHistoricMessages.removeAll(messages);