Bu codelab, Android Kotlin Temelleri kursuna dahildir. Codelab'ler üzerinden sırayla çalışıyorsanız bu kurstan en iyi şekilde yararlanabilirsiniz. Tüm kurs codelab'leri Android Kotlin Fundamentals codelabs açılış sayfasında listelenmektedir.
Giriş
Bu dersin önceki codelab'lerinde, bir web hizmetinden Mars'ta gayrimenkul verileri almayı ve bu verilerdeki resimleri yükleyip görüntülemek için tablo düzeniyle nasıl RecyclerView
oluşturacağınızı öğrendiniz. Bu codelab'de, Mars mülklerini kiralanabilen ya da satın alınabilen web sitelerine göre filtreleme özelliğini uygulayarak MarsRealEstate uygulamasını tamamladınız. Ayrıca, kullanıcı genel bakış içindeki bir mülk fotoğrafına dokunursa mülkle ilgili ayrıntıları içeren bir ayrıntılı görünüm göreceği için ayrıntılı görünüm de oluşturursunuz.
Bilmeniz gerekenler
- Parça oluşturma ve kullanma.
- Parçalar arasında gezinme ve parçalar arasında veri iletmek için Güvenli Args (Gradle eklentisi) kullanma.
- Görünüm modelleri, görünüm modeli fabrikaları, dönüşümler ve
LiveData
dahil olmak üzere mimari bileşenlerin nasıl kullanılacağı. - Bir REST web hizmetinden JSON kodlu verileri alma ve bu verileri Retrofit ve Moshi kitaplıklarıyla Kotlin nesnelerine ayrıştırma.
Neler öğreneceksiniz?
- Düzen dosyalarınızda karmaşık bağlama ifadeleri kullanma.
- Sorgu seçenekleriyle web hizmetine Retrofit istekleri gönderme.
Ne yaparsınız?
- Satılık Mars mülklerini (kiralık olanlar yerine) dolar işareti simgesiyle işaretlemek için MarsRealEstate uygulamasını değiştirin.
- Mars mülklerini türe göre filtreleyen bir web hizmeti isteği oluşturmak için genel bakış sayfasındaki seçenekler menüsünü kullanın.
- Mars mülkü için bir ayrıntı parçası oluşturun, bu parçayı gezinmeyle genel bakış tablosuna bağlayın ve mülk verilerini bu parçaya geçirin.
Bu codelab'de (ve ilgili codelab'lerde) MarsRealEstate adında, Mars'ta satılık mülkleri gösteren bir uygulamayla çalışıyorsunuz. Bu uygulama, fiyat bilgisi ve tesisin satılık veya kiralık olup olmadığı gibi ayrıntılar dahil olmak üzere tesis verilerini almak ve görüntülemek için bir internet sunucusuna bağlanır. Her mülkü temsil eden resimler, Mars'ın Mars gezginlerinden çekilen Mars'ın gerçek fotoğraflarıdır. Önceki codelab'lerde, tüm mülk fotoğrafları için ızgara düzenine sahip bir RecyclerView
oluşturdunuz:
Uygulamanın bu sürümünde mülkün türüyle (kiralama ve satın alma) birlikte çalışır ve satılık mülkleri işaretlemek için tablo düzenine bir simge eklersiniz:
Uygulamanın seçenek menüsünü değiştirerek ızgarayı yalnızca kiralanabilen veya satılık tesisleri gösterecek şekilde filtreleyebilirsiniz:
Son olarak, tek bir mülk için ayrıntı görünümü oluşturur ve genel bakış ızgarasındaki simgeleri gezinme özelliğiyle bu ayrıntı parçasına bağlarsınız:
Şu ana kadar, Mars mülkü verilerinin tek parçası, mülk resminin URL'siydi. Ancak, MarsProperty
sınıfında tanımladığınız mülk verileri de bir kimlik, fiyat ve tür (kiralık veya satılık) içerir. Hafızanızı tazelemek için web hizmetinden aldığınız JSON verilerinin snippet'i aşağıda verilmiştir:
{
"price":8000000,
"id":"424908",
"type":"rent",
"img_src": "http://mars.jpl.nasa.gov/msl-raw-images/msss/01000/mcam/1000ML0044631290305226E03_DXXX.jpg"
},
Bu görevde satıştaki genel bakış sayfasındaki mülklere dolar işareti eklemek için Mars mülkü türüyle çalışmaya başlarsınız.
1. Adım: MarsProperty'i türü içerecek şekilde güncelleyin
MarsProperty
sınıfı, web hizmeti tarafından sağlanan her mülkün veri yapısını tanımlar. Önceki bir codelab'de, Mars web hizmetinden ham JSON yanıtını bağımsız MarsProperty
veri nesnelerine ayrıştırmak için Moshi kitaplığını kullanıyordunuz.
Bu adımda, MarsProperty
sınıfına bir mülkün kiralık olup olmadığını (yani türün "rent"
veya "buy"
dizesi olup olmadığını) belirtmek için bazı mantık eklersiniz. Bu mantığı birden fazla yerde kullanırsınız. Bu nedenle, bu mantığı veri sınıfında çoğaltmak yerine burada kullanmanız daha iyi olur.
- Son codelab'den MarsRealEstate uygulamasını açın. (Uygulamanız yoksa MarsRealEstateEnlem'i indirebilirsiniz.)
network/MarsProperty.kt
'yi açın.MarsProperty
Sınıf tanımına bir gövde ekleyin ve nesne"rent"
türündeyseisRental
döndürentrue
için özel bir alıcı ekleyin.
data class MarsProperty(
val id: String,
@Json(name = "img_src") val imgSrcUrl: String,
val type: String,
val price: Double) {
val isRental
get() = type == "rent"
}
2. Adım: Izgara öğesi düzenini güncelleyin
Artık resimler ızgarasına ait öğe düzenini güncelleyerek yalnızca satılan satılık resimlerde bir dolar işareti çizebilirsiniz:
Veri bağlama ifadeleriyle bu testi tamamen ızgara öğelerinin XML düzeninde yapabilirsiniz.
res/layout/grid_view_item.xml
'yi açın. Bu,RecyclerView
tablosunun ızgara düzenindeki her bir hücrenin düzen dosyasıdır. Şu anda dosya, mülk resmi için yalnızca<ImageView>
öğesini içeriyor.<data>
öğesinin içineView
sınıfı için bir<import>
öğesi ekleyin. İçe aktarma özelliğini, bir düzen dosyasındaki veri bağlama ifadesi içinde bir sınıfın bileşenlerini kullanmak istediğinizde kullanabilirsiniz. Bu durumda,View.GONE
veView.VISIBLE
sabitlerini kullanacağınız içinView
sınıfına erişmeniz gerekir.
<import type="android.view.View"/>
- Resim görünümünün tamamını bir
FrameLayout
resmiyle çevreleyin. Böylece dolar işaretinin çizim resminin mülk resminin üzerine yığılmasına izin verilir.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="170dp">
<ImageView
android:id="@+id/mars_image"
...
</FrameLayout>
ImageView
öğesindeandroid:layout_height
üst öğesini yeniFrameLayout
alanını doldurmak içinmatch_parent
olarak değiştirin.
android:layout_height="match_parent"
- İlk öğenin hemen altına,
FrameLayout
içine ikinci bir<ImageView>
öğesi ekleyin. Aşağıda gösterilen tanımı kullanın. Bu resim, Mars resminin üst kısmında, ızgara öğesinin sağ alt köşesinde görünür ve dolar işareti simgesi içinres/drawable/ic_for_sale_outline.xml
öğesinde çizilebilir olanı kullanır.
<ImageView
android:id="@+id/mars_property_type"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:layout_gravity="bottom|end"
android:adjustViewBounds="true"
android:padding="5dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_for_sale_outline"
tools:src="@drawable/ic_for_sale_outline"/>
android:visibility
özelliğinimars_property_type
resim görünümüne ekleyin. Mülk türünü test etmek için bir bağlama ifadesi kullanın ve görünürlüğüView.GONE
(kiralama için) veyaView.VISIBLE
(satın alma için) olarak atayın.
android:visibility="@{property.rental ? View.GONE : View.VISIBLE}"
Şu ana kadar, yalnızca <data>
öğesinde tanımlanan bağımsız değişkenleri kullanan düzenlerde bağlayıcı ifadeler gördünüz. Bağlama ifadeleri son derece güçlü olup testleriniz ve matematik hesaplamaları gibi işlemleri XML düzeninizde gerçekleştirmenizi sağlar. Bu durumda, test gerçekleştirmek için üçlü operatörü (?:
) kullanırsınız (bu nesne bir kiralık mı?). Doğru için bir sonuç sağlarsınız (View.GONE
ile dolar işareti simgesini gizleyin) ve yanlış için başka bir sonuç sağlayın (bu simgeyi View.VISIBLE
ile gösterin).
Yeni grid_view_item.xml
dosyasının tamamı aşağıda gösterilmiştir:
<layout 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">
<data>
<import type="android.view.View"/>
<variable
name="property"
type="com.example.android.marsrealestate.network.MarsProperty" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="170dp">
<ImageView
android:id="@+id/mars_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:padding="2dp"
app:imageUrl="@{property.imgSrcUrl}"
tools:src="@tools:sample/backgrounds/scenic"/>
<ImageView
android:id="@+id/mars_property_type"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:layout_gravity="bottom|end"
android:adjustViewBounds="true"
android:padding="5dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_for_sale_outline"
android:visibility="@{property.rental ? View.GONE : View.VISIBLE}"
tools:src="@drawable/ic_for_sale_outline"/>
</FrameLayout>
</layout>
- Uygulamayı derleyip çalıştırın. Kiralık olmayan mülklerde dolar işareti simgesi olduğunu unutmayın.
Şu anda uygulamanız, genel bakış tablosunda tüm Mars mülklerini gösteriyor. Bir kullanıcı Mars'ta kiralık mülk alışverişi yapıyorsa, mevcut gayrimenkullerden hangilerinin satışta olduğunu belirten simgeler kullanmak yararlı olacaktır, ancak sayfada gezinilecek çok sayıda mülk olmalıdır. Bu görevde, genel bakış parçasına kullanıcının yalnızca kiralık mülkleri, yalnızca satılık mülkleri veya tümünü göstermesini sağlayan bir seçenekler menüsü eklersiniz.
Bu görevi gerçekleştirmenin bir yolu, genel bakış tablosunda her bir MarsProperty
için türü test etmek ve yalnızca eşleşen özellikleri görüntülemektir. Ancak asıl Mars web hizmeti, yalnızca rent
veya buy
türündeki mülkleri elde etmenizi sağlayan bir sorgu parametresine veya seçeneğine (filter
olarak adlandırılır) sahiptir. Bu filtre sorgusunu aşağıdaki gibi bir tarayıcıda realestate
web hizmeti URL'si ile kullanabilirsiniz:
https://android-kotlin-fun-mars-server.appspot.com/realestate?filter=buy
Bu görevde, Retrofit ile web hizmeti isteğine bir sorgu seçeneği eklemek için MarsApiService
sınıfını değiştirirsiniz. Ardından, ilgili sorgu seçeneğini kullanarak tüm Mars mülkü verilerini yeniden indirmek için seçenekler menüsünü bağlayabilirsiniz. Web hizmetinden aldığınız yanıt yalnızca ilgilendiğiniz mülkleri içerdiğinden genel bakış ızgarası için görüntüleme mantığını değiştirmeniz gerekmez.
1. Adım: Mars API hizmetini güncelleyin
İsteği değiştirmek için bu serideki ilk codelab'de uyguladığınız MarsApiService
sınıfını yeniden ziyaret etmeniz gerekir. Sınıfı, bir filtreleme API'si sağlayacak şekilde değiştirirsiniz.
network/MarsApiService.kt
'yi açın. İçe aktarmaların hemen altında, web hizmetinin beklediği sorgu değerleriyle eşleşen sabit değerler tanımlamak içinMarsApiFilter
adında birenum
oluşturun.
enum class MarsApiFilter(val value: String) {
SHOW_RENT("rent"),
SHOW_BUY("buy"),
SHOW_ALL("all") }
- Filtre sorgusu için dize girişini almak üzere
getProperties()
yöntemini değiştirin ve bu girişi aşağıda gösterildiği gibi@Query("filter")
ile ekleyin.
İstendiğinderetrofit2.http.Query
içe aktarın.@Query
ek açıklaması,getProperties()
yöntemine (ve dolayısıyla Retrofit'e) filtre seçeneğiyle web hizmeti isteği yapmasını söyler.getProperties()
her çağrıldığında, istek URL'si?filter=type
bölümünü içerir. Bu bölüm, web hizmetini bu sorguyla eşleşen sonuçlarla yanıt vermeye yönlendirir.
fun getProperties(@Query("filter") type: String):
2. Adım: Genel bakış görünümü modelini güncelleyin
OverviewViewModel
için getMarsRealEstateProperties()
yöntemindeki MarsApiService
kaynağından veri istiyorsunuz. Şimdi, filtre bağımsız değişkenini almak için bu isteği güncellemeniz gerekiyor.
overview/OverviewViewModel.kt
'yi açın. Önceki adımda yaptığınız değişiklikler nedeniyle Android Studio'da hatalar göreceksiniz.getMarsRealEstateProperties()
çağrısına parametre olarakMarsApiFilter
(olası filtre değerlerinin toplamı) ekleyin.
İstendiğindecom.example.android.marsrealestate.network.MarsApiFilter
içe aktarın.
private fun getMarsRealEstateProperties(filter: MarsApiFilter) {
- Söz konusu filtre sorgusunu dize olarak iletmek için Retrofit hizmetinde çağrıyı
getProperties()
olarak değiştirin.
var getPropertiesDeferred = MarsApi.retrofitService.getProperties(filter.value)
- Uygulama ilk yüklendiğinde tüm özellikleri göstermek için
init {}
blokundaMarsApiFilter.SHOW_ALL
öğesinigetMarsRealEstateProperties()
bağımsız değişkenine geçirin.
init {
getMarsRealEstateProperties(MarsApiFilter.SHOW_ALL)
}
- Sınıfın sonunda, bir
MarsApiFilter
bağımsız değişkenini alan ve bu bağımsız değişkenle birliktegetMarsRealEstateProperties()
'yi çağıran birupdateFilter()
yöntemi ekleyin.
fun updateFilter(filter: MarsApiFilter) {
getMarsRealEstateProperties(filter)
}
3. Adım: Parçayı seçenekler menüsüne bağlayın
Son adım, kullanıcı bir menü seçeneği belirlediğinde görünüm modelinde updateFilter()
öğesini çağırmak için taşma menüsünü parçaya bağlamaktır.
res/menu/overflow_menu.xml
'yi açın. MarsRealEstate uygulamasında mevcut üç seçeneği sağlayan bir taşma menüsü var: Tüm mülkleri gösterme, yalnızca kiralık yerleri gösterme ve sadece satılık mülkleri gösterme.
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/show_all_menu"
android:title="@string/show_all" />
<item
android:id="@+id/show_rent_menu"
android:title="@string/show_rent" />
<item
android:id="@+id/show_buy_menu"
android:title="@string/show_buy" />
</menu>
overview/OverviewFragment.kt
'yi açın. Dersin sonunda menü öğesi seçimlerini yönetmek içinonOptionsItemSelected()
yöntemini uygulayın.
override fun onOptionsItemSelected(item: MenuItem): Boolean {
}
onOptionsItemSelected()
için uygun modeli kullanarak görünüm modelindekiupdateFilter()
yöntemini çağırın. Seçenekler arasında geçiş yapmak için Kotlinwhen {}
bloğu kullanın. Varsayılan filtre değeri içinMarsApiFilter.SHOW_ALL
değerini kullanın. Menü öğesini işlediğiniz içintrue
ürününü iade edin. İstendiğindeMarsApiFilter
(com.example.android.marsrealestate.network.MarsApiFilter
) içe aktarın.onOptionsItemSelected()
yönteminin tamamı aşağıda gösterilmiştir.
override fun onOptionsItemSelected(item: MenuItem): Boolean {
viewModel.updateFilter(
when (item.itemId) {
R.id.show_rent_menu -> MarsApiFilter.SHOW_RENT
R.id.show_buy_menu -> MarsApiFilter.SHOW_BUY
else -> MarsApiFilter.SHOW_ALL
}
)
return true
}
- Uygulamayı derleyip çalıştırın. Uygulama, tüm mülk türleri ve dolar simgesiyle işaretlenmiş satış özellikleri ile ilk genel bakış ızgarasını başlatır.
- Seçenekler menüsünden Kirala'yı seçin. Özellikler yeniden yüklenir ve hiçbiri dolar simgesiyle görünmez. (Yalnızca kiralık mülkler gösterilir.) Yalnızca filtrelenen özelliklerin gösterilmesi amacıyla ekranın yenilenmesi için birkaç dakika beklemeniz gerekebilir.
- Seçenekler menüsünden Satın al'ı seçin. Özellikler yeniden yüklenir ve hepsi dolar simgesiyle görünür. (Yalnızca satılık mülkler gösterilir.)
Artık Mars mülkleri için kayan bir simge ızgaranıza sahipsiniz, ancak şimdi daha ayrıntılı bilginin zamanı geldi. Bu görevde belirli bir özelliğin ayrıntılarını görüntülemek için bir ayrıntı parçası eklersiniz. Ayrıntı parçası daha büyük bir resim, fiyat ve kiralık ya da satılık mülk türünü gösterir.
Bu parça, kullanıcı genel bakış tablosundaki bir resme dokunduğunda başlatılır. Bunu yapmak için RecyclerView
ızgara öğelerine bir onClick
işleyici eklemeniz ve ardından yeni parçaya gitmeniz gerekir. Bu derslerde yaptığınız gibi ViewModel
konumunda LiveData
değişikliği tetikleyerek geziniyorsunuz. Seçili MarsProperty
bilgilerini genel bakış parçasından ayrıntı parçasına iletmek için Gezinme bileşeninin Güvenli Args eklentisini de kullanırsınız.
1. Adım: Ayrıntı görünümü modelini oluşturun ve ayrıntı düzenini güncelleyin
Genel bakış görünümü modeli ve parçaları için kullandığınız yönteme benzer şekilde, şimdi ayrıntılı parça için görünüm modelini ve düzen dosyalarını uygulamanız gerekir.
detail/DetailViewModel.kt
'yi açın. Ağla ilgili Kotlin dosyalarının,overview
klasöründekinetwork
klasöründe ve genel bakış dosyalarında bulunması gibi,detail
klasörü de ayrıntılı görünümle ilişkilendirilmiş dosyaları içerir.DetailViewModel
sınıfının (şu anda boş) oluşturucudamarsProperty
olarak parametre aldığına dikkat edin.
class DetailViewModel( marsProperty: MarsProperty,
app: Application) : AndroidViewModel(app) {
}
- Ayrıntılı açıklamayı göstermek için, sınıf tanımının içinde, seçili Mars mülküne ait
LiveData
öğesini ekleyin.MarsProperty
öğesini tutmak için normal birMutableLiveData
oluşturma modeli uygulayın, ardından sabit bir genelLiveData
özelliğini gösterin.
İstendiğindeandroidx.lifecycle.LiveData
içe aktarın veandroidx.lifecycle.MutableLiveData
içe aktarın.
private val _selectedProperty = MutableLiveData<MarsProperty>()
val selectedProperty: LiveData<MarsProperty>
get() = _selectedProperty
init {}
bloku oluşturun ve oluşturucudan alınanMarsProperty
nesnesiyle seçili Mars mülkünün değerini ayarlayın.
init {
_selectedProperty.value = marsProperty
}
res/layout/fragment_detail.xml
uygulamasını açın ve tasarım görünümünde inceleyin.
Bu, ayrıntı parçasının düzen dosyasıdır. Büyük fotoğraf için birImageView
, tesis türü (kiralama veya satış) için birTextView
ve fiyat için birTextView
içerir. Kısıtlama düzeninin birScrollView
ile sarmalandığına dikkat edin. Bu nedenle, görünüm ekran için çok büyük olduğunda (örneğin, kullanıcı yatay modda görüntülediğinde) otomatik olarak kaydırılır.- Düzen için Metin sekmesine gidin. Düzenin üst kısmında,
<ScrollView>
öğesinin hemen önüne, ayrıntı görünümü modelini düzenle ilişkilendirmek için bir<data>
öğesi ekleyin.
<data>
<variable
name="viewModel"
type="com.example.android.marsrealestate.detail.DetailViewModel" />
</data>
app:imageUrl
özelliğiniImageView
öğesine ekleyin. Görüntü modelinin seçili mülkündenimgSrcUrl
değerine ayarlayın.
Kaydırma özelliğiyle resim yükleyen bağlayıcı adaptörü de tümapp:imageUrl
özelliklerini izlediği için burada da otomatik olarak kullanılır.
app:imageUrl="@{viewModel.selectedProperty.imgSrcUrl}"
2. Adım: Genel bakış görünümü modelinde gezinmeyi tanımlayın
Kullanıcı, genel bakış modelindeki bir fotoğrafa dokunduğunda, tıklanan öğeyle ilgili ayrıntıların gösterildiği bir parçanın gezinmesini tetiklemelidir.
overview/OverviewViewModel.kt
'yi açın. Bir_navigateToSelectedProperty
MutableLiveData
özelliği ekleyin ve bunu sabit birLiveData
ile gösterin.
BuLiveData
boş değer olarak değiştiğinde gezinme tetiklenir. (Yakında bu değişkeni gözlemleyip gezinmeyi tetiklemek için kodu ekleyeceksiniz.)
private val _navigateToSelectedProperty = MutableLiveData<MarsProperty>()
val navigateToSelectedProperty: LiveData<MarsProperty>
get() = _navigateToSelectedProperty
- Sınıfın sonuna, seçili Mars mülküne _
navigateToSelectedProperty
değerini ayarlayan birdisplayPropertyDetails()
yöntemi ekleyin.
fun displayPropertyDetails(marsProperty: MarsProperty) {
_navigateToSelectedProperty.value = marsProperty
}
_navigateToSelectedProperty
değerini geçersiz kılan birdisplayPropertyDetailsComplete()
yöntemi ekleyin. Bunu, gezinme durumunu tamamlamak için işaretlemeniz ve kullanıcı ayrıntı görünümünden çıktığında gezinmenin tekrar tetiklenmesini sağlamanız gerekir.
fun displayPropertyDetailsComplete() {
_navigateToSelectedProperty.value = null
}
3. Adım: Tıklama dinleyicileri, ızgara adaptöründe ve parçada ayarlayın
overview/PhotoGridAdapter.kt
'yi açın. Sınıfın sonunda,marsProperty
parametresiyle lambda alan özel birOnClickListener
sınıfı oluşturun. Sınıfın içinde, lambda parametresine ayarlanmış bironClick()
işlevi tanımlayın.
class OnClickListener(val clickListener: (marsProperty:MarsProperty) -> Unit) {
fun onClick(marsProperty:MarsProperty) = clickListener(marsProperty)
}
PhotoGridAdapter
öğesinin sınıf tanımına ilerleyin ve oluşturucuya gizli birOnClickListener
özelliği ekleyin.
class PhotoGridAdapter( private val onClickListener: OnClickListener ) :
ListAdapter<MarsProperty,
PhotoGridAdapter.MarsPropertyViewHolder>(DiffCallback) {
onBindviewHolder()
yönteminde ızgara öğesineonClickListener
ekleyerek bir fotoğrafı tıklanabilir hale getirin.getItem() and bind()
çağrısı arasında tıklama işleyiciyi tanımlayın.
override fun onBindViewHolder(holder: MarsPropertyViewHolder, position: Int) {
val marsProperty = getItem(position)
holder.itemView.setOnClickListener {
onClickListener.onClick(marsProperty)
}
holder.bind(marsProperty)
}
overview/OverviewFragment.kt
'yi açın.onCreateView()
yönteminde,binding.photosGrid.adapter
özelliğini başlatan satırı aşağıda gösterilen satırla değiştirin.
Bu kod,PhotoGridAdapter.onClickListener
nesnesiniPhotoGridAdapter
oluşturucuya ekler ve iletilenMarsProperty
nesnesiyleviewModel.displayPropertyDetails()
öğesini çağırır. Bu işlem, gezinme için görünüm modelindekiLiveData
öğesini tetikler.
binding.photosGrid.adapter = PhotoGridAdapter(PhotoGridAdapter.OnClickListener {
viewModel.displayPropertyDetails(it)
})
4. Adım: Gezinme grafiğini değiştirin ve MarsProperty'i ayrıştırılabilir hale getirin
Kullanıcı genel bakış tablosundaki bir fotoğrafa dokunduğunda, uygulama ayrıntı parçasına gidip seçili Mars mülkünün ayrıntılarını iletmelidir. Böylece, ayrıntı görünümü söz konusu bilgileri görüntüleyebilir.
Şu anda, dokunma işlemini gerçekleştirmek için PhotoGridAdapter
tıklama dinleyiciniz ve görüntüleme modelinde gezinmeyi tetiklemenin bir yolu vardır. Ancak henüz ayrıntı parçasına iletilmiş bir MarsProperty
nesneniz yok. Bunun için gezinme bileşenindeki Güvenli Argıları kullanırsınız.
res/navigation/nav_graph.xml
'yi açın. Gezinme grafiğine ait XML kodunu görmek için Metin sekmesini tıklayın.- Ayrıntı parçası için
<fragment>
öğesinin içine aşağıda gösterilen<argument>
öğesini ekleyin.selectedProperty
adlı bu bağımsız değişkenMarsProperty
türündedir.
<argument
android:name="selectedProperty"
app:argType="com.example.android.marsrealestate.network.MarsProperty"
/>
- Uygulamayı derleyin. Gezinme özelliği,
MarsProperty
ayrıştırılabileceği için size bir hata veriyor.Parcelable
arayüzü, nesnelerin serileştirilebilmesini sağlar. Böylece nesneler, parçalar veya etkinlikler arasında iletilebilir. Bu durumda,MarsProperty
nesnesinin içindeki verilerin Güvenli Kayışlar aracılığıyla ayrıntı parçasına iletilmesi içinMarsProperty
öğesininParcelable
arayüzünü uygulaması gerekir. Ancak, Kotlin bu arayüzün uygulanması için kolay bir kısayol sunuyor. network/MarsProperty.kt
'yi açın. Sınıf tanımına@Parcelize
ek açıklamasını ekleyin.
İstendiğindekotlinx.android.parcel.Parcelize
öğesini içe aktarın.@Parcelize
ek açıklaması, bu sınıf içinParcelable
arayüzünde yöntemleri otomatik olarak uygulamak üzere Kotlin Android uzantılarını kullanıyor. Bu durumda herhangi bir şey yapmanız gerekmez.
@Parcelize
data class MarsProperty (
Parcelable
öğesinin kapsamını genişletmek içinMarsProperty
sınıf tanımını değiştirin.
İstendiğindeandroid.os.Parcelable
içe aktarın.MarsProperty
sınıf tanımı artık şu şekilde görünüyor:
@Parcelize
data class MarsProperty (
val id: String,
@Json(name = "img_src") val imgSrcUrl: String,
val type: String,
val price: Double) : Parcelable {
5. Adım: Parçaları bağlayın
Hâlâ gezinmiyorsunuz. Gerçek gezinme, parçalarda gerçekleşir. Bu adımda, genel bakış ve ayrıntı parçaları arasında gezinmeyi uygulamak için son bitleri eklersiniz.
overview/OverviewFragment.kt
'yi açın.onCreateView()
içinde, fotoğraf ızgara bağdaştırıcısını başlatan çizgilerin altına, genel bakış görünümü modelindennavigatedToSelectedProperty
gözlemlemek için aşağıda gösterilen satırları ekleyin.
İstendiğindeandroidx.lifecycle.Observer
içe aktarın veandroidx.navigation.fragment.findNavController
içe aktarın.
Gözlemci, lambdadakiit
adlıMarsProperty
öğesinin boş olup olmadığını test eder ve böyle bir durumda gezinme denetleyicisinifindNavController()
içeren parçadan alır.displayPropertyDetailsComplete()
modelinde, görünüm modelininLiveData
değerini boş duruma sıfırlamasını söylemek için çağrı yapın. Böylece, uygulamaOverviewFragment
öğesine geri döndüğünde yanlışlıkla navigasyonu tetiklemez.
viewModel.navigateToSelectedProperty.observe(this, Observer {
if ( null != it ) {
this.findNavController().navigate(
OverviewFragmentDirections.actionShowDetail(it))
viewModel.displayPropertyDetailsComplete()
}
})
detail/DetailFragment.kt
'yi açın. Bu satırı,onCreateView()
yöntemindesetLifecycleOwner()
çağrısının hemen altına ekleyin. Bu satır, seçiliMarsProperty
nesnesini Güvenli bağımsız değişkenlerden alıyor.
Kotlin's boş olmayan onaylama operatörü (!!
) kullanıldığına dikkat edin.selectedProperty
yoksa ürkütücü bir durum oluştu ve kodun boş işaretçiye ulaşmasını istersiniz. (Üretim kodunda bu hatayı bir şekilde ele almanız gerekir.)
val marsProperty = DetailFragmentArgs.fromBundle(arguments!!).selectedProperty
- Yeni
DetailViewModelFactory
alabilmek için bu satırı ekleyin.DetailViewModel
öğesinin bir örneğini almak içinDetailViewModelFactory
makrosunu kullanacaksınız. Başlangıç uygulaması,DetailViewModelFactory
uygulamasını içerdiğinden, burada tek yapmanız gereken uygulamayı başlatmaktır.
val viewModelFactory = DetailViewModelFactory(marsProperty, application)
- Son olarak, bu satırı fabrikadan
DetailViewModel
almak ve tüm parçaları bağlamak için ekleyin.
binding.viewModel = ViewModelProviders.of(
this, viewModelFactory).get(DetailViewModel::class.java)
- Uygulamayı oluşturun ve çalıştırın ve herhangi bir Mars mülkü fotoğrafına dokunun. Söz konusu mülkün ayrıntıları için ayrıntı parçası görünür. Genel bakış sayfasına dönmek için Geri düğmesine dokunun ve ayrıntı ekranının hâlâ biraz seyrek olduğunu fark edin. Bir sonraki görevde özellik verilerini ayrıntılar sayfasına eklemeyi tamamlarsınız.
Şu anda ayrıntılar sayfasında yalnızca alışkın olduğunuz Mars fotoğrafı genel bakış sayfasında gösterilir. Ayrıca MarsProperty
sınıfının bir tesis türü (kiralama veya satın alma) ve tesis fiyatı vardır. Ayrıntılar ekranında her iki değer de bulunmalıdır. Kiralık mülkler, fiyatın aylık değer olduğunu gösteriyorsa faydalı olur. Bu öğelerin her ikisini de uygulamak için görünüm modelinde LiveData
dönüşümlerini kullanırsınız.
res/values/strings.xml
'yi açın. Başlangıç kodu, ayrıntılı görünüm için dizeler oluşturmanıza yardımcı olacak, aşağıda gösterilen dize kaynaklarını içerir. Fiyat için mülk türüne bağlı olarakdisplay_price_monthly_rental
veyadisplay_price
kaynağını kullanırsınız.
<string name="type_rent">Rent</string>
<string name="type_sale">Sale</string>
<string name="display_type">For %s</string>
<string name="display_price_monthly_rental">$%,.0f/month</string>
<string name="display_price">$%,.0f</string>
detail/DetailViewModel.kt
'yi açın. Sınıfın en altına, aşağıda gösterilen kodu ekleyin.
İstenirseandroidx.lifecycle.Transformations
içe aktarın.
Bu dönüştürme işleminde, ilk görevdeki aynı test kullanılarak, seçilen mülkün kiralık olup olmadığı test edilir. Mülk bir kiralıkysa dönüşüm, Kotlinwhen {}
anahtarı bulunan kaynaklardan uygun dizeyi seçer. Bu dizelerin her ikisinin de sonunda bir sayı olması gerekir, dolayısıylaproperty.price
öğesini daha sonra birleştirirsiniz.
val displayPropertyPrice = Transformations.map(selectedProperty) {
app.applicationContext.getString(
when (it.isRental) {
true -> R.string.display_price_monthly_rental
false -> R.string.display_price
}, it.price)
}
- Projedeki dize kaynaklarına erişmek için, oluşturulan
R
sınıfını içe aktarın.
import com.example.android.marsrealestate.R
displayPropertyPrice
dönüştürme işleminden sonra aşağıda gösterilen kodu ekleyin. Bu dönüştürme işleminde, mülk türünün kiralama olup olmadığına bağlı olarak birden fazla dize kaynağı birleştirilir.
val displayPropertyType = Transformations.map(selectedProperty) {
app.applicationContext.getString(R.string.display_type,
app.applicationContext.getString(
when (it.isRental) {
true -> R.string.type_rent
false -> R.string.type_sale
}))
}
res/layout/fragment_detail.xml
'yi açın. Yalnızca bir adım daha var ve yeni dizeleri (LiveData
dönüşümleriyle oluşturduğunuz) ayrıntı görünümüne bağlamak gerekir. Bunun için tesis türü metin için metin alanının değeriniviewModel.displayPropertyType
, fiyat değeri metninin metin alanınıviewModel.displayPropertyPrice
olarak ayarlarsınız.
<TextView
android:id="@+id/property_type_text"
...
android:text="@{viewModel.displayPropertyType}"
...
tools:text="To Rent" />
<TextView
android:id="@+id/price_value_text"
...
android:text="@{viewModel.displayPropertyPrice}"
...
tools:text="$100,000" />
- Uygulamayı oluşturun ve çalıştırın. Tüm mülk verileri artık ayrıntılar sayfasında düzgün bir şekilde biçimlendirilmiş olarak görünür.
Android Studio projesi: MarsRealEstateFinal
İfadeleri bağlama
- Kısıtlanmış verilerdeki matematiksel veya koşullu testler gibi basit programatik işlemleri gerçekleştirmek için XML düzen dosyalarında bağlayıcı ifadeleri kullanın.
- Düzen dosyanızdaki sınıflara referans vermek için
<data>
etiketinin içindeki<import>
etiketini kullanın.
Web hizmeti sorgu seçenekleri
- Web hizmetlerine yapılan istekler isteğe bağlı parametreleri içerebilir.
- İstekte sorgu parametrelerini belirtmek için Retrofit'teki
@Query
ek açıklamasını kullanın.
Udacity kursu:
Android geliştirici dokümanları:
- ViewModel'e Genel Bakış
- LiveData'ya Genel Bakış
- Bağlama adaptörleri
- Düzenler ve bağlama ifadeleri
- Gezinme
- Gezinme bileşenini kullanmaya başlama
- Hedefler arasında veri iletme (Güvenli Kayışlar'ı da açıklar)
Transformations
sınıfıViewModelProvider
sınıfıViewModelProvider.Factory
sınıfı
Diğer:
Bu bölümde, bir eğitmen tarafından sunulan kurs kapsamında bu codelab üzerinden çalışan öğrenciler için olası ev ödevi ödevleri listelenmektedir. Öğretmenin şunları yapması gerekir:
- Gerekirse ev ödevini atayın.
- Öğrencilere ev ödevlerinin nasıl gönderileceğini bildirin.
- Ev ödevlerine not verin.
Öğretmenler bu önerileri istedikleri kadar kullanabilir veya uygun görebilir ve uygun olan diğer ev ödevlerini atayabilirler.
Bu codelab'de kendiniz çalışıyorsanız, bilginizi test etmek için bu ödevlerden yararlanabilirsiniz.
Bu soruları yanıtlayın
1. Soru
Bir XML düzeni dosyasındaki <import>
etiketi ne işe yarar?
▢ ile bir düzen dosyası eklemek.
▢ Kotlin kodunu düzen dosyasının içine yerleştirin.
▢ Verilere bağlı mülklere erişim sağlar.
▢ Bağlayıcı ifadeler kullanarak sınıflara ve sınıf üyelerine referans vermenizi sağlar.
2. Soru
Retrofit'te REST web hizmeti çağrısına nasıl sorgu seçeneği eklenir?
▢ Sorgu URL'sinin sonuna ekleyin.
▢ İsteği yapan işleve sorgu için bir parametre ekleyip @Query
ile bu parametreye not ekleyin.
▢ İstek oluşturmak için Query
sınıfını kullanın.
▢ Retrofit oluşturucuda addQuery()
yöntemini kullanın.
Sonraki derse başlayın:
Bu kurstaki diğer codelab'lerin bağlantılarına ulaşmak için Android Kotlin Fundamentals codelabs açılış sayfasına göz atın.