Picasso er et populært Android-bibliotek med åpen kildekode for lasting av både lokale og eksterne bilder. Lær hvordan du enkelt bruker den til å håndtere dine behov for bildeinnlasting.
Picasso (navnet inspirert av den berømte franske kunstneren Pablo Picasso) er et veldig populært Android-bibliotek med åpen kildekode for å laste bilder i Android-appen din. Ifølge de offisielle dokumentene står det:
... Picasso muliggjør problemfri bildeinnlasting i søknaden din - ofte i en linje med kode!
Legg merke til at Picasso bruker OkHttp (et nettverksbibliotek fra samme utvikler) under hetten for å laste bildene over internett.
Nå har du lært hva Picasso handler om, det neste spørsmålet du kanskje spør er hvorfor bruke det?
Å utvikle din egen medieinnlasting og displayfunksjonalitet i Java eller Kotlin kan være en virkelig smerte: du må ta vare på caching, dekoding, styring av nettverkstilkoblinger, tråder, unntakshåndtering og mer. Picasso er et brukervennlig, godt planlagt, godt dokumentert og grundig testet bibliotek som kan spare deg for mye dyrebar tid - og spare deg for noen hodepine.
Her er mange av de vanlige fallgruvene for å laste bilder på Android som er behandlet for deg av Picasso, ifølge de offisielle doksene:
Imageview
resirkulering og nedlasting av kansellering i en adapterLegge til bilder i appen din, kan gjøre at Android-appen din blir levende. Så i denne opplæringen lærer vi om Picasso 2 ved å bygge et enkelt bildegalleri-app. Den vil laste bildene via internett og vise dem som miniatyrbilder i en RecyclerView, og når en bruker klikker på et bilde, åpnes det en detaljaktivitet som inneholder det større bildet.
Et prøveprosjekt (i Kotlin) for denne opplæringen finner du på vår GitHub repo, slik at du enkelt kan følge med.
God artister kopiere, gode kunstnere stjeler. - Pablo picasso
For å kunne følge denne opplæringen må du:
Brann opp Android Studio og opprett et nytt prosjekt (du kan nevne det PicassoDemo
) med en tom aktivitet som heter Hoved aktivitet
. Pass på at du også sjekker Inkluder Kotlin-støtte merk av i boksen.
Etter å ha opprettet et nytt prosjekt, spesifiser du følgende avhengigheter i din build.gradle. På tidspunktet for skriving er den nyeste versjonen av Picasso 2,71828
.
avhengigheter implementering 'com.android.support:recyclerview-v7:27.1.1' implementering 'com.squareup.picasso: picasso: 2.71828'
Eller med Maven:
com.squareup.picasso picasso 2,71828
Pass på at du synkroniserer prosjektet ditt etter å ha lagt til Picasso og RecyclerView
V7 gjenstander.
Fordi Picasso skal utføre en nettverksforespørsel for å laste bilder via internett, må vi inkludere tillatelsen INTERNETT
i vår AndroidManifest.xml.
Så gå gjør det nå!
Merk at dette kun er nødvendig hvis du skal laste bilder fra Internett. Dette er ikke nødvendig hvis du bare laster inn bilder lokalt på enheten.
Vi starter med å lage vår RecyclerView
inne i activity_main.xml layoutfil.
Neste, la oss lage XML-oppsettet (item_image.xml) som vil bli brukt for hvert element (Imageview
) innen RecyclerView
.
Nå som vi har opprettet layoutene som trengs for vår enkle galleri-app, er neste trinn å lage RecyclerView
adapter for å fylle data. Før vi gjør det, skjønner vi, la oss lage vår enkle datamodell.
Vi skal definere en enkel datamodell for vår RecyclerView
. Denne modellen implementerer Parcelable for høy ytelse transport av data fra en komponent til en annen i Android. I vårt tilfelle vil data bli transportert fra SunsetGalleryActivity
til SunsetPhotoActivity
.
dataklasse SunsetPhoto (val url: String): Parcelable constructor (pakke: Parcel): dette (parcel.readString ()) overstyre fun writeToParcel (pakke: Parcel, flagg: Int) parcel.writeString (url) tilsidesatte morsom beskrivelseContents (): Int return 0 følgesvennobjekt CREATOR: Parcelable.Creatoroverstyre moro createFromParcel (pakke: pakke): SunsetPhoto return SunsetPhoto (pakke) overstyre morsom newArray (størrelse: Int): Array return arrayOfNulls (size)
Legg merke til at denne modellen SunsetPhoto
har bare et enkelt felt kalt url
(for demo), men du kan ha mer hvis du vil. Denne klassen implementerer Parcelable
, noe som betyr at vi må overstyre noen metoder.
Vi kan bruke Android Studio IDEA til å generere disse metodene for oss, men ulempen til dette er vedlikehold. Hvordan? Når vi legger til nye felt i denne klassen, kan vi glemme å oppdatere konstruktør
og writeToParcel
metoder, som kan føre til noen feil hvis vi ikke oppdaterer metodene.
Nå, for å omgå oppdatering eller skriving av disse boilerplate-metodene, introduserte Kotlin 1.1.14 @Parcelize
merknad. Denne annotasjonen vil hjelpe oss med å generere writeToParcel
, writeFromParcel
, og describeContents
metoder automatisk under hetten for oss.
@Parcelize dataklasse SunsetPhoto (val url: String): Pakket
Nå, vår kode SunsetPhoto
klassen er bare to linjer! Rått!
Husk å legge til følgende kode i appmodulen din build.gradle
:
androidExtensions experimental = true
I tillegg inneholdt jeg et følgesvennobjekt (eller statisk metode i Java) getSunsetPhotos ()
i SunsetPhoto
modell klasse som vil ganske enkelt returnere en Arraylist
av SunsetPhoto
når kalt.
@Parcelize dataklasse SunsetPhoto (val url: String): Pakket companion object fun getSunsetPhotos (): Arrayreturn arrayOf (SunsetPhoto ("https://goo.gl/32YN2B"), SunsetPhoto ("https://goo.gl/Wqz4Ev"), SunsetPhoto ("https://goo.gl/U7XXdF"), SunsetPhoto ("https : //goo.gl/ghVPFq "), SunsetPhoto (" https://goo.gl/qEaCWe "), SunsetPhoto (" https://goo.gl/vutGmM "))
Vi lager en adapter for å fylle ut vår RecyclerView
med data. Vi vil også implementere en klikklytter for å åpne detaljaktiviteten-SunsetPhotoActivity
-passerer det en forekomst av SunsetPhoto
som en hensikt ekstra. Detaljeringsaktiviteten viser et nærbilde av bildet. Vi lager den i en senere del.
klasse MainActivity: AppCompatActivity () // ... privat indre klasse ImageGalleryAdapter (val kontekst: Context, val sunsetBilder: Array): RecyclerView.Adapter () override fun onCreateViewHolder (foreldre: ViewGroup, viewType: Int): ImageGalleryAdapter.MyViewHolder val context = parent.context val inflater = LayoutInflater.fra (kontekst) val photoView = inflater.inflate (R.layout.item_image, foreldre, falsk) returnere MyViewHolder (photoView) overstyr moro påBindViewHolder (holder: ImageGalleryAdapter.MyViewHolder, posisjon: Int) val sunsetPhoto = sunsetPhotos [posisjon] val imageView = holder.photoImageView overstyrer moro getItemCount (): Int return sunsetPhotos.size Innvendig klasse MyViewHolder (itemView: View): RecyclerView.ViewHolder (itemView), View.OnClickListener var photoImageView: ImageView = itemView.findViewById (R.id.iv_photo) init itemView.setOnClickListener (this) overstyre moro onClick (se: View) val posisjon = adapterPosisjon hvis (posisjon! = RecyclerView.NO_POSITION) val sunsetPhoto = sunsetPhotos [posisjon] val intent = Intent (kontekst, SunsetPhotoActivity :: class.java) .apply putExtra (SunsetPhotoActivity.EXTRA_SUNSET_PHOTO, sol setPhoto) startAktivitet (hensikt)
Legg merke til at vi brukte søke om
utvidelsesfunksjon for å sette et objekt som ekstra for hensikten. Som en påminnelse, den søke om
funksjon returnerer objektet som sendes til det som et argument (dvs. mottakerobjektet).
Vi skal trenge Picasso for å gjøre jobben sin i denne delen - ikke å male oss et kunstverk, men å hente bilder fra internett og vise dem. Vi viser disse bildene individuelt i deres respektive Imageview
s inne i vår RecyclerView
onBindViewHolder ()
Metode som brukeren ruller appen.
overstyr moro påBindViewHolder (holder: ImageGalleryAdapter.MyViewHolder, posisjon: Int) val sunsetPhoto = sunsetPhotos [posisjon] val imageView = holder.photoImageView Picasso.get () .load (sunsetPhoto.url) .stedholder (R.drawable.placeholder). feil (R.drawable.error) .fit () .into (imageView)
Trinn for trinn, her er det som kalles til Picasso
gjør:
få()
MetodeDette returnerer den globale Picasso
forekomst (singleton-instans) initialisert med følgende standardkonfigurasjoner:
Merk at hvis disse innstillingene ikke oppfyller kravene i søknaden din, er du fri til å konstruere dine egne Picasso
eksempel med full kontroll over disse konfigurasjonene ved å bruke Picasso.Builder
.
val picassoBuilder = Picasso.Builder (kontekst) // gjør egendefinerte konfigurasjoner // Angi @link Downloader som skal brukes til nedlasting av bilder. picassoBuilder.downloader () // Angi ExecutorService for å laste bilder i bakgrunnen. picassoBuilder.executor () // Angi minnebufferen som brukes for de nyeste bildene. picassoBuilder.memoryCache () // og flere val picasso = picassoBuilder.build ()
Til slutt, du ringer til bygge()
metode for å returnere en Picasso
eksempel med dine egne konfigurasjoner.
Det anbefales at du gjør dette i din Application.onCreate
og sett den så som singleton-forekomsten med Picasso.setSingletonInstance
i den metoden - for å sikre at Picasso
eksempel er den globale.
laste()
Metode last (strengbane)
starter en bildeforespørsel ved hjelp av den angitte banen. Denne banen kan være en ekstern URL, filressurs, innholdsressurs eller Android-ressurs.
plassholder (int placeholderResId)
: En lokal plassholder ressurs ID eller drawable å bli brukt mens bildet lastes og deretter vises. Det fungerer som en god brukeropplevelse for å vise et plassholderbilde mens bildet lastes ned. Legg merke til at Picasso først kontrollerer om ønsket bilde er i minnekachen, og hvis det er, viser det bildet derfra (vi diskuterer caching i Picasso mer senere i et senere avsnitt).
feil (int errorResId)
: en tegning som kan brukes hvis det forespurte bildet ikke kunne lastes - sannsynligvis fordi nettsiden er nede. noFade ()
: Picasso forsvinner alltid i bildet som skal vises i Imageview
. Hvis du ikke vil ha denne fade-in animasjonen, bare ring noFade ()
metode. inn i (ImageView imageView)
: Målbildevisningen som bildet skal plasseres i.Hvis serveren du ber om bildet fra, ikke gir deg bildet du trenger i ønsket størrelse, kan du enkelt endre størrelsen på bildet ved hjelp av endre størrelse (int targetWidth, int targetHeight)
. Å ringe denne metoden endrer størrelsen på bildet og viser det på Imageview
. Merk at dimensjonene er i piksler (px), ikke dp.
Picasso.get () .load (sunsetPhoto.url) .stedholder (R.drawable.placeholder) .resize (400, 200) .into (imageView)
Du kan sende inn en Android-dimensjonsressurs for både bredde og høyde ved hjelp av metoden resizeDimen (int targetWidthResId, int targetHeightResId)
. Denne metoden vil konvertere dimensjonsstørrelsen til råpiksler og deretter ringe endre størrelse ()
under hette-passerer de konverterte størrelsene (i piksler) som argumenter.
Picasso.get () // ... resizeDimen (R.dimen.list_detail_image_size, R.dimen.list_detail_image_size) // ...
Merk at disse endringene ikke respekterer størrelsesforholdet. Med andre ord kan bildeforholdet ditt forvrenges.
Heldigvis, Picasso
gir oss noen nyttige metoder for å løse dette problemet:
centerCrop ()
: Skalerer bildet jevnt (opprettholder bildeforholdet) slik at bildet fyller opp det oppgitte området, med så mye av bildet som mulig. Om nødvendig vil bildet bli beskåret horisontalt eller vertikalt for å passe. Å ringe denne metoden beskjærer et bilde inne i grensene angitt av endre størrelse ()
.centerInside ()
: skalerer bildet slik at begge dimensjonene er lik eller mindre enn de forespurte grensene. Dette vil sentrere et bilde inne i grensene spesifisert av endre størrelse ()
. onlyScaleDown ()
: Endre størrelsen på et bilde hvis den opprinnelige bildestørrelsen er større enn målstørrelsen spesifisert av endre størrelse ()
.passe()
: forsøk å endre størrelsen på bildet slik at det passer akkurat inn i målet Imageview
s grenser.Picasso har en enkel API for å rotere et bilde og deretter vise det bildet. De roter (float grader)
Metoden roterer bildet med de angitte grader.
Picasso.get () // ... rotere (90f) // ...
I eksemplet ovenfor vil dette rotere bildet med 90 grader. De roter (float grader, float pivotX, float pivotY)
Metoden roterer bildet med angitte grader rundt et svingpunkt.
Picasso.get () // ... rotere (30f, 200f, 100f) // ...
Her skal vi rotere bildet med 30 grader rundt pivotpunktet 200, 100 piksler.
Bortsett fra å bare manipulere et bilde ved å rotere det, gir Picasso oss også muligheten til å bruke en tilpasset transformasjon til et bilde før det vises.
Du oppretter bare en klasse som implementerer Picasso Transformation
grensesnitt. Du må da overstyre to metoder:
Bitmap-transformasjon (Bitmap-kilde)
: dette forvandler kildebitmapet til en ny bitmap. Strengnøkkel ()
: Returnerer en unik nøkkel for transformasjonen, brukt til cachingformål.Når du er ferdig med å skape din tilpassede transformasjon, utfører du det bare ved å påberope transformere (transformasjonstransformasjon)
på din Picasso-instans. Merk at du også kan sende en liste over Transformation
til forvandle()
.
Picasso.get () // ... transform (CropCircleTransformation ()) .into (imageView)
Her brukte jeg en omforming av sirkelavlinger til bildet fra Picasso Transformations open-source Android-biblioteket. Dette biblioteket har mange transformasjoner du kan søke på et bilde med Picasso-inkludert transformasjoner for uskarphet eller gråskalering av et bilde. Gå sjekke det ut hvis du vil bruke noen kule transformasjoner på bildene dine.
Her oppretter vi bare vår RecyclerView
med GridLayoutManager
Som layoutleder, initialiser adapteren, og bind den til RecyclerView
.
klasse MainActivity: AppCompatActivity () private lateinit var recyclerView: RecyclerView privat sentinit var imageGalleryAdapter: ImageGalleryAdapter override fun onCreate (savedInstanceState: Bundle?) // ... val layoutManager = GridLayoutManager (dette, 2) recyclerView = findViewById (R.id.rv_images ) recyclerView.setHasFixedSize (true) recyclerView.layoutManager = layoutManager imageGalleryAdapter = ImageGalleryAdapter (dette, SunsetPhoto.getSunsetPhotos ()) overstyre moro påStart () super.onStart () recyclerView.adapter = imageGalleryAdapter // ...
Opprett en ny aktivitet og navn den SunsetPhotoActivity
. Vi får SunsetPhoto
ekstra og last inn bildet innvendig onStart ()
-med Picasso som vi gjorde før.
Klassen SunsetPhotoActivity: AppCompatActivity () følgesvennobjekt const val EXTRA_SUNSET_PHOTO = "SunsetPhotoActivity.EXTRA_SUNSET_PHOTO" privat sentinit var imageView: ImageView privat seniit var sunsetPhoto: SunsetPhoto overstyr moro onCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState) setContentView R.layout.activity_sunset_photo) sunsetPhoto = intent.getParcelableExtra (EXTRA_SUNSET_PHOTO) imageView = findViewById (R.id.image) overstyre moro påStart () super.onStart () Picasso.get () .load (sunsetPhoto.url) .placeholder (R.drawable.placeholder) .error (R.drawable.error) .fit () .into (imageView)
Her er et oppsett for å vise detaljaktiviteten. Det viser bare en Imageview
som vil vise fulloppløsningsversjonen av det lastede bildet.
Hvis du observerer nøye, vil du legge merke til at når du går tilbake til et bilde som tidligere var lastet, laster det enda raskere enn før. Hva gjorde det raskere? Det er Picassos caching-mekanisme, det er det.
Her er det som skjer under hetten. Etter at et bilde er lastet inn en gang fra internett, vil Picasso cache det både i minne og på disk, lagrer gjentatte nettverksforespørsler og tillater raskere henting av bildet. Når bildet er nødvendig igjen, vil Picasso først sjekke om bildet er tilgjengelig i minnet, og hvis det er der, vil det returnere det umiddelbart. Hvis bildet ikke er i minnet, vil Picasso sjekke disken neste, og hvis den er der, returnerer den den. Hvis det ikke er der, vil Picasso endelig gjøre en nettverksforespørsel for det bildet og vise det.
Oppsummert, her er det som skjer (under hetten) for en bildeforespørsel: minne -> disk -> nettverk.
Avhengig av søknaden din, kan du likevel unngå cache-for eksempel hvis bildene som vises, sannsynligvis vil endre seg ofte og ikke bli lastet opp.
Du kan unngå minnebufring ved å ringe memoryPolicy (MemoryPolicy.NO_CACHE)
. Dette vil ganske enkelt hoppe over minnekachensoppslaget når du behandler en bildeforespørsel.
Picasso.get () .load (sunsetPhoto.url) .stedholder (R.drawable.placeholder) .error (R.drawable.error) .fit () .memoryPolicy (MemoryPolicy.NO_CACHE) .into (imageView)
Legg merke til at det er en annen enum: MemoryPolicy.NO_STORE
. Dette er nyttig hvis du er veldig sikker på at du bare vil be om et bilde en gang. Hvis du bruker dette, lagres ikke bildet i minnekufferen, og derved tvinges ikke andre bitmap fra minnekachen.
Men vær veldig oppmerksom på at bildet fortsatt vil bli cached på disken for å forhindre at du også bruker det networkPolicy (@NonNull NetworkPolicy policy, @NonNull NetworkPolicy ... tillegg)
, som tar en eller flere av følgende enumverdier:
NetworkPolicy.NO_CACHE
: hopper sjekker diskbufferen og styrker lasten gjennom nettverket.NetworkPolicy.NO_STORE
: hopper lagrer resultatet i diskbufferen.NetworkPolicy.OFFLINE
: styrker forespørselen bare gjennom diskbufferen, hopper over nettverket.For å unngå både minne og disk caching helt, bare ring begge metodene etter hverandre:
Picasso.get () .load (sunsetPhoto.url) .placeholder (R.drawable.placeholder) .error (R.drawable.error) .fit () .memoryPolicy (MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE) .networkPolicy (NetworkPolicy. NO_CACHE) .into (imageView)
I Picasso kan du implementere en lytter eller tilbakeringing for å overvåke statusen til forespørselen du laget som bildet laster. Bare en av disse metodene blir kalt hvis du implementerer Mål
grensesnitt på forespørsel.
ugyldig onBitmapFailed (e: Unntak?, errorDrawable: Drawable?)
: utløst når bildet ikke kunne lastes inn. Her kan vi få tilgang til unntaket som ble kastet. void onBitmapLoaded (Bitmap bitmap, LoadedFrom fra)
: sparket når et bilde er lastet inn. Her får vi bitmapet til å vise brukeren. void onPrepareLoad (Drawable placeHolderDrawable)
: Påkrevd rett før forespørselen er sendt inn. Picasso.get () .load (sunsetPhoto.url) .placeholder (R.drawable.placeholder) .error (R.drawable.error) .into (objekt: Target overstyr moro påPrepareLoad (placeHolderDrawable: Drawable?) Overstyrer moro onBitmapFailed (e: Unntak?, errorDrawable: Drawable?) overstyr moro onBitmapLoaded (bitmap: Bitmap ?, fra: Picasso.LoadedFrom?) )
Her kan du også vise og skjule en fremdriftsdialog hvis du hadde en.
Det er en annen tilbakeringingslytter du kan implementere hvis du vil, kalt Ring tilbake
. Dette grensesnittet har bare to metoder: onSuccess ()
og onError (Unntak e)
. Den førstnevnte heter når bildeforespørselsbelastningen var vellykket, og den senere blir kalt når det er en feil i behandlingen av forespørselen.
Kommer tilbake til vårt bildegalleri-app (inne SunsetPhotoActivity
), la oss endre skjermen litt ved hjelp av a Ring tilbake
objekt som vil sette bitmapet til Imageview
og endre også bakgrunnsfargen på layoutet ved å trekke ut den mørke og levende fargen på bildet vårt ved hjelp av Android Palette API.
Så inkluder palettartefaget i appmodulets build.gradle:
avhengigheter // ... implementering 'com.android.support:palette-v7:27.1.1'
La oss nå implementere Ring tilbake
grensesnitt i vår Picasso-forespørsel.
overstyr moro onStart () super.onStart () Picasso.get () .load (sunsetPhoto.url) .placeholder (R.drawable.placeholder) .error (R.drawable.error) .fit () .into (imageView, objekt: Tilbakering overstyr moro onSuccess () val bitmap = (imageView.drawable som BitmapDrawable) .bitmap onPalette (Palette.from (bitmap) .generate ()) overstyr moro onError (e: Exception?) ) morsom på Palette (palett: Palette?) hvis (null! = palett) val foreldre = imageView.parent.parent som ViewGroup parent.setBackgroundColor (palette.getDarkVibrantColor (Color.GRAY))
Til slutt kan du kjøre appen! Klikk på et miniatyrbilde for å få en full størrelse versjon av bildet.
Når du vil laste forskjellige bilder samtidig på samme skjerm, har du muligheten til å bestille hvilken som er viktigere enn den andre. Med andre ord kan du først laste viktige bilder.
Du ringer bare prioritet()
på din Picasso-forespørsel og pass på noen av enumene: Priority.LOW
, Priority.NORMAL
, eller Priority.HIGH
.
Picasso.get () .load (sunsetPhoto.url) .stedholder (R.drawable.placeholder) .error (R.drawable.error) .fit () .priority (Picasso.Priority.HIGH) .into (imageView) Picasso. få () .load (sunsetPhoto.url) .stedholder (R.drawable.placeholder) .error (R.drawable.error) .fit () .priority (Picasso.Priority.NORMAL) .into (imageView) Picasso.get ( ) .load (sunsetPhoto.url) .stedholder (R.drawable.placeholder) .error (R.drawable.error) .fit () .priority (Picasso.Priority.LOW) .into (imageView)
Ved å merke dine Picasso-forespørsler kan du fortsette, pause eller avbryte forespørsler som er knyttet til bestemte koder. Avhengig av brukssaken kan du merke dine forespørsler med en streng eller objekter som skal definere omfanget av forespørselen som en Kontekst
, en Aktivitet
, eller a Fragment
. Du kan enkelt merke en Picasso-forespørsel ved å ringe tag (@NonNull Object tag)
på en. Pass det en forekomst av Gjenstand
som tjener som taggen.
Her er følgende operasjoner du kan utføre på merkede Picasso-forespørsler:
pauseTag (Objekt-tag)
: Pause alle forespørsler knyttet til den oppgitte taggen. resumeTag (Object tag)
: Fortsett pauser forespørsler med den oppgitte taggen.cancelTag (Object tag)
: Slett eventuelle eksisterende forespørsler med den oppgitte taggen.Picasso.get () // ... tag (kontekst
Selv om merking av forespørsler gir deg litt kontroll over dine forespørsler, bør du være veldig forsiktig når du bruker koder på grunn av potensialet for minnelekkasjer. Her er hva den offisielle dokumentasjonen sier:
Picasso vil holde en referanse til taggen så lenge denne taggen er pauset og / eller har aktive forespørsler. Se opp for potensielle lekkasjer.
Det er greit å laste bilder lokalt i appen din.
Filfil = Ny fil ("din / bilde / fil / sti / fil.png") Picasso.get () .load (fil) .fit () .into (imageView)
Fin jobb! I denne opplæringen har du bygget et komplett bildegalleri-app med Picasso, og underveis har du lært hvordan biblioteket fungerer og hvordan du kan integrere det i ditt eget prosjekt.
Du har også lært hvordan du viser både lokale og eksterne bilder, merkingsforespørsler, prioritere forespørsler, og hvordan du bruker bildetransformasjoner som resizing. Ikke bare det, men du har sett hvor enkelt det er å aktivere og deaktivere caching, feilhåndtering og egendefinerte forespørsler.
For å lære mer om Picasso, kan du se den offisielle dokumentasjonen. For å lære mer om koding for Android, sjekk ut noen av våre andre kurs og opplæringsprogrammer her på Envato Tuts+!