Android RecyclerView: mis on, õppige lihtsate näidetega
Milles on RecyclerView Android?
. RecyclerView on vidin, mis on GridView ja ListView paindlikum ja täiustatud versioon. See on konteiner suurte andmekogumite kuvamiseks, mida saab tõhusalt kerida, säilitades piiratud arvu vaateid. Saate kasutada vidinat RecyclerView, kui teil on andmekogusid, mille elemendid käitusajal muutuvad, sõltuvad võrgusündmusest või kasutaja tegevusest.
views
. Android platvorm kasutab üksuste ekraanile joonistamiseks klasse View ja ViewGroup. Need klassid on abstraktsed ja neid laiendatakse erinevatele rakendustele vastavalt kasutusjuhtumile. Näiteks TextView'l on lihtne eesmärk kuvada ekraanil tekstisisu. EditText ulatub samast vaateklassist välja ja lisab rohkem funktsioone, mis võimaldavad kasutajal andmeid sisestada.
Võimalik on luua oma kohandatud vaateid, et saavutada kasutajaliideste arendamisel suurem paindlikkus. Klass Vaade pakub meetodeid, mida saame ekraanile joonistamisel alistada, ja vahendeid selliste parameetrite nagu laius, kõrgus ja oma kohandatud atribuudid, mida sooviksime oma vaatele lisada, et see käituks nii, nagu me sooviksime.
ViewGroups
Klass ViewGroup on omamoodi vaade, kuid erinevalt lihtsast vaateklassist, mille ülesanne on lihtsalt kuvamine, annab ViewGroup meile võimaluse panna ühte vaatesse mitu vaadet, millele saame viidata tervikuna. Sel juhul nimetatakse ülatasemel loodud vaadet, millele lisame muid lihtsaid vaateid (saame lisada ka vaaterühmi), vanemaks ja sees olevaid vaateid nimetatakse lastele.
Saame kujutada vaadet massiivina ja vaaterühma massiivi massiivina. Arvestades, et massiivi massiiv on massiiv ise, näeme, kuidas vaaterühma saab käsitleda vaatena.
var arr1 = [1,2,3] //imagine a simple View as an Array //we can imagine this as a NumberTextView which doesn't really exist //but we could imagine there's one that makes it easy to use numbers var arr2 = ["a","b","c"] // We can imagine this as another simple view var nestedArr = [arr1,arr2] //in our anology, we can now group views //together and the structure that would hold that would be what we call the ViewGroup
ViewGroup võimaldab meil ka määratleda, kuidas lapsed vaates on korraldatud, näiteks asetatakse need vertikaalselt või horisontaalselt. Meil võivad vaates interaktsiooniks olla erinevad reeglid. Näiteks üksteisele järgnevate TextView-vaadete kaugus peaks olema 12 dp, samas kui ImageView-de, millele järgneb TextView, kaugus peaks olema 5 dp.
See oleks nii, kui arendaksime oma ViewGroupi nullist. Nende seadistuste hõlbustamiseks Android pakub klassi nimega LayoutParams, mida saame kasutada nende konfiguratsioonide sisestamiseks.
Android dokumentatsioon pakub mõningaid vaikeparameetreid, mida rakendaksime oma ViewGroupi seadistamisel. Mõned levinumad parameetrid on need, mis puudutavad laiust, kõrgust ja veerist. Vaikimisi on nende konfiguratsioonide struktuur kõrguse jaoks android:layout_height, näiteks android:layout_width. Sellega seoses saate oma ViewGroupi loomisel täiendavalt luua paigutusparameetreid vastavalt sellele, kuidas soovite oma ViewGroupi käitumist.
Android kaasas vaikimisi vaated ja vaaterühmad, mida saame kasutada paljude vajalike tavapäraste toimingute tegemiseks. Üks näide, mida oleme maininud, on TextView. See on lihtne vaade, mis sisaldab konfigureeritavaid aspekte, nagu kõrgus, laius, teksti suurus ja muu sarnane. Meil on piltide kuvamiseks ja EditTexti kuvamiseks ImageView, nagu olime paljude teiste hulgas maininud. Android sisaldab ka kohandatud vaaterühmi, kuhu saame oma vaated lisada ja soovitud käitumist saavutada.
Lineaarne paigutus
LinearLayout võimaldab meil lisada sellesse vaateüksusi. LinearLayout on orientatsiooniatribuut, mis määrab, kuidas see ekraanil paigutatakse. Sellel on ka LinearLayout.LayoutParams, mis dikteerivad sisemiste vaadete reeglid, näiteks atribuut android:center_horizontal tsentreerib vaated piki horisontaaltelge, samas kui atribuut `android:center_vertical tsentreerib vaate sisu piki vertikaaltelge.
Siin on mõned pildid tsentreerimise mõistmiseks. Peaksime seda lihtsaks TextView'ks, mille suurus on 200 x 200 pikslit, atribuutide tsentreerimine paneks selle käituma järgmiselt.
android: center_horizontal

android: center_vertical

android:center

RecyclerView põhikomponendid

Järgmised on RecyclerView olulised komponendid.
RecyclerView.Adapter
Alustöö nr 1 – adapteri muster
Adapter on seade, mis muudab süsteemi või seadme atribuudid muul viisil ühildumatu seadme või süsteemi atribuudideks. Mõned neist muudavad signaali või võimsuse atribuute, teised aga lihtsalt kohandavad ühe konnektori füüsilist vormi teisega.
Lihtne näide, mida me päriselus leiame adapteri selgitamiseks, on see, kui peame seadmed omavahel ühendama, kuid neil on ühenduspordid, mis ei sobi üksteisega. See võib juhtuda, kui külastate mõnda teist riiki, kus nad kasutavad erinevat tüüpi pistikupesasid. Kui kannate telefoni või sülearvuti laadijat, oleks seda võimatu vooluvõrku ühendada. Kuid te ei anna alla, vaid hankite lihtsalt adapteri, mis tuleks pistikupesa ja laadija vahele ning võimaldaks laadimist.
See kehtib programmeerimise puhul, kui tahame ülesande täitmiseks ühendada kaks andmestruktuuri, kuid nende vaikepordid ei saa omavahel suhelda.
Kasutame lihtsat näidet seadmest ja laadijast. Meil on kaks laadijat. Ameerika ja Briti oma
class AmericanCharger() {
var chargingPower = 10
}
class BritishCharger(){
var charginPower = 5
}
Seejärel loome kaks seadet
class AmericanDevice() class BritishDevice()
Näitena saame seejärel luua mõned seadmete eksemplarid kaasamängimiseks.
var myAmericanPhone = new AmericanDevice() var myBritishPhone = new BritishDevice()
Seejärel tutvustame mõlema seadme laadimise kontseptsiooni, lisades seadmetes meetodi charge() .
Meetod võtab sisendiks vastava laadija ja laadib selle alusel.
sealed trait Device
class AmericanDevice : Device{
fun charge(charger:AmericanCharger){
//Do some American charging
}
}
class BritishDevice: Device{
fun charge(charger:BritishCharger){
//Do some British charging
}
}
Sel juhul vajaksime meie analoogia põhjal ühel või teisel põhjusel AmericanDevice'i kasutamisel BritishChargerit või vastupidi.
Programmeerimismaailmas on see tavaliselt sama funktsiooni pakkuvate teekide segamisel (meie kontekstis on meie jagatud funktsionaalsus tasuline). Peaksime leidma viisi selle võimaldamiseks.
Kui järgime analoogiat, peame minema elektroonikapoodi ja ostma adapteri, mille abil saaksime laadida AmericanDevices'i, kui on antud BritishChargers. Programmeerimise vaatenurgast oleme need, kes on adapteri tootjad.
Valmistame ühe jaoks adapteri, mis sobib täpselt teise loomiseks vajamineva mustriga. Rakendame seda klassina järgmiselt. See ei pea tingimata olema klass ja see võib olla funktsioon, mis tõstab esile selle, mida adaptermuster üldiselt teeb. Kasutame klassi, mis vastab enamikule kasutusaladele Android.
class AmericanToBritishChargerAdapter(theAmericanCharger:AmericanCharger){
fun returnNewCharger(): BritishCharger{
//convert the American charger to a BritishCharger
//we would change the American charging functionality
//to British charging functionality to make sure the
//adapter doesn't destroy the device. The adapter could
//, for example, control the power output by dividing by 2
//our adapter could encompass this functionality in here
var charingPower:Int = charger.chargingPower / 2
var newBritishCharger = new BritishCharger()
newBritishCharger.chargingPower = theAmericanCharger.chargingPower/2
return newBritishCharger
}
}
Programmeerimismaailmas on pistikupesade erinevus analoogne laadimiseks kasutatavate meetodite erinevusega. Erinevate meetoditega laadijad muudaksid laadijate kasutamise võimatuks.
var myBritishDevice = new BritishDevice() var americanChargerIFound = new AmericanCharger()
Meetodi charge() kutsumine rakenduses myBritishDevice koos americanChargerIFoundiga ei toimi, kuna AmericanDevice aktsepteerib ainult AmericanChargerit
Nii et seda on võimatu teha
var myBritishDevice = new BritishDevice() var americanChargerIFound = new AmericanCharger() myBritishDevice.charge(americanChargerIFound)
Selles stsenaariumis on meie loodud adapter
AmericanToBritishChargerAdapter võib nüüd kasuks tulla. Meetodit returnNewCharger() saame kasutada uue BritishChargeri loomiseks, mida saame kasutada laadimiseks. Kõik, mida me vajame, on luua meie adapteri eksemplar ja toita see meil oleva AmericanChargeriga ning see loob BritishChargeri, mida saame kasutada.
var myBritishDevice = new BritishDevice() var americanChargerIFound = new AmericanCharger() //We create the adapter and feed it the americanCharger var myAdapter = AmericanToBritishChargerAdapter(theAmericanCharger) //calling returnNewCharger from myAdapter would return a BritishCharger var britishChargerFromAdapter = myAdapter.returnNewCharger() //and once we have the britishCharger we can now use it myBritishDevice.charge(britishChargerFromAdapter)
RecyclerView.LayoutManager
Vaaterühmaga tegelemisel paigutaksime vaated selle sisse. LayoutManageri ülesanne on kirjeldada, kuidas vaated sees on.
Võrdluseks, Linearlayout ViewGroupiga töötamisel soovime, et saaksime üksusi paigutada kas vertikaalselt või horisontaalselt. Seda on lihtne rakendada, lisades orientatsiooniatribuudi, mis ütleb meile, kuidas lineaarpaigutus ekraanile paigutatakse. Saame seda teha kasutades android:orientation=VERTICAL|HORIZONTAL atribuut.
Meil on ka teine ViewGroup nimega GridLayout, seda kasutatakse siis, kui soovime paigutada vaated ristkülikukujulisse ruudustikustruktuuri. Selle põhjuseks võivad olla näiteks rakenduse kasutajale esitatavate andmete hõlpsa tarbimise muutmine. Disaini järgi võimaldab GridLayout konfiguratsioone, mis aitavad teil seda eesmärki saavutada, kasutades konfiguratsioone, kus saame määratleda ruudustiku mõõtmed, näiteks 4 × 4 ruudustik, 3 × 2 ruudustik.
RecyclerView.ViewHolder
ViewHolder on abstraktne klass, mida laiendame ka RecyclerView'st. ViewHolder pakub meile ühiseid meetodeid, mis aitavad meil viidata vaatele, mille oleme RecyclerView'sse paigutanud, isegi pärast seda, kui RecyclerView'i taaskasutusmasinad on muutnud mitmesuguseid viiteid, millest me ei tea.
Suured nimekirjad
RecyclerViews kasutatakse siis, kui tahame kasutajale esitada tõeliselt suure hulga vaateid, ilma et see kurnata RAM meie seadmes iga loodud vaate eksemplari jaoks.
Kui võtaksime kontaktiloendi, saaksime üldise ettekujutuse sellest, kuidas üks kontakt loendis välja näeb. Seejärel loome mallipaigutuse – mis on tegelikult vaade – pesadega, kuhu täituvad erinevad andmed meie kontaktide loendist. Järgnev on pseudokood, mis selgitab kogu eesmärki:
//OneContactView
<OneContact>
<TextView>{{PlaceHolderForName}}</TextView>
<TextView>{{PlaceHolderForAddress}}</TextView>
<ImageView>{{PlaceHolderForProfilePicture}}</ImageView>
<TextView>{{PlaceHolderForPhoneNumber}}</TextView>
</OneContact>
Siis oleks meil seda laadi kontaktiloend
<ContactList> </ContactList>
Kui see nii on, kodeerisime sisu kõvasti, meil poleks programmilist viisi loendisse uue sisu lisamiseks ilma rakendust ümber kirjutamata. Meie õnneks. Vaate lisamist ViewGroupi toetab an addView(view:View) meetod.
Isegi kui see nii on, ei lisa RecyclerView sellele lastevaateid.
Meie kasutusjuhul oleks meil pikk kontaktide loend. Peaksime iga loendis oleva kontakti jaoks looma OneContactView ja sisestama vaates olevad andmed, et need vastaksid meie kontaktiklassi väljadele. Kui vaade on käes, peaksime selle loendi kuvamiseks lisama RecyclerView'sse.
data class Contact(var name:String, var address:String, var pic:String, var phoneNumber:Int)
var contact1 = Contact("Guru","Guru97", "SomePic1.jpg", 991)
var contact2 = Contact("Guru","Guru98", "SomePic2.jpg", 992)
var contact3 = Contact("Guru","Guru99", "SomePic3.jpg", 993)
var myContacts:ArrayList<Contact> = arrayListOf<Contact>(contact1,contact2,contact3)
Meil on hulk kontakte nimega OneContactView. See sisaldab pesasid kontaktiklassi sisu võtmiseks ja kuvamiseks. RecyclerView's peame lisama sellele vaated, et see saaks meid selle taaskasutusvõimega aidata.
RecyclerView ei võimalda meil tegelikult vaadet lisada, kuid võimaldab meil lisada ViewHolderi. Nii et selle stsenaariumi korral on meil kaks asja, mida tahame ühendada, kuid ei ühti. Siin tulebki appi meie adapter. RecyclerView annab meile sarnase adapteri AmericanToBritishChargerAdapter() varasemast ajast, mis võimaldas meil muuta oma AmericanChargeri, mis oli meie BritishDevice'iga kasutuskõlbmatu, millekski kasutuskõlblikuks, mis on sarnane reaalses elus toiteadapteriga.
Selle stsenaariumi korral võtab adapter meie kontaktide massiivi ja vaate ning genereerib sealt ViewHolderid, mida RecyclerView on nõus aktsepteerima.
RecyclerView pakub liidest, mida saame laiendada oma adapteri loomiseks klassi RecyclerView.Adapter kaudu. Selle adapteri sees on viis ViewHolderi klassi loomiseks, millega RecyclerView soovib töötada. Seega on meil sama olukord, mis varem, kuid ühe lisaasjaga, see on adapter.
Meil on hulk kontakte, vaade ühe kontakti kuvamiseks OneContactView. RecyclerView on vaadete loend, mis pakuvad taaskasutusteenuseid, kuid on valmis võtma vastu ainult ViewHolders
Kuid selle stsenaariumi korral on meil nüüd klass RecyclerView.Adapter, millel on meetod ViewHolderide loomiseks.
fun createViewHolder(@NonNull parent: ViewGroup, viewType: Int): ViewHolder
RecyclerView.ViewHolder on abstraktne klass, mis võtab meie vaate argumendina ja teisendab selle ViewHolderiks.
See kasutab ümbrismustrit, mida kasutatakse klasside võimete laiendamiseks.
Alustöö nr 2 – ümbrismuster
Kasutame lihtsat näidet, et näidata, kuidas saame loomad rääkima panna.
sealed trait Animal{
fun sound():String
}
data class Cat(name:String):Animal{
fun sound(){
"Meow"
}
}
data class Dog(name:String):Animal{
fun sound(){
"Woof"
}
}
var cat1 = Cat("Tubby")
var dog1 = Dog("Scooby")
cat1.sound() //meow
dog1.sound() //woof
Ülaltoodud näites on meil kaks looma. Tahtsime juhuslikult lisada kõnelema panemise meetodi, kuid raamatukogu autoril polnud lõbus, leidsime siiski võimaluse. Meie loomade klassi jaoks oleks vaja ümbrist. Me teeksime seda, kui võtaksime looma oma klassi konstruktoriks
class SpeechPoweredAnimalByWrapper(var myAnimal:Animal){
fun sound(){
myAnimal.sound()
}
speak(){
println("Hello, my name is ${myAnimal.name}")
}
}
Nüüd saame edastada loomaeksemplari SpeechPoweredAnimalByWrapperile. Sellel meetodi sound() kutsumine kutsuks läbi looma sound() meetodi. Meil on ka täiendav speak()-meetod, mis läheb arvesse kui uus funktsionaalsus, mille lisame loomadele, kes on sisse antud. Saame seda kasutada järgmiselt:
var cat1 = Cat("Garfield")
cat1.sound()//"meow"
cat1.speak()// doesn't work as it isn't implemented
var talkingCat = new SpeechPoweredAnimalByWrapper(cat1)
talkingCat.sound() //"meow" the sound method calls the one defined for cat1
talkingCat.speak() //"Hello, my name is Garfield"
Seda mustrit kasutades saame võtta klasse ja lisada funktsioone. Kõik, mida me vajame, on klassi eksemplar ja uued meetodid, mille on määratlenud meie ümbrisklass.
Meie ülaltoodud juhul kasutasime betooniklassi. Sama on võimalik rakendada ka abstraktsetes klassides. Peaksime muutma klassi SpeechPoweredAnimalByWrapper abstraktseks ja olemegi valmis. Muudame klassi nime lühemaks, et see oleks loetavam.
abstract class SpeechPowered(var myAnimal:Animal){
fun sound(){
myAnimal.sound()
}
speak(){
println("Hello, my name is ${myAnimal.name}")
}
}
See on sama, mis varem, kuid see tähendaks midagi muud. Tavaklassis võib meil olla klassi eksemplar samamoodi, nagu lõime kass1 ja koer1. Abstraktsed klassid ei ole aga mõeldud eksemplarideks, vaid need on mõeldud teiste klasside laiendamiseks. Niisiis, kuidas me kasutaksime uut abstraktset klassi SpeechPowered(var myAnimal:Animal). Saame seda kasutada, luues uusi klasse, mis laiendavad seda ja omakorda omandavad selle funktsionaalsuse.
Meie näites loome klassi SpeechPoweredAnimal, mis laiendab klassi
class SpeechPoweredAnimal(var myAnimal:Animal):SpeechPowered(myAnimal)
var cat1 = Cat("Tubby")
var speakingKitty = SpeechPoweredAnimal(cat1)
speakingKitty.speak() //"Hello, my name is Tubby"
See on sama muster, mida kasutatakse ViewHolderis. Klass RecyclerView.ViewHolder on abstraktne klass, mis lisab vaatele funktsionaalsust, umbes nagu oleme loomadele lisanud kõnemeetodi. Lisafunktsioonid on see, mis paneb selle RecyclerView'ga tegelemisel tööle.
Nii loome OneContactView'st OneContactViewHolderi
//The View argument we pass is converted to a ViewHolder which uses the View to give it more abilities and in turn work with the RecyclerView class OneContactViewHolder(ourContactView: View) : RecyclerView.ViewHolder(ourContactView)
RecyclerView'l on adapter, mis võimaldab meil ühendada meie kontaktide massiivi RecyclerView'ga ContactsView'ga
Vaate lisamine
ViewGroup ei joonista ViewGroupi automaatselt ümber, vaid järgib kindlat ajakava. Teie seadmes võib juhtuda, et see joonistab uuesti iga 10 ms või 100 ms järel või kui valime vaate ViewGroupi lisamisel absurdse arvu, näiteks 1 minuti, näete muudatusi 1 minut hiljem, kui ViewGroup "värskendub".
RecyclerView.Recycler
Alustöö nr 3. Vahemällu salvestamine
Üks parimaid näiteid selle kohta, kus me regulaarselt värskendame, on brauser. Kujutagem näiteks ette, et meie külastatav sait on staatiline ega saada sisu dünaamiliselt. Muudatuste nägemiseks peaksime pidevalt värskendama.
Selle näite puhul kujutame ette, et kõnealune sait on Twitter. Meil oleks loendis rida staatilisi säutse ja ainus viis, kuidas saaksime uusi säutse näha, on klõpsata sisu uuesti toomiseks värskendamisnupul.
Kogu ekraani ülevärvimine on ilmselgelt kulukas asi. Kui peaksime ette kujutama, et see nii oleks, oli meil oma telefoniteenuse pakkujaga piiratud ribalaius. Ja meie säutsuloendis oli palju pilte ja videoid, oleks kulukas lehe kogu sisu uuesti alla laadida iga värskenduse järel.
Vajame viisi juba laaditud säutsude salvestamiseks ja tagame, et meie järgmisel päringul on võime öelda juba olemasolevaid säutse. Seetõttu ei laadi see kõike uuesti alla ja hangib ainult uued säutsud, mis tal on, ning kontrollib ka, kas mõnda lokaalselt salvestatud säutsu pole enam olemas, et saaks selle kohapeal kustutada. Seda, mida me kirjeldame, nimetatakse vahemällu salvestamiseks.
Teavet, mille me saadame veebisaidile oma sisu kohta, nimetatakse metaandmeteks. Nii et tegelikus mõttes me ei ütle lihtsalt „tahame teie saiti laadida“, vaid „tahame teie saiti laadida ja siin on osa sisust, mille olime juba viimase laadimise ajal salvestanud. Palun kasutage seda saatke meile ainult seda, mida seal pole, nii et me ei kasuta palju ribalaiust, kuna meil pole palju ressursse.
Paigutuskõned – säutsuloend peab olema hull
Paigutuskutsete näide on scrollToPosition
See on tavaline näide, mis esineb näiteks vestlusrakendustes. Kui keegi vestluslõimes vastab varasemale vestlusmullile, sisaldavad mõned vestlusrakendused vastust ja linki vestlusmullile, mis klõpsamisel suunab teid algse sõnumi asukohta.
Sel juhul kutsume seda meetodit välja enne, kui oleme oma RecyclerView'le lisanud LayoutManageri ja enne kui meil on RecyclerView.Adapter, ignoreeritakse scrollToPosition(n:Int) lihtsalt.
RecyclerView komponentide vaheline suhtlus
Alustöö nr 4. Tagasihelistamised
RecyclerView omab oma tööd tehes palju liikuvaid osi. See peab tegelema LayoutManageriga, mis ütleb meile, kuidas vaateid korraldada kas lineaarselt või ruudustikus. See peab tegelema adapteriga, mis muudab meie üksuste kontaktloendi vaadeteks OneContactView ja seejärel ViewHolderiteks OneContactViewHolder, mida RecyclerView on valmis meile pakutavate meetodite raames töötama.
RecyclerView tooraineks on meie vaated, nt OneContactView ja andmeallikas.
contactList:Array<Contact>
Oleme kasutanud lihtsat stsenaariumi lähtepunktina, et saada aimu, mida RecyclerView püüab saavutada.
Lihtne mõista, kui meil on 1000 kontaktist koosnev staatiline massiiv, mida tahame kasutajale näidata.
RecyclerView masinavärk hakkab tõesti elu võtma, kui loend ei ole enam staatiline.
Dünaamilise loendi puhul peame mõtlema, mis juhtub ekraanil kuvatava vaatega, kui lisame loendisse üksuse või eemaldame üksuse loendist.
RecyclerView.LayoutManager
Peale selle, et me otsustame, kuidas meie vaated lineaarselt või ruudustikuna paigutada. LayoutManager teeb kapoti all palju tööd, et aidata taaskasutajal teada, millal ringlussevõttu teha.
See vastutab praegu ekraanil nähtavate vaadete jälgimise ja selle teabe edastamise eest taaskasutusmehhanismile. Kui kasutaja allapoole kerib, vastutab paigutushaldur selle eest, et teavitada taaskasutussüsteemi vaadetest, mis lähevad ülaosas fookusest välja, et neid saaks uuesti kasutada, selle asemel, et need sinna jääda ja mälu tarbida või hävitada ja luua. uued.
See tähendab, et LayoutManager peab meie loendit kerides jälgima, kus kasutaja asub. Selleks on positsioonide loend, mis on indeksi alus, st esimene üksus peab algama 0-st ja suurendama seda, et see vastaks meie loendis olevate üksuste arvule.
Kui saame vaadata 10 üksust näiteks 100 loendis, siis alguses on LayoutManager teadlik, et sellel on fookuses vaade 0 kuni vaateni 9. Kerimise ajal suudab LayoutManager arvutada välja ilmuvad vaated. fookusest.
LayoutManager suudab need vaated taaskasutusmehhanismile vabastada, et neid saaks uuesti kasutada (neiga saab siduda uusi andmeid, nt vaate kontaktandmeid saab eemaldada ja kohahoidjaid saab asendada järgmise segmendi uute kontaktandmetega).
See oleks õnnelik juhtum, kui meil olev loend on staatiline, kuid üks levinumaid RecyclerView kasutamise juhtumeid on dünaamilised loendid, kus andmed võivad pärineda veebipõhisest lõpp-punktist või isegi andurilt. Andmeid mitte ainult ei lisata, vaid mõnikord ka meie loendis olevaid andmeid eemaldatakse või värskendatakse.
Meie andmete dünaamiline olek võib muuta LayoutManageri põhjendamise väga keeruliseks. Sel põhjusel haldab LayoutManager üksuste ja positsioonide kohta oma loendit, mis on eraldi taaskasutuskomponendi kasutatavast loendist. See tagab, et see täidab oma paigutustööd õigesti.
Samal ajal ei taha RecyclerView's LayoutManager olemasolevaid andmeid valesti esitada. Korrektseks töötamiseks sünkroonib LayoutManager RecyclerView.Adapteriga etteantud ajavahemike järel (60 ms), jagades teavet meie loendi üksuste kohta. st üksused lisatud, värskendatud, eemaldatud, ühest kohast teise teisaldatud). LayoutManager korraldab selle teabe saamisel ekraanil oleva sisu ümber, et see vastaks vajadusel tehtud muudatustele.
Paljud RecylerView'ga seotud põhitoimingud pöörlevad ümber RecyclerView.LayoutManageri ja RecyclerView.Adapteri vahelise suhtluse, mis salvestab meie mõnikord staatiliste või mõnikord dünaamiliste andmete loendid.
Veelgi enam, RecyclerView pakub meile meetodeid, mida saame kasutada selliste sündmuste kuulamiseks nagu onBindViewHolder, kui meie RecyclerView.Adapter seob sisu meie loendist, nt kontakti ViewHolderiga, nii et see harjub nüüd teabe kuvamisega ekraanil.
Teine on onCreateViewHolder, mis annab meile teada, millal RecyclerView. Adapter võtab tavalise vaate nagu OneContactView ja teisendab selle ViewHolderi üksuseks, millega RecyclerView saab töötada. Meie ViewHolderist RecyclerView kasutamiseks. onViewDetached
Peale ringlussevõttu võimaldavate põhimehhanismide. RecyclerView pakub viise käitumise kohandamiseks ilma ringlussevõttu mõjutamata.
Vaadete korduvkasutamine muudab staatiliste vaadetega harjunud tavapäraste toimingute tegemise keeruliseks, näiteks onClicki sündmustele reageerimise.
Nagu me teame, et RecyclerView.LayoutManager mis esitleb kasutajale vaateid, võib hetkeks olla üksuste loendist erinev RecyclerView.Adapter millel on loend, mille oleme andmebaasi salvestanud või mille oleme allikast voogedastanud. OnClicki sündmuste otse vaadetesse paigutamine võib põhjustada ootamatu käitumise, näiteks vale kontakti kustutamise või muutmise.
Gradle
Kui tahame RecyclerView't kasutada, peame lisama selle oma build .gradle-faili sõltuvusena.
Järgmises näites oleme kasutanud rakendust „androidx.recyclerview:recyclerview:1.1.0”, mis on selle artikli järgi kõige uuem versioon.
Pärast sõltuvuse lisamist meie Gradle faili, küsib meilt Android Stuudio juurde Syncmuuta muudatusi,
Nii on meie Gradle fail näeb välja selline, nagu pärast RecyclerView lisamist tühja projekti ainult vaikeväärtustega.
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.guru99.learnrecycler"
minSdkVersion 17
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation "androidx.recyclerview:recyclerview:1.1.0"
}
Meil on hetkel ainult üks paigutusfail. Alustame lihtsa näitega, kus kasutame RecyclerView'd, et kuvada ekraanil puuviljanimede loend.
Üksuste loend
Navigeerime oma MainActivity faili ja loome massiivi puuviljade nimedega vahetult enne seadistamise ajal loodud meetodit onCreate().
package com.guru99.learnrecycler
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Meie järgmine eesmärk on esitada see loend ekraanil RecyclerView abil.
Selleks navigeerime paigutuskataloogi, mis sisaldab meie paigutusi, ja loome vaate, mis vastutab ühe vilja kuvamise eest.
Paigutus, mida kasutatakse meie loendi iga üksuse jaoks
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fruitName"
/>
</TextView>
Ülaltoodud tekstivaatesse oleme lisanud ID-välja, mida kasutatakse vaate tuvastamiseks.
Vaikimisi seda ei genereerita. Meil on TextView id fruitName, et see sobiks andmetega, mis sellega seotakse.
RecyclerView lisamine põhipaigutusele
Samas tegevuses on küljendusfail main_layout.xml, mis vaikimisi meie jaoks genereeriti.
Kui valisime tühja projekti. See on tekitanud XML ConstraintLayout sisaldav ja sees on TextView koos "Tere" tekstiga.
Kustutame kogu sisu ja laseme küljendus sisaldada ainult RecyclerView'd, nagu allpool.
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fruitRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />
Lisasime ka atribuudi RecyclerView id, mida kasutame sellele oma koodis viitamiseks.
android:id="@+id/fruitRecyclerView"
Seejärel navigeerime tagasi oma MainActivity faili. Kasutades meie loodud ID-sid, saame viidata äsja loodud vaadetele.
Alustuseks viitame RecyclerView'le, kasutades pakutud meetodit findViewById(). Android. Teeme seda oma onCreate() meetodil.
Meie meetod onCreate() näeb välja järgmine.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
}
Loo ViewHolder
Järgmisena loome RecyclerView.ViewHolderi, mis vastutab meie vaate loomise ja teisendamise eest ViewHolderiks, mida RecyclerView kasutab meie üksuste kuvamiseks.
Teeme seda kohe pärast meie lõbusat onCreate() meetodit.
package com.guru99.learnrecycler
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
}
class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)
}
Looge RecyclerView Adapter
Järgmisena loome klassi FruitArrayAdapter, mis laiendab klassi RecyclerView.Adapter.
Meie loodud FruitArrayAdapter vastutab järgmiste toimingute eest.
See võtab puuviljade massiivist puuviljanimed. See loob ViewHolderi, kasutades meie vaadet one_fruit_view.xml See seob vilja ViewHolderiga ja seob sisu dünaamiliselt vaatega, mille oleme loonud one_fruit_view.xml.
package com.guru99.learnrecycler
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
}
class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)
class FruitArrayAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>()
}
Android Studio lisab meie FruitArrayAdapterile punased tõmblused, öeldes meile, et peame rakendama meetodi, mida RecyclerView saab kasutada meie massiivi ühendamiseks ViewHolderiga, mida RecyclerView saab kasutada.
class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {
}
override fun getItemCount(): Int {
}
override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {
}
}
Alustame genereeritud koodi lihtsaima bitiga, mis on meetod getItemCount(). Me teame, kuidas saada massiivi üksuste arv, kutsudes välja meetodi array.length.
class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {
}
override fun getItemCount(): Int {
return fruitArray.size
}
override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {
}
}
Seejärel rakendame rakendusesCreateViewHolder lõbususe alistamise meetodi.
See on koht, kus RecyclerView palub meil aidata tal luua selle jaoks FruitHolder.
Kui meenutada, nägi meie FruitViewHolder klass välja selline:
class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)
See nõuab meie fruitView-d, mille lõime xml-failina one_fruit_view.xml
Saame sellele xml-ile viite luua ja selle vaateks teisendada järgmiselt.
class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {
var fruitView = LayoutInflater.from(parent.context).inflate(R.layout.one_fruit_view, parent, false)
var fruitViewHolder = FruitViewHolder(fruitView)
return fruitViewHolder
}
override fun getItemCount(): Int {
return fruitArray.size
}
override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {
}
}
Ülejäänud bitt on alistamine
fun onBindViewHolder(holder: FruitViewHolder, position: Int)
RecyclerView.Adapter küsib positsioonitäisarvuga, mida kasutame loendist üksuse toomiseks. See annab meile ka hoidiku, et saaksime puuviljamassiivist saadud üksuse siduda vaatega, mida hoitakse vaatehoidikus.
ViewHoderis hoitavale vaatele pääseb juurde välja ViewHolder.itemView kaudu. Kui oleme vaate saanud, saame sisu määramiseks kasutada varem loodud ID-d fruitName.
override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {
var ourFruitTextView = holder.itemView.findViewById<TextView>(R.id.fruitName)
var aFruitName = fruitArray.get(position)
ourFruitTextView.setText(aFruitName)
}
Sellega on meie FruitArrayAdapter valmis ja näeb välja järgmine.
class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {
var fruitView = LayoutInflater.from(parent.context).inflate(R.layout.one_fruit_view, parent, false)
var fruitViewHolder = FruitViewHolder(fruitView)
return fruitViewHolder
}
override fun getItemCount(): Int {
return fruitArray.size
}
override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {
var ourFruitTextView = holder.itemView.findViewById<TextView>(R.id.fruitName)
var aFruitName = fruitArray.get(position)
ourFruitTextView.setText(aFruitName)
}
}
Lõpuks oleme valmis meie RecyclerView ülejäänud osad ühendama. Mis loovad LayoutManageri, mis ütleb RecyclerView'le, kuidas loendi sisu kuvada. Kas kuvada lineaarselt, kasutades LinearLayoutManagerit, või ruudustikus, kasutades GridLayoutManagerit või StaggeredGridLayoutManagerit.
Loo paigutushaldur
Naaseme oma funktsiooni onCreate sisse ja lisame LayoutManageri
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
var fruitLinearLayout = LinearLayoutManager(this)
myFruitRecyclerView.layoutManager =fruitLinearLayout
}
Ühendage meie adapter esemete külge ja seadke see RecyclerView'sse
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
var fruitLinearLayout = LinearLayoutManager(this)
myFruitRecyclerView.layoutManager =fruitLinearLayout
var fruitListAdapter = FruitListAdapter(fruitNames)
myFruitRecyclerView.adapter =fruitListAdapter
}
Oleme loonud ka fruitListAdapteri eksemplari ja andnud sellele puuviljanimede massiivi.
Ja põhimõtteliselt oleme kõik valmis.
Täielik MainActivity.kt fail näeb välja järgmine.
package com.guru99.learnrecycler
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
var fruitLinearLayout = LinearLayoutManager(this)
myFruitRecyclerView.layoutManager =fruitLinearLayout
var fruitListAdapter = FruitListAdapter(fruitNames)
myFruitRecyclerView.adapter =fruitListAdapter
}
class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)
class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {
var fruitView = LayoutInflater.from(parent.context).inflate(R.layout.one_fruit_view, parent, false)
var fruitViewHolder = FruitViewHolder(fruitView)
return fruitViewHolder
}
override fun getItemCount(): Int {
return fruitArray.size
}
override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {
var ourFruitTextView = holder.itemView.findViewById<TextView>(R.id.fruitName)
var aFruitName = fruitArray.get(position)
ourFruitTextView.setText(aFruitName)
}
}
}
