Upgrade to Pro — share decks privately, control downloads, hide ads and more …

よしなに頑張る画像ロードの話 / image load mettya tsurai

よしなに頑張る画像ロードの話 / image load mettya tsurai

2019/06/18に開催されたPotatotips #62にて発表したスライドです

Yoshihiro WADA

June 18, 2019
Tweet

More Decks by Yoshihiro WADA

Other Decks in Programming

Transcript

  1. Yoshihiro Wada a.k.a. @e10dokup
    Potatotips #62 - 2019/06/18

    View Slide

  2. Yoshihiro Wada a.k.a. @e10dokup
    CyberAgant Inc. / Ameba
    Ameba

    View Slide

  3. View Slide

  4. 1 URL
    2
    3
    3.5

    View Slide

  5. bumptech/glide square/picasso Image Loading Library
    bumptech/glide 4.9.0
    ConstraintLayout

    View Slide

  6. 1
    URL

    View Slide

  7. GlideApp.with(this)
    .load(/* Image URL */)
    .placeholder(/* Placeholder Drawable */)
    .error(/* Error Drawable */)
    .into(/* Target ImageView */)

    View Slide

  8. 2

    View Slide

  9. ConstraintLayout
    XML ImageView
    android:id=“@+id/image_view”
    android:layout_width="0dp"
    android:layout_height=“0dp”
    app:layout_constraintDimensionRatio="H,3:2"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf=“parent" />

    View Slide

  10. centerCrop
    GlideApp.with(this)
    .load(/* Image URL */)
    .placeholder(/* Placeholder Drawable */)
    .error(/* Error Drawable */)
    .centerCrop()
    .into(/* Target ImageView */)

    View Slide

  11. XML
    BindingAdapter
    android:id=“@+id/image_view”
    android:layout_width="0dp"
    android:layout_height=“0dp”
    app:layout_constraintDimensionRatio="H,3:2"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf=“parent”
    app:url=“@{imageUrl}” />

    View Slide

  12. BindingAdapter
    BindingAdapter
    @BindingAdapter(“url")
    internal fun ImageView.loadImage(url: String?) {
    if (url == null) {
    setImageDrawable(null)
    return
    }
    GlideApp
    .with(this)
    .load(url)
    .centerCrop()
    .into(this)
    }

    View Slide

  13. 3

    View Slide

  14. DimensionRatio

    View Slide

  15. API URL
    BindingAdapter DimensionRatio
    3
    android:id=“@+id/image_view”
    android:layout_width="0dp"
    android:layout_height=“0dp”
    app:width=“@{imageWidth}”
    app:height=“@{imageHeight}”
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf=“parent”
    app:url=“@{imageUrl}” />

    View Slide

  16. width/height dimensionRatio
    BindingAdapter
    layout_constraintDimensionRatio ConstraintLayout
    BindingAdapter
    3
    @BindingAdapter(“width”, “height”)
    internal fun ImageView.setAspectRatio(width: Int, height: Int) {
    (layoutParams as ConstraintLayout.LayoutParams).dimensionRatio
    = “h,${width}:${height}”
    }

    View Slide

  17. glide RequestListener Drawable
    requestLayout() onMeasure()
    3.5

    View Slide

  18. 3.5
    override fun onResourceReady(
    resource: Drawable?,
    model: Any?,
    target: Target?,
    dataSource: DataSource?,
    isFirstResource: Boolean
    ): Boolean {
    resource ?: return false
    val width = resource.intrinsicWidth.toFloat()
    val height = resource.intrinsicHeight.toFloat()
    aspectRatio = width / height
    requestLayout()
    return false
    }

    View Slide

  19. 3.5
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    aspectRatio?.let {
    // ݱঢ়ͷԣ෯Λऔಘ͠ɺ৽نʹΞεϖΫτൺΛ൓өͨ͠αΠζʹ੾Γସ͑Δ
    val width = MeasureSpec.getSize(widthMeasureSpec)
    val w = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY)
    val h = MeasureSpec
    .makeMeasureSpec((width / it).toInt(), MeasureSpec.EXACTLY)
    super.onMeasure(w, h)
    return
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

    View Slide

  20. 4

    View Slide



  21. *NBHF7JFX


    *NBHF7JFX


    *NBHF7JFX

    View Slide

  22. Load Bitmap
    Glide CenterCrop() Transformation
    Transformation
    4:2 2 

    ->
    ->
    Transformation

    View Slide

  23. • override fun updateDiskCacheKey(messageDigest: MessageDigest)
    equals() / hashCode()
    • override fun transform(

    pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int

    ): Bitmap
    toTransform Bitmap
    BitmapTransformation

    View Slide

  24. override fun transform(
    pool: BitmapPool,
    toTransform: Bitmap,
    outWidth: Int,
    outHeight: Int
    ): Bitmap {
    val width = toTransform.width
    val height = toTransform.height
    aspectRatio = width / height
    return when {
    aspectRatio >= 2 -> // 2:5 ΑΓԣ௕
    cropWidth(pool, toTransform, imageWidth, imageHeight)
    else -> // ͦΕҎ֎ͷͱ͖ɺͦͷ··BitmapΛฦ٫
    toTransform
    }
    }

    View Slide

  25. private fun transform(
    pool: BitmapPool,
    toTransform: Bitmap,
    width: Int,
    height: Int
    ): Bitmap {
    val croppedWidth = (width * 0.5).toInt()
    return TransformationUtils.centerCrop(
    pool,
    toTransform,
    trimmedWidth,
    height
    )
    }

    View Slide

  26. View Slide

  27. :pray:

    View Slide