Mobile Development 18 min read

Comparative Analysis of Native Image Loading and External Texture Solutions in Flutter

This article examines Flutter's native image loading mechanisms, compares them with Android's traditional image frameworks, discusses the challenges of duplicated resources and memory usage, and details two external‑texture approaches—ShareContext and shared memory—providing code examples and practical recommendations for mobile projects.

IEG Growth Platform Technology Team
IEG Growth Platform Technology Team
IEG Growth Platform Technology Team
Comparative Analysis of Native Image Loading and External Texture Solutions in Flutter

Native Image Loading in Flutter

Flutter supports several native image sources through the Image.network() , Image.file() , Image.asset() and Image.memory() constructors. Each constructor delegates to a subclass of ImageProvider that overrides the load method.

The core loading logic is illustrated by the following snippet, which resolves an image key, checks the ImageCache , and invokes load when the image is not cached:

void resolveStreamForKey(ImageConfiguration configuration, ImageStream stream, T key, ImageErrorListener handleError) {
    …………
    final ImageStreamCompleter? completer = PaintingBinding.instance!.imageCache!.putIfAbsent(
        key,
        () => load(key, PaintingBinding.instance!.instantiateImageCodec),
        onError: handleError,
    );
    if (completer != null) {
        stream.setCompleter(completer);
    }
}

The ImageCache stores images in a Map<Object, _CachedImage> and exposes maximumSize and maximumSizeBytes properties for configuring the total number of cached images and their memory footprint.

Image Loading on Android

Android loads images into Bitmap or Drawable objects via network, file, or resource parsing. Popular third‑party libraries—Picasso, Glide, and Fresco—provide mature caching and processing capabilities.

Problems with Separate Resource Pools

When a project contains both Flutter and native modules, each platform allocates its own memory region for images, leading to duplicated resources, increased package size, higher memory consumption, and the inability to share native image‑processing features such as filters or watermarks.

Industry Solutions: External Textures

In 2018, Xianyu published an article about using external textures to share native texture data with Flutter for camera preview and video playback. The same concept can be applied to image rendering.

Two main implementations exist:

ShareContext / ShareGroup : creates an EGL (or iOS EAGL) shared context so that textures can be accessed across the Flutter and native OpenGL environments.

Shared Memory (EGLImageKHR) : leverages the EGLImageKHR extension to share 2D image data between EGL clients without modifying the Flutter engine.

ShareContext Implementation

The EGL shared‑context creation is performed with eglCreateContext using the share_context parameter:

/**
 * share_context:
 * Specifies another EGL rendering context with which to share data.
 */
EGLContext eglCreateContext(EGLDisplay display,
    EGLConfig config,
    EGLContext share_context,
    const EGLint * attrib_list);

By injecting the Flutter EGL context into the native context, the native platform can render textures that Flutter later consumes. This method requires engine modifications and is invasive.

Shared‑Memory Implementation

Flutter provides a built‑in TextureRegistry that creates a SurfaceTexture and registers it with a generated texture ID. The Android side draws a Bitmap onto the SurfaceTexture and returns the ID via a method channel:

new MethodChannel(getFlutterView(), "CHANNEL").setMethodCallHandler(new MethodCallHandler() {
    @Override
    public void onMethodCall(MethodCall call, Result result) {
        TextureRegistry textureRegistry = registrar.textures();
        TextureRegistry.SurfaceTextureEntry entry = textureRegistry.createSurfaceTexture();
        long textureId = entry.id();
        SurfaceTexture surfaceTexture = entry.surfaceTexture();
        Bitmap bitmap = createBitmapYouNeed();
        Surface surface = new Surface(surfaceTexture);
        Canvas canvas = surface.lockCanvas(rect);
        canvas.drawBitmap(bitmap, null, rect, null);
        bitmap.recycle();
        surface.unlockCanvasAndPost(canvas);
        result.success(textureId);
    }
});

Flutter retrieves the texture ID and displays it with the Texture widget:

static const platform = const MethodChannel('CHANNEL_NAME');
Future
getTextureView() async {
  int textureId = await platform.invokeMethod('loadTexture');
  return Container(child: Texture(textureId: textureId));
}

Internally, the texture ID is registered with the native engine ( FlutterRenderer , FlutterJNI , platform_view_android.cc , texture.cc ) and later fetched by TextureLayer during scene construction.

Comparison and Recommendations

For pure Flutter projects, the built‑in ImageCache combined with list pre‑loading usually suffices. When complex texture processing or native image‑optimisation is required, external textures become valuable. In hybrid projects, the choice depends on how many native images need reuse and whether native processing capabilities must be leveraged.

Conclusion

Flutter’s native image loading is straightforward but limited to a single‑layer cache. Android/iOS provide richer caching frameworks. External‑texture techniques—ShareContext and shared memory—allow Flutter to render native textures, with shared memory being the preferred, non‑intrusive solution. Developers should weigh the maintenance cost of engine modifications against the performance benefits when selecting an image‑loading strategy.

Flutterexternal-textureiOSAndroidcachingImage Loadingtexture-sharing
IEG Growth Platform Technology Team
Written by

IEG Growth Platform Technology Team

Official account of Tencent IEG Growth Platform Technology Team, showcasing cutting‑edge achievements across front‑end, back‑end, client, algorithm, testing and other domains.

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.