Android fresco image loading optimization scheme

Time:2022-5-8
catalogue
  • Optimization background
  • data record
  • Optimization scheme
  • matters needing attention

Optimization background

In general, fresco image loading requires simpledraweeview. This control cannot automatically load images on demand according to its own size, that is, an n × The actual picture loaded behind the UI control of 2n may be 2n × 2N。 This leads to the low memory efficiency in the running process of practical applications, which needs to be optimized.

It is particularly obvious on some entry-level hardware devices. With the growth of program running time, the risk of oom is also increasing.

Fresco version: 1.13.0

data record

The declared control size is 480 × two hundred and seventy


<com.facebook.drawee.view.SimpleDraweeView
  android:id="@+id/simple_drawee_view"
  android:layout_width="480dp"
  android:layout_height="270dp"
  android:layout_alignParentBottom="true"
  android:layout_centerHorizontal="true"
  app:layout_constraintBottom_toBottomOf="parent"
  app:layout_constraintLeft_toLeftOf="parent"
  app:layout_constraintRight_toRightOf="parent"
  app:layout_constraintTop_toTopOf="parent" />

Load the image code and call fresco’s setimageuri


val mImageUrl = "https://static.runoob.com/images/demo/demo4.jpg"
val simple_drawee_view = findViewById<SimpleDraweeView>(R.id.simple_drawee_view)
simple_drawee_view.setImageURI(mImageUrl)

After running dump, the memory is as follows. You can find that the size of the picture in the memory is 1920 × 1080, that is, at this time, simpledraweeview will be loaded according to the original size on the network, and the memory occupation size is 8294475bytes = 7.91mb. A picture occupies nearly 8MB. In the page scene with rich picture display, the total memory occupation of the picture will be particularly beautiful. In case of memory leakage on this page, it will be even more beautiful.

If only 480 is loaded × For 270 size pictures, the memory occupation is 518475bytes = 0.49mb. Compared with the original 1920 × 1080 size, memory reduced by 94%!

Optimization scheme

Fresco provides the resize API, which enables the caller to modify the size of the picture in memory before decoding the picture. The API is roughly as follows


ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
 .setResizeOptions(new ResizeOptions(width, height))
 .build();
PipelineDraweeController controller = Fresco.newDraweeControllerBuilder()
 .setOldController(mDraweeView.getController())
 .setImageRequest(request)
 .build();
mSimpleDraweeView.setController(controller);

Note that this scheme only supports jpg images by default in the lower version. If you need to support other image formats, you need to add isdownsample configuration when setting image pipeline. At the same time, the size of the generated picture can only be roughly controlled, and the picture cannot be modified to a determined size.


.setDownsampleEnabled(true)

This scheme has a significant disadvantage, that is, the page adaptability is very poor. It needs to be called when the width and height of the control can be dynamically obtained in accordance with the life cycle of the view layer. For a mature project, the amount of code changes is too large and the optimization cost is too high. Here, the subclass of simpledraweeview is written for optimization, and the upward transformation is used to minimize the changes in the view layer code. Only the control declaration in the XML layout file needs to be modified. The scheme structure is as follows:

Desiredsimpledraweeview is a subclass of simpledraweeview. You can clearly know the specific width and height of the control in the onwindowfocuschanged method callback, and then load the picture.


public class DesiredSimpleDraweeView extends SimpleDraweeView {

 Uri mUri;
 Object mCallerContext;

 public DesiredSimpleDraweeView(Context context) {
  super(context);
 }

 @Override
 public void setImageURI(Uri uri, Object callerContext) {
  mUri = uri;
  mCallerContext = callerContext;
 }

 private void setImageURI(int width, int height) {
  try {
   ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(mUri)
     .setResizeOptions(new ResizeOptions(width, height))
     .build();
   DraweeController controller =
     getControllerBuilder()
       .setOldController(getController())
       .setImageRequest(imageRequest)
       .build();
   setController(controller);
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }

 @Override
 public void onWindowFocusChanged(boolean hasWindowFocus) {
  super.onWindowFocusChanged(hasWindowFocus);
  if (hasWindowFocus) {
   setImageURI(getWidth(), getHeight());
  }
 }
}

Copy the setimageuri (URI, object) method, temporarily store the URI and callercontext, and load the picture according to the width and height of the control after the onwindowfoucuschanged callback. In this way, with the upward transformation, the code of the view layer does not need to be changed. After replacing the control declaration in the XML file, the memory utilization can be significantly improved.

matters needing attention

Performance optimization is an endless road. There is no best scheme, only the most appropriate scheme. If you want to accurately control the image loading size and load on demand, glide may be a better choice.

The above is the details of the Android fresco image loading optimization scheme. For more information about Android fresco image loading optimization, please pay attention to other relevant articles of developeppaer!