Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

เพิ่ม Picasso Library ใน Android Studio


Picasso คืออะไร?

Picasso เป็น Image Loading Library จาก Square Inc. โดดเด่นด้วย API ที่เรียบง่ายมาก "One-liner" เหมาะสำหรับโปรเจกต์ที่ต้องการโหลดภาพพื้นฐาน ไม่ต้องการฟีเจอร์ซับซ้อน כמו GIF/Video

การติดตั้ง

build.gradle (Module: app)

dependencies {
    // Picasso เวอร์ชันล่าสุด (ตรวจสอบที่ GitHub: square/picasso)
    implementation 'com.squareup.picasso:picasso:2.8'
    
    // สำหรับ OkHttp (แนะนำให้ใช้ร่วม)
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'
    
    // Picasso OkHttp3 Downloader (ถ้าใช้ OkHttp)
    // implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
}
> ⚠️ **หมายเหตุ:** โค้ดตัวอย่างเดิมใช้ `com.squareup.picasso3:picasso:2.71828` ซึ่งเป็นเวอร์ชันเก่า/ผิดปกติ ควรใช้ `com.squareup.picasso:picasso:2.8` หรือใหม่กว่า

การใช้งานพื้นฐาน

Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:scaleType="centerCrop"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java

import android.os.Bundle;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView imageView = findViewById(R.id.imageView);

        Picasso.get() // ใช้ get() แทน with(context) ในเวอร์ชันใหม่
            .load("https://www.tutorialspoint.com/images/tp-logo-diamond.png")
            .placeholder(R.mipmap.ic_launcher)      // ระหว่างโหลด
            .error(R.drawable.ic_error)             // โหลดล้มเหลว
            .resize(400, 400)                       // Resize ก่อนโหลด (ป้องกัน OOM)
            .centerCrop()                           // Crop ให้เต็มพื้นที่
            .rotate(0)                              // หมุนองศา
            .into(imageView, new Callback() {
                @Override
                public void onSuccess() {
                    Toast.makeText(MainActivity.this, "โหลดภาพสำเร็จ", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onError(Exception e) {
                    Toast.makeText(MainActivity.this, "โหลดภาพล้มเหลว: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
    }
}

เมธอดหลักของ Picasso (Cheat Sheet)

เมธอดคำอธิบาย
get()ดึง Singleton Instance (แทน with(context) เดิม)
load(String/File/Uri/Resource)ระบุแหล่งที่มาของภาพ
placeholder(Drawable/ResId)ภาพชั่วคราวระหว่างโหลด
error(Drawable/ResId)ภาพเมื่อโหลดล้มเหลว
memoryPolicy(MemoryPolicy)NO_CACHE, NO_STORE
networkPolicy(NetworkPolicy)OFFLINE, NO_CACHE
resize(int, int)ปรับขนาด (px) - ทำ Downscaling บน Network Thread
resizeDimen(int, int)ปรับขนาดจาก Dimen Resource
centerCrop()ScaleType.CENTER_CROP
centerInside()ScaleType.CENTER_INSIDE
fit()วัดขนาด View อัตโนมัติ (ต้องไม่มี fixed size)
rotate(float degrees)หมุนภาพ
rotate(float degrees, float pivotX, float pivotY)หมุนพร้อมจุดหมุน
transform(Transformation)Custom Transformation
priority(Priority)LOW, NORMAL, HIGH
tag(Object)Tag สำหรับ Cancel request กลุ่ม
into(ImageView)โหลดลง ImageView
into(ImageView, Callback)โหลดพร้อม Callback
into(Target)โหลดลง Custom Target
fetch()ดึงแค่ Cache ไม่แสดง
fetch(Callback)ดึง Cache พร้อม Callback

ฟีเจอร์ขั้นสูง

1. Custom Transformation (มุมโค้ง, วงกลม)

import com.squareup.picasso.Transformation;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Shader;

public class CircleTransform implements Transformation {
    @Override
    public Bitmap transform(Bitmap source) {
        int size = Math.min(source.getWidth(), source.getHeight());
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;
        
        Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
        if (squared != source) source.recycle();
        
        Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        BitmapShader shader = new BitmapShader(squared, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        paint.setShader(shader);
        paint.setAntiAlias(true);
        float radius = size / 2f;
        canvas.drawCircle(radius, radius, radius, paint);
        squared.recycle();
        return bitmap;
    }

    @Override
    public String key() { return "circle"; }
}

// ใช้งาน
Picasso.get().load(url).transform(new CircleTransform()).into(imageView);

2. Request Creator และ Target สำหรับ RecyclerView

// ใน Adapter onBindViewHolder
Picasso.get()
    .load(item.getImageUrl())
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error)
    .fit() // ใช้กับ View ที่ไม่มี fixed size
    .centerCrop()
    .into(holder.imageView);

// สำคัญ: Cancel request เมื่อ View Recycle
@Override
public void onViewRecycled(@NonNull ViewHolder holder) {
    super.onViewRecycled(holder);
    Picasso.get().cancelRequest(holder.imageView);
}

3. Debugging และ Indicators

// เปิด Debug Mode (แสดงสีขอบ: แดง=Network, น้ำเงิน=Disk, เขียว=Memory)
Picasso.get().setIndicatorsEnabled(true);

// Logging
Picasso.get().setLoggingEnabled(true);

Picasso vs Glide: เลือกตัวไหนดี?

ด้านPicassoGlide
API ComplexitySimple, MinimalRich, Fluent
GIF/Video❌✅
Auto Lifecycle❌ (Manual cancel)✅ (with Fragment/Activity)
TransformationsBasic + CustomRich Built-in
Memory ManagementGoodExcellent (Downsampling)
Size~120 KB~400 KB
Kotlin ExtensionsCommunityOfficial

แนวทางเลือก

  • Picasso: โปรเจกต์เล็ก, โหลดภาพ Static, API เรียบง่าย, ขนาด APK สำคัญ
  • Glide: โปรเจกต์ Production, ต้องการ GIF/Video, RecyclerView มาก, Lifecycle Awareness
  • Coil: โปรเจกต์ Kotlin ใหม่ (Recommended สำหรับ Kotlin First)

สิ่งที่ควรระวัง

  • Picasso ไม่ Cancel Request อัตโนมัติเมื่อ View Detach → เรียก Picasso.get().cancelRequest(imageView) ใน onViewRecycled หรือ onDestroyView
  • ใช้ .fit() แทน .resize() เมื่อ ImageView ไม่มีขนาดคงที่
  • Placeholder/Error ควรเป็น Resource (ResId) ไม่ใช่ Drawable Object เพื่อ Performance
  • สำหรับ List ใหญ่ ใช้ memoryPolicy(MemoryPolicy.NO_CACHE) เพื่อไม่ให้เต็ม Memory