Advertisement
  1. Code
  2. Coding Fundamentals

Kode sebuah Aplikasi Android Galeri Gambar Dengan Picasso

Scroll to top
Read Time: 17 min

() translation by (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

Picasso adalah pustaka Android open-source populer untuk memuat gambar lokal dan jarak jauh. Pelajari cara mudah menggunakannya untuk menangani kebutuhan pemuatan gambar Anda.

1. Apa itu Picasso?

Picasso (nama yang terinspirasi oleh seniman Perancis terkenal Pablo Picasso) adalah pustaka Android open-source yang sangat populer untuk memuat gambar di aplikasi Android Anda. Menurut dokumen resmi, itu menyatakan:

...Picasso memungkinkan pemuatan gambar tanpa kerumitan dalam aplikasi Anda—sering kali dalam satu baris kode!

Perhatikan bahwa Picasso menggunakan OkHttp (perpustakaan jaringan dari pengembang yang sama) di bawah tenda untuk memuat gambar melalui internet.

2. Jadi Mengapa Menggunakan Picasso?

Sekarang Anda telah belajar tentang apa Picasso, pertanyaan berikutnya yang mungkin Anda tanyakan adalah mengapa menggunakannya?

Mengembangkan media Anda sendiri memuat dan menampilkan fungsi di Java atau Kotlin dapat menjadi rasa sakit nyata: Anda harus menjaga caching, decoding, mengelola koneksi jaringan, threading, penanganan eksepsi, dan banyak lagi. Picasso adalah perpustakaan yang mudah digunakan, terencana dengan baik, terdokumentasi dengan baik, dan benar-benar teruji, yang dapat menghemat banyak waktu berharga Anda — dan menyelamatkanmu dari pusing.

Berikut ini banyak jebakan umum pemuatan gambar di Android yang ditangani untuk Anda oleh Picasso, menurut dokumen resmi:

  • menangani daur ulang ImageView dan mengunduh pembatalan di adaptor
  • transformasi gambar yang kompleks dengan penggunaan memori minimal
  • memori otomatis dan disk cache

Menambahkan gambar ke aplikasi Anda dapat membuat aplikasi Android Anda menjadi hidup. Jadi dalam tutorial ini, kita akan belajar tentang Picasso 2 dengan membangun aplikasi galeri gambar sederhana. Ini akan memuat gambar melalui internet dan menampilkannya sebagai thumbnail di RecyclerView, dan ketika pengguna mengklik gambar, itu akan membuka aktivitas detail yang berisi gambar yang lebih besar.

Contoh proyek (di Kotlin) untuk tutorial ini dapat ditemukan di repo GitHub kami sehingga Anda dapat dengan mudah mengikuti.

Seniman yang bagus menyalin, seniman hebat mencuri. - Pablo Picasso

3. Prasyarat

Untuk dapat mengikuti tutorial ini, Anda akan membutuhkan:

Aktifkan Android Studio dan buat proyek baru (Anda dapat menamainya PicassoDemo) dengan aktivitas kosong bernama MainActivity. Pastikan juga memeriksa kotak centang Sertakan dukungan Kotlin.

Android Studios Add an Activity to Mobile dialogAndroid Studios Add an Activity to Mobile dialogAndroid Studios Add an Activity to Mobile dialog

4. Deklarasi Dependensi

Setelah membuat proyek baru, tentukan dependensi berikut di build.gradle Anda. Pada saat penulisan, versi terbaru Picasso adalah 2.71828.

1
dependencies {
2
     implementation 'com.android.support:recyclerview-v7:27.1.1'
3
     implementation 'com.squareup.picasso:picasso:2.71828'
4
 }

Atau dengan Maven:

1
<dependency>
2
   <groupId>com.squareup.picasso</groupId>
3
   <artifactId>picasso</artifactId>
4
   <version>2.71828</version>
5
 </dependency>

Pastikan Anda menyinkronkan proyek Anda setelah menambahkan Picasso dan artefak RecyclerView v7.

5. Tambahkan Izin Internet

Karena Picasso akan melakukan permintaan jaringan untuk memuat gambar melalui internet, kita perlu menyertakan izin INTERNET di AndroidManifest.xml kami.

Jadi lakukan itu sekarang!

1
<uses-permission android:name="android.permission.INTERNET" />

Perhatikan bahwa ini hanya diperlukan jika Anda akan memuat gambar dari internet. Ini tidak diperlukan jika Anda hanya memuat gambar secara lokal di perangkat.

6. Membuat Tata Letak

Kami akan mulai dengan membuat RecyclerView kami di dalam file layout activity_main.xml.

1
<?xml version="1.0" encoding="utf-8"?>
2
 <RelativeLayout
3
         xmlns:android="http://schemas.android.com/apk/res/android"
4
         android:id="@+id/activity_main"
5
         android:layout_width="match_parent"
6
         android:layout_height="match_parent">
7
 
8
     <android.support.v7.widget.RecyclerView
9
             android:id="@+id/rv_images"
10
             android:layout_width="match_parent"
11
             android:layout_height="match_parent"/>
12
 </RelativeLayout>

Membuat Tata Letak Item Kustom

Selanjutnya, mari kita buat layout XML (item_image.xml) yang akan digunakan untuk setiap item (ImageView) dalam RecyclerView.

1
<?xml version="1.0" encoding="utf-8"?>
2
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
               android:orientation="vertical"
4
               android:layout_width="match_parent"
5
               android:layout_height="wrap_content">
6
     
7
     <ImageView
8
             android:id="@+id/iv_photo"
9
             android:adjustViewBounds="true"
10
             android:layout_height="200dp"
11
             android:scaleType="centerCrop"
12
             android:layout_margin="2dp"
13
             android:layout_width="match_parent"/>
14
 </LinearLayout>

Sekarang kami telah membuat tata letak yang dibutuhkan untuk aplikasi galeri sederhana kami, langkah selanjutnya adalah membuat adaptor RecyclerView untuk mengisi data. Sebelum kita melakukan itu, mari kita buat model data sederhana kita.

7. Membuat Model Data

Kami akan mendefinisikan model data sederhana untuk RecyclerView kami. Model ini menerapkan Parcelable untuk transportasi data berkinerja tinggi dari satu komponen ke komponen lainnya di Android. Dalam kasus kami, data akan diangkut dari SunsetGalleryActivity ke SunsetPhotoActivity.

1
data class SunsetPhoto(val url: String) : Parcelable {
2
 
3
     constructor(parcel: Parcel) : this(parcel.readString())
4
 
5
     override fun writeToParcel(parcel: Parcel, flags: Int) {
6
         parcel.writeString(url)
7
     }
8
 
9
     override fun describeContents(): Int {
10
         return 0
11
     }
12
 
13
     companion object CREATOR : Parcelable.Creator<SunsetPhoto> {
14
         override fun createFromParcel(parcel: Parcel): SunsetPhoto {
15
             return SunsetPhoto(parcel)
16
         }
17
 
18
         override fun newArray(size: Int): Array<SunsetPhoto?> {
19
             return arrayOfNulls(size)
20
         }
21
     }
22
 }

Perhatikan bahwa model ini SunsetPhoto hanya memiliki satu bidang yang disebut url (untuk tujuan demo), tetapi Anda dapat memiliki lebih banyak jika Anda mau. Kelas ini mengimplementasikan Parcelable, yang berarti kita harus mengesampingkan beberapa metode.

Kami dapat menggunakan Android Studio IDEA untuk menghasilkan metode ini bagi kami, tetapi sisi negatifnya adalah pemeliharaan. Bagaimana? Setiap kali kita menambahkan bidang baru ke kelas ini, kita mungkin lupa untuk memperbarui metode constructor dan writeToParcel secara eksplisit, yang dapat menyebabkan beberapa bug jika kita tidak memperbarui metode.

Sekarang, untuk menghindari memperbarui atau menulis metode boilerplate ini, Kotlin 1.1.14 memperkenalkan @Parcelize anotasi. Anotasi ini akan membantu kami menghasilkan metode writeToParcel, writeFromParcel, dan describeContents secara otomatis di bawah kap untuk kami.

1
@Parcelize
2
 data class SunsetPhoto(val url: String) : Parcelable

Sekarang, kode kami kelas SunsetPhoto hanya dua baris! Luar biasa!

Ingat untuk menambahkan kode berikut ke build.gradle modul aplikasi Anda:

1
androidExtensions {
2
     experimental = true
3
 }

Selain itu, saya menyertakan objek pendamping (atau metode statis di Java) getSunsetPhotos() di kelas model SunsetPhoto yang hanya akan mengembalikan ArrayList of SunsetPhoto saat dipanggil.

1
@Parcelize
2
 data class SunsetPhoto(val url: String) : Parcelable {
3
 
4
     companion object {
5
         fun getSunsetPhotos(): Array<SunsetPhoto> {
6
             return arrayOf<SunsetPhoto>(SunsetPhoto("https://goo.gl/32YN2B"),
7
                     SunsetPhoto("https://goo.gl/Wqz4Ev"),
8
                     SunsetPhoto("https://goo.gl/U7XXdF"),
9
                     SunsetPhoto("https://goo.gl/ghVPFq"),
10
                     SunsetPhoto("https://goo.gl/qEaCWe"),
11
                     SunsetPhoto("https://goo.gl/vutGmM"))
12
         }
13
     }
14
 }

8. Membuat Adaptor

Kami akan membuat adaptor untuk mengisi RecyclerView kami dengan data. Kami juga akan menerapkan pendengar klik untuk membuka aktivitas detail —SunsetPhotoActivity— memberikan contoh SunsetPhoto sebagai tambahan maksud. Aktivitas detail akan menampilkan gambar close-up. Kami akan membuatnya di bagian selanjutnya.

1
class MainActivity : AppCompatActivity() {
2
     //...

3
     private inner class ImageGalleryAdapter(val context: Context, val sunsetPhotos: Array<SunsetPhoto>) 
4
      : RecyclerView.Adapter<ImageGalleryAdapter.MyViewHolder>() {
5
 
6
         override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageGalleryAdapter.MyViewHolder {
7
             val context = parent.context
8
             val inflater = LayoutInflater.from(context)
9
             val photoView = inflater.inflate(R.layout.item_image, parent, false)
10
             return MyViewHolder(photoView)
11
         }
12
 
13
         override fun onBindViewHolder(holder: ImageGalleryAdapter.MyViewHolder, position: Int) {
14
             val sunsetPhoto = sunsetPhotos[position]
15
             val imageView = holder.photoImageView
16
         }
17
 
18
         override fun getItemCount(): Int {
19
             return sunsetPhotos.size
20
         }
21
 
22
         inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
23
 
24
             var photoImageView: ImageView = itemView.findViewById(R.id.iv_photo)
25
 
26
             init {
27
                 itemView.setOnClickListener(this)
28
             }
29
 
30
             override fun onClick(view: View) {
31
                 val position = adapterPosition
32
                 if (position != RecyclerView.NO_POSITION) {
33
                     val sunsetPhoto = sunsetPhotos[position]
34
                     val intent = Intent(context, SunsetPhotoActivity::class.java).apply {
35
                         putExtra(SunsetPhotoActivity.EXTRA_SUNSET_PHOTO, sunsetPhoto)
36
                     }
37
                     startActivity(intent)
38
                 }
39
             }
40
         }
41
     }
42
 }

Perhatikan bahwa kami menggunakan fungsi ekstensi apply untuk meletakkan objek sebagai tambahan untuk maksud. Sebagai pengingat, fungsi apply mengembalikan objek yang diteruskan kepadanya sebagai argumen (yaitu objek penerima).

9. Memuat Gambar Dari URL

Kami akan membutuhkan Picasso untuk melakukan tugasnya di bagian ini—bukan melukis kami sebuah karya seni, tetapi untuk mengambil gambar dari internet dan menampilkannya. Kami akan menampilkan gambar-gambar ini secara individual di ImageViews masing-masing di dalam metode RecyclerView onBindViewHolder() kami saat pengguna menggulir aplikasi.

1
override fun onBindViewHolder(holder: ImageGalleryAdapter.MyViewHolder, position: Int) {
2
     val sunsetPhoto = sunsetPhotos[position]
3
     val imageView = holder.photoImageView
4
 
5
     Picasso.get()
6
             .load(sunsetPhoto.url)
7
             .placeholder(R.drawable.placeholder)
8
             .error(R.drawable.error)
9
             .fit()
10
             .into(imageView)
11
 
12
 }

Selangkah demi selangkah, inilah panggilan ke Picasso:

Metode get()

Ini mengembalikan instance global Picasso (instance tunggal) yang diinisialisasi dengan konfigurasi default berikut:

  • Memori LRU cache 15% dari RAM aplikasi yang tersedia.
  • Disk cache dari 2% ruang penyimpanan hingga 50MB tetapi tidak kurang dari 5MB. Catatan: ini hanya tersedia di API 14+.
  • Tiga unduhan utas untuk akses disk dan jaringan.

Perhatikan bahwa jika pengaturan ini tidak memenuhi persyaratan aplikasi Anda, Anda bebas untuk membangun contoh Picasso Anda sendiri dengan kontrol penuh dari konfigurasi ini dengan menggunakan Picasso.Builder.

1
val picassoBuilder = Picasso.Builder(context)
2
 // do custom configurations

3
 
4
 // Specify the {@link Downloader} that will be used for downloading images.

5
 picassoBuilder.downloader() 
6
 // Specify the ExecutorService for loading images in the background.

7
 picassoBuilder.executor()
8
 // Specify the memory Cache used for the most recent images.

9
 picassoBuilder.memoryCache()
10
 // and more

11
 val picasso = picassoBuilder.build()

Akhirnya, Anda memanggil metode build() untuk mengembalikan Anda instance Picasso dengan konfigurasi Anda sendiri.

Sebaiknya lakukan ini di Application.onCreate Anda dan kemudian atur sebagai contoh tunggal dengan Picasso.setSingletonInstance dalam metode tersebut—untuk memastikan bahwa instance Picasso adalah yang global.

Metode load()

load(String path) memulai permintaan gambar menggunakan jalur yang ditentukan. Jalur ini dapat berupa URL jarak jauh, sumber daya file, sumber konten, atau sumber daya Android.

  • placeholder(int placeholderResId): sumber penampung lokal atau dapat digambar untuk digunakan ketika gambar sedang dimuat dan kemudian ditampilkan. Ini berfungsi sebagai pengalaman pengguna yang baik untuk menampilkan gambar placeholder saat gambar sedang diunduh.

Perhatikan bahwa Picasso pertama-tama memeriksa apakah gambar yang diminta ada di cache memori, dan jika itu, gambar itu akan ditampilkan dari sana (kita akan membahas cache di Picasso lebih lanjut di bagian selanjutnya).

Metode lain

  • error(int errorResId): gambar yang dapat digambar untuk digunakan jika gambar yang diminta tidak dapat dimuat—mungkin karena situs web sedang tidak aktif.
  • noFade(): Picasso selalu memudar dalam gambar yang akan ditampilkan ke dalam ImageView. Jika Anda tidak menginginkan animasi fade-in ini, cukup panggil metode noFade().
  • into(ImageView imageView): tampilan gambar target di mana gambar akan ditempatkan.

Pengubahan Ukuran Gambar dan Transformasi

Jika server yang Anda minta gambar tidak memberikan Anda gambar yang Anda butuhkan dalam ukuran yang diperlukan, Anda dapat dengan mudah mengubah ukuran gambar tersebut menggunakan resize(int targetWidth, int targetHeight). Memanggil metode ini mengubah ukuran gambar dan kemudian menampilkannya di ImageView. Perhatikan bahwa dimensi dalam pixel (px), bukan dp.

1
Picasso.get()
2
         .load(sunsetPhoto.url)
3
         .placeholder(R.drawable.placeholder)
4
         .resize(400, 200)
5
         .into(imageView)

Anda dapat meneruskan sumber daya dimensi Android untuk lebar dan tinggi menggunakan metode resizeDimen(int targetWidthResId, int targetHeightResId). Metode ini akan mengonversi ukuran dimensi menjadi piksel mentah dan kemudian mengubah resize() di bawah kap-melewati ukuran yang dikonversi (dalam pixel) sebagai argumen.

1
Picasso.get()
2
    //...

3
     .resizeDimen(R.dimen.list_detail_image_size, R.dimen.list_detail_image_size)
4
     //...

Perhatikan bahwa metode pengubah ukuran ini tidak akan menghormati rasio aspek. Dengan kata lain, rasio aspek gambar Anda dapat terdistorsi.

Untungnya, Picasso memberi kami beberapa metode berguna untuk menyelesaikan masalah ini:

  • centerCrop(): skala gambar seragam (menjaga aspek rasio gambar) sehingga gambar mengisi area yang diberikan, dengan sebanyak mungkin gambar yang ditampilkan. Jika diperlukan, gambar akan dipotong secara horizontal atau vertikal agar pas. Memanggil metode ini memotong gambar di dalam batas yang ditentukan dengan mengubah resize().
  • centerInside(): skala gambar sehingga kedua dimensi sama atau kurang dari batas yang diminta. Ini akan memusatkan gambar di dalam batas yang ditentukan dengan mengubah resize().
  • onlyScaleDown(): hanya mengubah ukuran gambar jika ukuran gambar asli lebih besar dari ukuran target yang ditentukan dengan mengubah resize().
  • fit(): mencoba untuk mengubah ukuran gambar agar pas dengan target ImageView.

Rotasi Gambar

Picasso memiliki API yang mudah untuk memutar gambar dan kemudian menampilkan gambar itu. Metode rotate(float degrees) memutar gambar dengan derajat yang ditentukan.

1
Picasso.get()
2
     //...

3
     .rotate(90f)
4
     //...

Dalam contoh di atas, ini akan memutar gambar hingga 90 derajat. rotate(float degrees, float pivotX, float pivotY) metode memutar gambar dengan derajat yang ditentukan di sekitar pivot point.

1
Picasso.get()
2
     //...

3
     .rotate(30f, 200f, 100f)
4
     //...

Di sini kita akan memutar gambar dengan 30 derajat di sekitar pivot point 200, 100 pixel.

Transformasi

Selain hanya memanipulasi gambar dengan memutarnya, Picasso juga memberi kita opsi untuk menerapkan transformasi kustom ke sebuah gambar sebelum menampilkannya.

Anda cukup membuat kelas yang mengimplementasikan antarmuka Transformation Picasso. Anda kemudian harus mengganti dua metode:

  • Bitmap transform(Bitmap source): ini mengubah bitmap sumber menjadi bitmap baru.
  • String key(): mengembalikan kunci unik untuk transformasi, yang digunakan untuk tujuan cache.

Setelah selesai membuat transformasi kustom Anda, Anda cukup menjalankannya dengan memohon transform(Transformation transformation) pada instance Picasso Anda. Perhatikan bahwa Anda juga dapat memberikan daftar Transformation untuk transform().

1
Picasso.get()
2
         // ...

3
         .transform(CropCircleTransformation())
4
         .into(imageView)

Di sini, saya menerapkan transformasi crop circle ke gambar dari Picasso Transformations open-source Android library. Pustaka ini memiliki banyak transformasi yang dapat Anda terapkan pada gambar dengan Picasso—termasuk transformasi untuk gambar buram atau abu-abu. Pergi periksa jika Anda ingin menerapkan beberapa transformasi keren ke gambar Anda.

10. Inisialisasi Adaptor

Di sini, kita cukup membuat RecyclerView dengan GridLayoutManager sebagai manajer tata letak, menginisialisasi adaptor kami, dan mengikatnya ke RecyclerView.

1
class MainActivity : AppCompatActivity() {
2
 
3
     private lateinit var recyclerView: RecyclerView
4
     private lateinit var imageGalleryAdapter: ImageGalleryAdapter
5
 
6
     override fun onCreate(savedInstanceState: Bundle?) {
7
         //...

8
         
9
         val layoutManager = GridLayoutManager(this, 2)
10
         recyclerView = findViewById(R.id.rv_images)
11
         recyclerView.setHasFixedSize(true)
12
         recyclerView.layoutManager = layoutManager
13
         imageGalleryAdapter = ImageGalleryAdapter(this, SunsetPhoto.getSunsetPhotos())
14
     }
15
 
16
     override fun onStart() {
17
         super.onStart()
18
         recyclerView.adapter = imageGalleryAdapter
19
     }
20
     // ...

21
 }

11. Membuat Detail Kegiatan

Buat aktivitas baru dan beri nama SunsetPhotoActivity. Kami mendapatkan SunsetPhoto tambahan dan memuat gambar—di dalam onStart()—dengan Picasso seperti yang kami lakukan sebelumnya.

1
class SunsetPhotoActivity : AppCompatActivity() {
2
 
3
     companion object {
4
         const val EXTRA_SUNSET_PHOTO = "SunsetPhotoActivity.EXTRA_SUNSET_PHOTO"
5
     }
6
 
7
     private lateinit var imageView: ImageView
8
     private lateinit var sunsetPhoto: SunsetPhoto
9
 
10
     override fun onCreate(savedInstanceState: Bundle?) {
11
         super.onCreate(savedInstanceState)
12
         setContentView(R.layout.activity_sunset_photo)
13
 
14
         sunsetPhoto = intent.getParcelableExtra(EXTRA_SUNSET_PHOTO)
15
         imageView = findViewById(R.id.image)
16
     }
17
 
18
     override fun onStart() {
19
         super.onStart()
20
 
21
         Picasso.get()
22
                 .load(sunsetPhoto.url)
23
                 .placeholder(R.drawable.placeholder)
24
                 .error(R.drawable.error)
25
                 .fit()
26
                 .into(imageView)
27
     }
28
 }

Tata Letak Detail

Berikut tata letak untuk menampilkan aktivitas detail. Ini hanya menampilkan ImageView yang akan menampilkan versi resolusi penuh dari gambar yang dimuat.

1
<?xml version="1.0" encoding="utf-8"?>
2
 <LinearLayout
3
         xmlns:android="http://schemas.android.com/apk/res/android"
4
         android:layout_width="match_parent"
5
         android:layout_height="match_parent">
6
 
7
     <ImageView
8
             android:id="@+id/image"
9
             android:layout_width="match_parent"
10
             android:layout_height="wrap_content"
11
             android:adjustViewBounds="true"
12
             android:scaleType="fitCenter"
13
             android:layout_gravity="center"/>
14
 </LinearLayout>

12. Mekanisme Caching di Picasso

Jika Anda mengamati dengan hati-hati, Anda akan melihat bahwa ketika Anda mengunjungi kembali gambar yang sebelumnya dimuat, itu memuat lebih cepat dari sebelumnya. Apa yang membuatnya lebih cepat? Ini mekanisme cache Picasso, itulah.

Inilah yang terjadi di bawah kap. Setelah gambar dimuat sekali dari internet, Picasso akan menyimpannya di memori dan pada disk, menyimpan permintaan jaringan berulang dan memungkinkan pengambilan gambar yang lebih cepat. Ketika gambar itu diperlukan lagi, Picasso akan memeriksa dulu apakah gambar tersedia dalam memori, dan jika ada, akan segera mengembalikannya. Jika gambar itu tidak ada dalam memori, Picasso akan memeriksa disk berikutnya, dan jika ada, akan mengembalikannya. Jika tidak ada, Picasso akhirnya akan melakukan permintaan jaringan untuk gambar itu dan menampilkannya.

Singkatnya, inilah yang terjadi (di bawah tenda) untuk permintaan gambar: memori -> disk -> jaringan.

Tergantung pada aplikasi Anda, Anda mungkin ingin menghindari caching—misalnya, jika gambar yang ditampilkan cenderung sering berubah dan tidak dimuat ulang.

Jadi Bagaimana Anda Menonaktifkan Caching?

Anda dapat menghindari cache memori dengan memanggil memoryPolicy(MemoryPolicy.NO_CACHE). Ini hanya akan melewatkan pencarian cache memori saat memproses permintaan gambar.

1
Picasso.get()
2
         .load(sunsetPhoto.url)
3
         .placeholder(R.drawable.placeholder)
4
         .error(R.drawable.error)
5
         .fit()
6
         .memoryPolicy(MemoryPolicy.NO_CACHE)
7
         .into(imageView)

Perhatikan bahwa ada enum lain: MemoryPolicy.NO_STORE. Ini berguna jika Anda sangat yakin bahwa Anda hanya akan meminta gambar sekali. Menerapkan ini juga tidak akan menyimpan gambar dalam cache memori—dengan demikian tidak memaksakan bitmap lain dari cache memori.

Tetapi sangat sadar bahwa gambar akan tetap di-cache pada disk—untuk mencegahnya juga, Anda menggunakan networkPolicy(@NonNull NetworkPolicy policy, @NonNull NetworkPolicy... additional), yang mengambil satu atau beberapa nilai enum berikut:

  • NetworkPolicy.NO_CACHE: skips memeriksa cache disk dan memaksa memuat melalui jaringan.
  • NetworkPolicy.NO_STORE: melompat menyimpan hasil ke dalam cache disk.
  • NetworkPolicy.OFFLINE: memaksa permintaan hanya melalui cache disk, melewati jaringan.

Untuk menghindari cache memori dan disk secara keseluruhan, cukup panggil kedua metode satu per satu:

1
Picasso.get()
2
         .load(sunsetPhoto.url)
3
         .placeholder(R.drawable.placeholder)
4
         .error(R.drawable.error)
5
         .fit()
6
         .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
7
         .networkPolicy(NetworkPolicy.NO_CACHE)
8
         .into(imageView)

13. Minta Pendengar

Di Picasso, Anda dapat menerapkan pendengar atau panggilan balik untuk memantau status permintaan yang Anda buat saat pemuatan gambar. Hanya satu dari metode ini yang akan dipanggil jika Anda mengimplementasikan antarmuka Target pada permintaan.

  • void onBitmapFailed(e: Exception?, errorDrawable: Drawable?): Dipicu kapan saja gambar tidak berhasil dimuat. Di sini, kita dapat mengakses pengecualian yang dilemparkan.
  • void onBitmapLoaded(Bitmap bitmap, LoadedFrom from): diaktifkan setiap kali sebuah gambar berhasil dimuat. Di sini, kami mendapatkan Bitmap untuk menunjukkan kepada pengguna.
  • void onPrepareLoad(Drawable placeHolderDrawable): dipanggil tepat sebelum permintaan Anda diajukan.
1
Picasso.get()
2
         .load(sunsetPhoto.url)
3
         .placeholder(R.drawable.placeholder)
4
         .error(R.drawable.error)
5
         .into(object : Target {
6
             
7
             override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
8
             }
9
 
10
             override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {
11
             }
12
 
13
             override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
14
             }
15
         })

Di sini Anda juga dapat menampilkan dan kemudian menyembunyikan dialog progres jika Anda memilikinya.

Ada pendengar panggilan balik lain yang dapat Anda terapkan jika Anda mau, yang disebut Callback. Antarmuka ini hanya memiliki dua metode: onSuccess() dan onError(Exception e). Yang pertama dipanggil ketika beban permintaan gambar berhasil, dan kemudian dipanggil ketika ada kesalahan dalam memproses permintaan.

Kembali ke aplikasi galeri foto kami (di dalam SunsetPhotoActivity), mari kita ubah tampilan sedikit dengan menggunakan objek Callback yang akan mengatur bitmap ke ImageView dan juga mengubah warna latar belakang tata letak dengan mengekstrak warna gelap dan bersemangat dari gambar kita menggunakan Android Palette API.

Jadi sertakan artefak palet di build.gradle modul aplikasi Anda:

1
dependencies {
2
     //... 

3
     implementation 'com.android.support:palette-v7:27.1.1'
4
 }

Sekarang mari kita menerapkan antarmuka Callback dalam permintaan Picasso kami.

1
override fun onStart() {
2
     super.onStart()
3
 
4
     Picasso.get()
5
             .load(sunsetPhoto.url)
6
             .placeholder(R.drawable.placeholder)
7
             .error(R.drawable.error)
8
             .fit()
9
             .into(imageView, object : Callback {
10
 
11
                 override fun onSuccess() {
12
                     val bitmap = (imageView.drawable as BitmapDrawable).bitmap
13
                     onPalette(Palette.from(bitmap).generate())
14
                 }
15
 
16
                 override fun onError(e: Exception?) {
17
                 }
18
             })
19
 }
20
 
21
 fun onPalette(palette: Palette?) {
22
     if (null != palette) {
23
         val parent = imageView.parent.parent as ViewGroup
24
         parent.setBackgroundColor(palette.getDarkVibrantColor(Color.GRAY))
25
     }
26
 }

14. Menguji Aplikasi

Akhirnya, Anda dapat menjalankan aplikasinya! Klik thumbnail untuk mendapatkan versi gambar ukuran penuh.

Final app resultFinal app resultFinal app result

15. Memprioritaskan Permintaan

Ketika Anda ingin memuat gambar yang berbeda pada saat yang sama pada layar yang sama, Anda memiliki opsi untuk memesan mana yang lebih penting daripada yang lain. Dengan kata lain, Anda dapat memuat gambar penting terlebih dahulu.

Anda cukup memanggil priority() pada contoh permintaan Picasso Anda dan menyampaikan dalam salah satu dari enum: Priority.LOW, Priority.NORMAL, atau Priority.HIGH.

1
Picasso.get()
2
         .load(sunsetPhoto.url)
3
         .placeholder(R.drawable.placeholder)
4
         .error(R.drawable.error)
5
         .fit()
6
         .priority(Picasso.Priority.HIGH)
7
         .into(imageView)
8
 
9
 Picasso.get()
10
         .load(sunsetPhoto.url)
11
         .placeholder(R.drawable.placeholder)
12
         .error(R.drawable.error)
13
         .fit()
14
         .priority(Picasso.Priority.NORMAL)
15
         .into(imageView)
16
 
17
 Picasso.get()
18
         .load(sunsetPhoto.url)
19
         .placeholder(R.drawable.placeholder)
20
         .error(R.drawable.error)
21
         .fit()
22
         .priority(Picasso.Priority.LOW)
23
         .into(imageView)

16. Menandai Permintaan

Dengan menandai permintaan Picasso Anda, Anda dapat melanjutkan, menjeda, atau membatalkan permintaan yang terkait dengan tag tertentu. Bergantung pada kasus penggunaan Anda, Anda dapat memberi tag permintaan Anda dengan string atau objek yang harus menentukan ruang lingkup permintaan sebagai Context, Activity, atau Fragment. Anda dapat dengan mudah menandai permintaan Picasso dengan memanggil tag(@NonNull Object tag) pada satu. Berikan contoh Object yang berfungsi sebagai tag.

Berikut adalah operasi berikut yang dapat Anda lakukan pada permintaan Picasso yang ditandai:

  • pauseTag(Object tag): menghentikan semua permintaan yang terkait dengan tag yang diberikan.
  • resumeTag(Object tag): melanjutkan permintaan yang dijeda dengan tag yang diberikan.
  • cancelTag(Object tag): membatalkan semua permintaan yang ada dengan tag yang diberikan.
1
Picasso.get()
2
         // ...

3
         .tag(context

Meskipun pemberian tag permintaan Anda memberi Anda kontrol atas permintaan Anda, Anda harus sangat berhati-hati saat menggunakan tag karena potensi kebocoran memori. Inilah yang dikatakan dokumentasi resmi:

Picasso akan menyimpan referensi ke tag selama tag ini dijeda dan/atau memiliki permintaan aktif. Waspadai potensi kebocoran.

Memuat Dari Sistem File

Sangat mudah untuk memuat gambar secara lokal di aplikasi Anda.

1
File file = new File("your/pic/file/path/file.png")
2
 Picasso.get()
3
         .load(file)
4
         .fit()
5
         .into(imageView)

Kesimpulan

Pekerjaan yang baik! Dalam tutorial ini, Anda telah membangun aplikasi galeri gambar lengkap dengan Picasso, dan sepanjang jalan Anda telah belajar bagaimana perpustakaan bekerja dan bagaimana Anda dapat mengintegrasikannya ke dalam proyek Anda sendiri.

Anda juga telah belajar bagaimana untuk menampilkan gambar baik lokal dan remote, permintaan tagging, permintaan memprioritaskan, dan bagaimana menerapkan transformasi gambar seperti mengubah ukuran. Tidak hanya itu, tetapi Anda telah melihat betapa mudahnya mengaktifkan dan menonaktifkan cache, penanganan kesalahan, dan pendengar permintaan khusus.

Untuk mempelajari lebih lanjut tentang Picasso, Anda dapat merujuk ke dokumentasi resminya. Untuk mempelajari lebih lanjut tentang koding untuk Android, lihat beberapa kursus dan tutorial kami yang lain di Envato Tuts+!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.