Mobile Development 10 min read

Performance Optimization for Emoji Deletion in Android EditText Using Profiler and Emoji2

Using Android Profiler we discovered that deleting many custom emojis in an EditText triggers repeated DynamicLayout ChangeWatcher calls, causing up to two‑second lag, and by adopting the emoji2 library’s EmojiSpan rendering with a custom EditableFactory that suppresses onSpanChanged for emoji spans, the lag is eliminated.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Performance Optimization for Emoji Deletion in Android EditText Using Profiler and Emoji2

In real‑world usage, deleting a large number of emojis from the middle of a text can cause a noticeable lag of up to 2 seconds, severely affecting user experience.

Using Android Profiler we traced the latency to the following call chain: SpannableStringBuilder.delete → SpannableStringBuilder.sendSpanChanged → DynamicLayout$ChangeWatcher.onSpanChanged . The onSpanChanged method is invoked many times, and each invocation performs expensive layout calculations.

Profiling revealed that DynamicLayout$ChangeWatcher is called repeatedly for every EmojiSpan affected by the delete operation, which explains the long pause.

Tests showed that system emojis do not exhibit the same lag, suggesting that the issue originates from the handling of custom emojis (e.g., large bitmap size).

The open‑source emoji2 library (androidx.emoji2) adopts a different rendering strategy: it uses EmojiSpan together with TypefaceEmojiRasterizer and draws emojis via canvas.drawText instead of ImageSpan . This approach reduces the number of layout passes.

/**
 * Draws the emoji onto a canvas with origin at (x,y), using the specified paint.
 *
 * @param canvas Canvas to be drawn
 * @param x x-coordinate of the origin of the emoji being drawn
 * @param y y-coordinate of the baseline of the emoji being drawn
 * @param paint Paint used for the text (e.g. color, size, style)
 */
public void draw(@NonNull final Canvas canvas, final float x, final float y,
                @NonNull final Paint paint) {
    final Typeface typeface = mMetadataRepo.getTypeface();
    final Typeface oldTypeface = paint.getTypeface();
    paint.setTypeface(typeface);
    final int charArrayStartIndex = mIndex * 2;
    canvas.drawText(mMetadataRepo.getEmojiCharArray(), charArrayStartIndex, 2, x, y, paint);
    paint.setTypeface(oldTypeface);
}

The library also provides EmojiEditableFactory , which creates a custom Editable for EditTextView . It replaces the default ChangeWatcher with a WatcherWrapper that suppresses onSpanChanged calls when the changed span is an EmojiSpan .

@Override
public Editable newEditable(@NonNull final CharSequence source) {
    if (sWatcherClass != null) {
        return SpannableBuilder.create(sWatcherClass, source);
    }
    return super.newEditable(source);
}
@Override
public void onSpanChanged(Spannable text, Object what, int ostart, int oend, int nstart, int nend) {
    if (mBlockCalls.get() > 0 && isEmojiSpan(what)) {
        return; // block expensive calls for EmojiSpan
    }
    // platform‑specific work‑arounds omitted for brevity
    ((SpanWatcher) mObject).onSpanChanged(text, what, ostart, oend, nstart, nend);
}

By copying EmojiEditableFactory and SpannableBuilder into our project and replacing the isEmojiSpan check with our own custom‑emoji detection, we can apply the same optimisation to custom emojis.

The final integration step is to set the custom factory on the EditTextView :

editTextView.setEditableFactory(EmojiEditableFactory.getInstance());

This reduces the number of DynamicLayout$ChangeWatcher invocations during middle‑deletion of custom emojis, eliminating the lag.

In summary, the Android Profiler is essential for locating performance bottlenecks. The emoji2 source offers a proven solution for optimizing emoji editing, which can be adapted to custom emoji implementations to improve user experience.

performanceemojioptimizationAndroidProfilerEditTextSpannableStringBuilder
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.