Load invisible pictures through glide

Time:2021-11-28

Today, I met a need to generate pictures and QR codes when I click to share.

That is, generate a bitmap from a layout file with pictures and QR codes. Of course, this layout file is generated in the background and is not visible. At this time, you will find that there is no response to loading pictures with glide.

Source code analysis:

Trace to getSize method in viewtarget:

void getSize(@NonNull SizeReadyCallback cb) {
      int currentWidth = getTargetWidth();
      int currentHeight = getTargetHeight();
      if (isViewStateAndSizeValid(currentWidth, currentHeight)) {
        cb.onSizeReady(currentWidth, currentHeight);
        return;
      }

      // We want to notify callbacks in the order they were added and we only expect one or two
      // callbacks to be added a time, so a List is a reasonable choice.
      if (!cbs.contains(cb)) {
        cbs.add(cb);
      }
      if (layoutListener == null) {
        ViewTreeObserver observer = view.getViewTreeObserver();
        layoutListener = new SizeDeterminerLayoutListener(this);
        observer.addOnPreDrawListener(layoutListener);
      }
    }

If the width and height of the obtained view are not greater than 0, cb.onsizeready (currentwidth, currentheight) will not be used; Instead of going down, a listener will be set for viewtreeobserver.

 

Let’s go to the gettargetwidth () method:

private int getTargetWidth() {
  int horizontalPadding = view.getPaddingLeft() + view.getPaddingRight();
  LayoutParams layoutParams = view.getLayoutParams();
  int layoutParamSize = layoutParams != null ? layoutParams.width : PENDING_SIZE;
  return getTargetDimen(view.getWidth(), layoutParamSize, horizontalPadding);
}

 

Then go to:

private int getTargetDimen(int viewSize, int paramSize, int paddingSize) {
  // We consider the View state as valid if the View has non-null layout params and a non-zero
  // layout params width and height. This is imperfect. We're making an assumption that View
  // parents will obey their child's layout parameters, which isn't always the case.
  int adjustedParamSize = paramSize - paddingSize;
  if (adjustedParamSize > 0) {
    return adjustedParamSize;
  }
  // Since we always prefer layout parameters with fixed sizes, even if waitForLayout is true,
  // we might as well ignore it and just return the layout parameters above if we have them.
  // Otherwise we should wait for a layout pass before checking the View's dimensions.
  if (waitForLayout && view.isLayoutRequested()) {
    return PENDING_SIZE;
  }
  // We also consider the View state valid if the View has a non-zero width and height. This
  // means that the View has gone through at least one layout pass. It does not mean the Views
  // width and height are from the current layout pass. For example, if a View is re-used in
  // RecyclerView or ListView, this width/height may be from an old position. In some cases
  // the dimensions of the View at the old position may be different than the dimensions of the
  // View in the new position because the LayoutManager/ViewParent can arbitrarily decide to
  // change them. Nevertheless, in most cases this should be a reasonable choice.
  int adjustedViewSize = viewSize - paddingSize;
  if (adjustedViewSize > 0) {
    return adjustedViewSize;
  }
  // Finally we consider the view valid if the layout parameter size is set to wrap_content.
  // It's difficult for Glide to figure out what to do here. Although Target.SIZE_ORIGINAL is a
  // coherent choice, it's extremely dangerous because original images may be much too large to
  // fit in memory or so large that only a couple can fit in memory, causing OOMs. If users want
  // the original image, they can always use .override(Target.SIZE_ORIGINAL). Since wrap_content
  // may never resolve to a real size unless we load something, we aim for a square whose length
  // is the largest screen size. That way we're loading something and that something has some
  // hope of being downsampled to a size that the device can support. We also log a warning that
  // tries to explain what Glide is doing and why some alternatives are preferable.
  // Since WRAP_CONTENT is sometimes used as a default layout parameter, we always wait for
  // layout to complete before using this fallback parameter (ConstraintLayout among others).
  if (!view.isLayoutRequested() && paramSize == LayoutParams.WRAP_CONTENT) {
    if (Log.isLoggable(TAG, Log.INFO)) {
      Log.i(
          TAG,
          "Glide treats LayoutParams.WRAP_CONTENT as a request for an image the size of this"
              + " device's screen dimensions. If you want to load the original image and are"
              + " ok with the corresponding memory cost and OOMs (depending on the input size),"
              + " use override(Target.SIZE_ORIGINAL). Otherwise, use LayoutParams.MATCH_PARENT,"
              + " set layout_width and layout_height to fixed dimension, or use .override()"
              + " with fixed dimensions.");
    }
    return getMaxDisplayLength(view.getContext());
  }
  // If the layout parameters are < padding, the view size is < padding, or the layout
  // parameters are set to match_parent or wrap_content and no layout has occurred, we should
  // wait for layout and repeat.
  return PENDING_SIZE;
}

Namely: when

Layoutparamsize – returns the result when padding is greater than 0.

View. Getwidth() – this result is returned when padding is greater than 0.

When the layouparam of ImageView in the layout loaded in the background is not set to an exact value, it returns pending_ Size = = 0. At this time, as mentioned above, it will not call back. Instead, it will set a listener for viewtreeobserver, addonpredrawlistener. After measurement, it will call back the listener before drawing. However, because our layout is loaded in the background and not added to the interface, the callback will not go, so the picture cannot be loaded.

When we normally use it, we will call back the listener, retrieve the view size, and call back out.

 

Therefore, if you want to load an invisible picture through glide, you need to set layouparam with an exact numerical size.

(if the analysis is wrong, please correct it)

Please indicate:  https://www.cnblogs.com/tangZH/p/14691697.html