Bu codelab, Android Kotlin Hakkında Temel Bilgiler kursunun bir parçasıdır. Bu kurstan en iyi şekilde yararlanmak için codelab'leri sırayla tamamlamanızı öneririz. Kursla ilgili tüm codelab'ler Android Kotlin Hakkında Temel Bilgiler codelab'leri açılış sayfasında listelenir.
Giriş
Bu dersin önceki codelab'lerinde, Mars'taki gayrimenkullerle ilgili verileri bir web hizmetinden nasıl alacağınızı ve bu verilerdeki resimleri yükleyip görüntülemek için ızgara düzenine sahip bir RecyclerView oluşturmayı öğrendiniz. Bu codelab'de, Mars mülklerini kiralık veya satılık olup olmamasına göre filtreleme özelliğini uygulayarak MarsRealEstate uygulamasını tamamlayacaksınız. Ayrıca, kullanıcı genel bakışta bir tesis fotoğrafına dokunduğunda tesisle ilgili ayrıntıların yer aldığı bir ayrıntı görünümü görmesi için ayrıntı görünümü de oluşturursunuz.
Bilmeniz gerekenler
- Parçacık oluşturma ve kullanma
- Parçalar arasında gezinme ve parçalar arasında veri aktarmak için Safe Args'ı (bir Gradle eklentisi) kullanma.
- Görünüm modelleri, görünüm modeli fabrikaları, dönüşümler ve
LiveDatadahil olmak üzere mimari bileşenleri kullanma - Retrofit ve Moshi kitaplıklarını kullanarak REST web hizmetinden JSON kodlu verileri alma ve bu verileri Kotlin nesnelerine ayrıştırma.
Neler öğreneceksiniz?
- Düzen dosyalarınızda karmaşık bağlama ifadelerini kullanma
- Sorgu seçenekleriyle bir web hizmetine Retrofit istekleri gönderme
Yapacaklarınız
- Satılık Mars mülklerini (kiralık olanların aksine) dolar işareti simgesiyle işaretlemek için MarsRealEstate uygulamasını değiştirin.
- Genel bakış sayfasındaki seçenekler menüsünü kullanarak Mars özelliklerini türe göre filtreleyen bir web hizmeti isteği oluşturun.
- Bir Mars mülkü için ayrıntı parçası oluşturun, bu parçayı gezinme içeren genel bakış ızgarasına bağlayın ve mülk verilerini bu parçaya aktarın.
Bu codelab'de (ve ilgili codelab'lerde) MarsRealEstate adlı bir uygulamayla çalışacaksınız. Bu uygulama, Mars'ta satılık mülkleri gösterir. Bu uygulama, fiyat ve mülkün satılık veya kiralık olup olmadığı gibi ayrıntılar da dahil olmak üzere mülk verilerini almak ve görüntülemek için bir internet sunucusuna bağlanır. Her bir tesisi temsil eden görüntüler, NASA'nın Mars keşif araçları tarafından çekilen gerçek Mars fotoğraflarıdır. Önceki codelab'lerde, tüm tesis fotoğrafları için ızgara düzenine sahip bir RecyclerView oluşturmuştunuz:

Uygulamanın bu sürümünde, mülkün türüyle (kiralık veya satılık) çalışır ve satılık mülkleri işaretlemek için ızgara düzenine bir simge eklersiniz:

Uygulamanın seçenek menüsünü, ızgarayı yalnızca kiralık veya satılık mülkleri gösterecek şekilde filtrelemek için değiştirirsiniz:

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:

Şimdiye kadar Mars mülk verilerinin yalnızca mülk resminin URL'sini kullandınız. Ancak MarsProperty sınıfında tanımladığınız mülk verileri de kimlik, fiyat ve tür (kiralık veya satılık) içerir. Hatırlatmak için web hizmetinden aldığınız JSON verilerinin bir snippet'ini aşağıda bulabilirsiniz:
{
"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, genel bakış sayfasındaki satılık mülklere dolar işareti resmi eklemek için Mars mülk türüyle çalışmaya başlayacaksınız.
1. adım: MarsProperty'yi 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 gelen ham JSON yanıtını tek tek MarsProperty veri nesnelerine ayrıştırmak için Moshi kitaplığını kullanmıştınız.
Bu adımda, bir mülkün kiralık olup olmadığını (yani türün "rent" veya "buy" dizesi olup olmadığını) belirtmek için MarsProperty sınıfına bazı mantıklar eklersiniz. Bu mantığı birden fazla yerde kullanacağınız için mantığı burada, veri sınıfında bulundurmak, kopyalamaktan daha iyidir.
- Son codelab'deki MarsRealEstate uygulamasını açın. (Uygulama yüklü değilse MarsRealEstateGrid'i indirebilirsiniz.)
network/MarsProperty.ktadlı kişiyi aç.MarsPropertysınıf tanımına bir gövde ekleyin veisRentaliçin özel bir alıcı ekleyin. Bu alıcı, nesne"rent"türündeysetruedeğerini döndürür.
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
Şimdi, yalnızca satılık olan tesis resimlerinde dolar işareti çizilebilir öğesini göstermek için resim ızgarasının öğe düzenini güncelleyin:

Veri bağlama ifadeleriyle bu testi tamamen ızgara öğelerinin XML düzeninde yapabilirsiniz.
res/layout/grid_view_item.xmladlı kişiyi aç. Bu,RecyclerViewiçin ızgara düzenindeki her bir hücrenin düzen dosyasıdır. Şu anda dosya yalnızca mülk resmi için<ImageView>öğesini içeriyor.<data>öğesinin içineViewsınıfı için bir<import>öğesi ekleyin. Bir sınıfın bileşenlerini bir düzen dosyasındaki veri bağlama ifadesinde kullanmak istediğinizde içe aktarmaları kullanırsınız. Bu durumdaView.GONEveView.VISIBLEsabitlerini kullanacağınız içinViewsınıfına erişmeniz gerekir.
<import type="android.view.View"/>- Dolar işaretiyle çizilebilen öğenin mülk resminin üzerine yerleştirilmesine izin vermek için tüm resim görünümünü
FrameLayoutile çevreleyin.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="170dp">
<ImageView
android:id="@+id/mars_image"
...
</FrameLayout>ImageViewiçin yeni üst öğeFrameLayout'ü doldurmak üzereandroid:layout_heightözelliğinimatch_parentolarak değiştirin.
android:layout_height="match_parent"FrameLayoutiçinde, ilk<ImageView>öğesinin hemen altına ikinci bir<ImageView>öğesi ekleyin. Aşağıda gösterilen tanımı kullanın. Bu resim, ızgara öğesinin sağ alt köşesinde, Mars resminin üzerinde görünür ve dolar işareti simgesi içinres/drawable/ic_for_sale_outline.xmliçinde tanımlanan çizilebilir öğeyi 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_typeresim görünümüne ekleyin. Mülk türünü test etmek için 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şkenlerin kullanıldığı düzenlerde bağlama ifadelerini görmüş olabilirsiniz. Bağlama ifadeleri son derece güçlüdür ve testler ile matematiksel hesaplamalar gibi işlemleri tamamen XML düzeninizde yapmanıza olanak tanır. Bu durumda, bir testi (Bu nesne kiralık mı?) gerçekleştirmek için üçlü operatörü (?:) kullanırsınız. Doğru için bir sonuç (dolar işareti simgesini View.GONE ile gizleyin), yanlış için ise başka bir sonuç (bu simgeyi View.VISIBLE ile gösterin) sağlarsınız.
Yeni tamamlanmış grid_view_item.xml dosyası aşağıda gösterilmektedir:
<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ülklerin dolar işareti simgesine sahip olduğunu unutmayın.

Uygulamanız şu anda genel bakış ızgarasında tüm Mars mülklerini gösteriyor. Bir kullanıcı Mars'ta kiralık mülk arıyorsa mevcut mülklerden hangilerinin satılık olduğunu gösteren simgeler faydalı olur ancak sayfada kaydırılması gereken çok sayıda mülk vardır. Bu görevde, genel bakış parçasına bir seçenekler menüsü ekleyerek kullanıcının yalnızca kiralık yerleri, yalnızca satılık yerleri veya tümünü göstermesini sağlayacaksınız.

Bu görevi yerine getirmenin bir yolu, genel bakış tablosundaki her MarsProperty için türü test etmek ve yalnızca eşleşen özellikleri göstermektir. Ancak gerçek Mars web hizmetinde, yalnızca rent türündeki veya buy türündeki özellikleri almanızı sağlayan bir sorgu parametresi ya da seçenek (filter olarak adlandırılır) vardır. Bu filtre sorgusunu, tarayıcıda realestate web hizmeti URL'siyle birlikte şu şekilde kullanabilirsiniz:
https://android-kotlin-fun-mars-server.appspot.com/realestate?filter=buyBu 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, bu sorgu seçeneğini kullanarak tüm Mars mülk verilerini yeniden indirmek için seçenekler menüsünü bağlarsınız. Web hizmetinden aldığınız yanıt yalnızca ilgilendiğiniz özellikleri içerdiğinden, genel bakış ızgarası için görünüm görüntüleme mantığını hiç 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ı tekrar ziyaret etmeniz gerekir. Filtreleme API'si sağlamak için sınıfı değiştirirsiniz.
network/MarsApiService.ktadlı kişiyi aç. İçe aktarma işlemlerinin hemen altında, web hizmetinin beklediği sorgu değerleriyle eşleşen sabitleri tanımlamak içinenumadlı birMarsApiFilteroluşturun.
enum class MarsApiFilter(val value: String) {
SHOW_RENT("rent"),
SHOW_BUY("buy"),
SHOW_ALL("all") }- Filtre sorgusu için dize girişi alacak şekilde
getProperties()yöntemini değiştirin ve bu girişi aşağıda gösterildiği gibi@Query("filter")ile açıklama ekleyin.
İstendiğinderetrofit2.http.Queryiçe aktarın.
@Queryek açıklaması,getProperties()yöntemine (ve dolayısıyla Retrofit'e) web hizmeti isteğini filtre seçeneğiyle yapmasını söyler.getProperties()her çağrıldığında istek URL'si, web hizmetini bu sorguyla eşleşen sonuçlarla yanıt vermeye yönlendiren?filter=typebölümünü içerir.
fun getProperties(@Query("filter") type: String): 2. adım: Genel bakış görünümü modelini güncelleyin
OverviewViewModel içinde getMarsRealEstateProperties() yönteminde MarsApiService'dan veri isteğinde bulunursunuz. Şimdi bu isteği filtre bağımsız değişkenini alacak şekilde güncellemeniz gerekiyor.
overview/OverviewViewModel.ktadlı kişiyi aç. Önceki adımda yaptığınız değişiklikler nedeniyle Android Studio'da hatalar görürsünüz.MarsApiFilter(olası filtre değerlerinin numaralandırılmış türü) öğesinigetMarsRealEstateProperties()çağrısına parametre olarak ekleyin. İstendiğinde
İçe aktar'ıcom.example.android.marsrealestate.network.MarsApiFiltertıklayın.
private fun getMarsRealEstateProperties(filter: MarsApiFilter) {- Bu filtre sorgusunu dize olarak iletmek için Retrofit hizmetindeki
getProperties()çağrısını değiştirin.
var getPropertiesDeferred = MarsApi.retrofitService.getProperties(filter.value)- Uygulama ilk yüklendiğinde tüm özellikleri göstermek için
init {}bloğundaMarsApiFilter.SHOW_ALLöğesinigetMarsRealEstateProperties()için bağımsız değişken olarak iletin.
init {
getMarsRealEstateProperties(MarsApiFilter.SHOW_ALL)
}- Sınıfın sonuna,
updateFilter()bağımsız değişkenini alan vegetMarsRealEstateProperties()işlevini bu bağımsız değişkenle çağıran birMarsApiFilteryö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ının bir menü seçeneğini belirlediğinde görünüm modelinde updateFilter() işlevini çağırmak için taşma menüsünü parçaya bağlamaktır.
res/menu/overflow_menu.xmladlı kişiyi aç. MarsRealEstate uygulamasında, mevcut bir taşma menüsü vardır. Bu menüde üç seçenek sunulur: tüm mülkleri gösterme, yalnızca kiralık mülkleri gösterme ve yalnızca 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.ktadlı kişiyi aç. Dersin sonunda, menü öğesi seçimlerini işlemek içinonOptionsItemSelected()yöntemini uygulayın.
override fun onOptionsItemSelected(item: MenuItem): Boolean {
} onOptionsItemSelected()içinde, görünüm modelindeupdateFilter()yöntemini uygun filtreyle çağırın. Seçenekler arasında geçiş yapmak için Kotlinwhen {}bloğunu kullanın. Varsayılan filtre değeri içinMarsApiFilter.SHOW_ALLdeğerini kullanın. Menü öğesini işlediğiniz içintruedeğerini döndürün. İstendiğindeMarsApiFilter(com.example.android.marsrealestate.network.MarsApiFilter) dosyasını içe aktarın. TamonOptionsItemSelected()yöntemi aşağıda gösterilmektedir.
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ürlerini içeren ilk genel bakış ızgarasını başlatır ve satılık mülkler dolar simgesiyle işaretlenir.
- Seçenekler menüsünden Kirala'yı seçin. Mülkler yeniden yüklenir ve hiçbiri dolar simgesiyle görünmez. (Yalnızca kiralık mülkler gösterilir.) Yalnızca filtrelenmiş mülkleri göstermek için ekranın yenilenmesi birkaç dakika sürebilir.
- Seçenekler menüsünden Satın al'ı seçin. Mülkler yeniden yüklenir ve tümü dolar simgesiyle görünür. (Yalnızca satılık mülkler gösterilir.)
Artık Mars tesislerinin simgelerini içeren kaydırılabilir bir ızgaranız var ancak daha fazla ayrıntı edinme zamanı geldi. Bu görevde, belirli bir mülkün ayrıntılarını göstermek için ayrıntı parçası ekleyeceksiniz. Ayrıntı parçası daha büyük bir resim, fiyat ve mülk türünü (kiralık veya satılık) gösterir.

Bu parça, kullanıcı genel bakış ızgarasındaki bir resme dokunduğunda başlatılır. Bunu yapmak için onClick öğelerine RecyclerView dinleyici eklemeniz ve ardından yeni parçaya gitmeniz gerekir. Bu derslerde yaptığınız gibi, ViewModel içinde LiveData değişikliği tetikleyerek gezinirsiniz. Ayrıca, seçilen MarsProperty bilgilerini genel bakış parçasından ayrıntı parçasına iletmek için Navigation bileşeninin Safe 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 sürece benzer şekilde, artık ayrıntı parçası için görünüm modeli ve düzen dosyalarını uygulamanız gerekiyor.
detail/DetailViewModel.ktadlı kişiyi aç. Ağla ilgili Kotlin dosyalarınetworkklasöründe, genel bakış dosyaları iseoverviewklasöründe yer alır. Benzer şekilde,detailklasöründe de ayrıntı görünümüyle ilişkili dosyalar bulunur.DetailViewModelsınıfının (şu anda boş) oluşturucuda parametre olarakmarsPropertyaldığını unutmayın.
class DetailViewModel( marsProperty: MarsProperty,
app: Application) : AndroidViewModel(app) {
}- Sınıf tanımının içinde, seçilen Mars mülkü için
LiveDataekleyerek bu bilgileri ayrıntı görünümünde gösterin.MarsPropertyöğesini tutacak birMutableLiveDataoluşturma ve ardından değişmez bir genelLiveDataözelliği kullanıma sunma şeklindeki normal kalıbı izleyin. İstendiğinde
içe aktarınandroidx.lifecycle.LiveDataveandroidx.lifecycle.MutableLiveData.
private val _selectedProperty = MutableLiveData<MarsProperty>()
val selectedProperty: LiveData<MarsProperty>
get() = _selectedProperty- Bir
init {}bloğu oluşturun ve oluşturucudakiMarsPropertynesnesiyle seçilen Mars mülkünün değerini ayarlayın.
init {
_selectedProperty.value = marsProperty
}res/layout/fragment_detail.xmldosyasını açıp tasarım görünümünde inceleyin.
Bu, ayrıntı parçası için düzen dosyasıdır. Büyük fotoğraf içinImageView, tesis türü (kiralık veya satılık) içinTextViewve fiyat içinTextViewiçerir. Kısıtlama düzenininScrollViewile sarmalandığını unutmayın. Bu nedenle, görünüm ekrana sığmayacak kadar büyüdüğünde (örneğin, kullanıcı görünümü yatay modda görüntülediğinde) otomatik olarak kaydırılır.- Düzen için Metin sekmesine gidin. Düzenin en üstünde,
<ScrollView>öğesinden hemen önce, 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ünüm modelinin seçili özelliğindenimgSrcUrlolarak ayarlayın.
Glide kullanarak bir resmi yükleyen bağlama bağdaştırıcısı, 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ış modelinde bir fotoğrafa dokunduğunda, tıklanan öğeyle ilgili ayrıntıları gösteren bir parçaya yönlendirme tetiklenmelidir.
overview/OverviewViewModel.ktadlı kişiyi aç._navigateToSelectedPropertyMutableLiveDataözelliği ekleyin ve bunu değişmez birLiveDataile kullanıma sunun.
BuLiveDatadeğeri null olmayan bir değere değiştiğinde gezinme tetiklenir. (Yakında bu değişkeni gözlemlemek ve gezinmeyi tetiklemek için kodu ekleyeceksiniz.)
private val _navigateToSelectedProperty = MutableLiveData<MarsProperty>()
val navigateToSelectedProperty: LiveData<MarsProperty>
get() = _navigateToSelectedProperty- Sınıfın sonunda, _
navigateToSelectedPropertydeğerini seçilen Mars mülküne ayarlayan birdisplayPropertyDetails()yöntemi ekleyin.
fun displayPropertyDetails(marsProperty: MarsProperty) {
_navigateToSelectedProperty.value = marsProperty
}_navigateToSelectedPropertydeğerini boş yapan birdisplayPropertyDetailsComplete()yöntemi ekleyin. Bu, gezinme durumunu tamamlandı olarak işaretlemek ve kullanıcı ayrıntı görünümünden döndüğünde gezinmenin tekrar tetiklenmesini önlemek için gereklidir.
fun displayPropertyDetailsComplete() {
_navigateToSelectedProperty.value = null
}3. adım: Izgara bağdaştırıcısında ve parçada tıklama dinleyicilerini ayarlayın
overview/PhotoGridAdapter.ktadlı kişiyi aç. Sınıfın sonunda,marsPropertyparametreli bir lambda alan özel birOnClickListenersı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)
}PhotoGridAdaptersınıfının sınıf tanımına gidin ve oluşturucuya özel birOnClickListenerözelliği ekleyin.
class PhotoGridAdapter( private val onClickListener: OnClickListener ) :
ListAdapter<MarsProperty,
PhotoGridAdapter.MarsPropertyViewHolder>(DiffCallback) {onClickListeneryöntemindeonBindviewHolder()öğesineonClickListenerekleyerek fotoğrafı tıklanabilir hale getirin. Tıklama işleyicisinigetItem() and bind()çağrıları arasında 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.ktadlı kişiyi aç.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.onClickListenernesnesiniPhotoGridAdapteroluşturucusuna ekler ve iletilenMarsPropertynesnesiyleviewModel.displayPropertyDetails()işlevini çağırır. Bu işlem, gezinme için görünüm modelindeLiveDataöğesini tetikler.
binding.photosGrid.adapter = PhotoGridAdapter(PhotoGridAdapter.OnClickListener {
viewModel.displayPropertyDetails(it)
})4. adım: Gezinme grafiğini değiştirin ve MarsProperty'yi paketlenebilir hale getirin
Kullanıcı, genel bakış ızgarasında bir fotoğrafa dokunduğunda uygulama, ayrıntı parçasına gitmeli ve seçilen Mars mülkünün ayrıntılarını aktarmalıdır. Böylece ayrıntı görünümünde bu bilgiler gösterilebilir.

Şu anda dokunma işlemini işlemek için PhotoGridAdapter öğesinden bir tıklama işleyiciye ve görünüm modelinden gezinmeyi tetikleme yöntemine sahipsiniz. Ancak henüz ayrıntı parçasına iletilen bir MarsProperty nesneniz yok. Bunun için gezinme bileşenindeki Safe Args'ı kullanırsınız.
res/navigation/nav_graph.xmladlı kişiyi aç. Gezinme grafiğinin XML kodunu görüntülemek 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.selectedPropertyadlı bu bağımsız değişkenin türüMarsProperty'dir.
<argument
android:name="selectedProperty"
app:argType="com.example.android.marsrealestate.network.MarsProperty"
/>- Uygulamayı derleyin.
MarsProperty, parcelable olmadığı için gezinme sırasında hata alırsınız.Parcelablearayüzü, nesnelerin serileştirilmesini sağlar. Böylece nesnelerin verileri parçalar veya etkinlikler arasında aktarılabilir. Bu durumda,MarsPropertynesnesinin içindeki verilerin Safe Args aracılığıyla ayrıntı parçasına aktarılması içinMarsProperty,Parcelablearayüzünü uygulamalıdır. Kotlin, bu arayüzü uygulamak için kolay bir kısayol sunar. network/MarsProperty.ktadlı kişiyi aç. Sınıf tanımına@Parcelizeek açıklamasını ekleyin.
İstendiğindekotlinx.android.parcel.Parcelizeöğesini içe aktarın.@Parcelizeek açıklaması, bu sınıf içinParcelablearayüzündeki yöntemleri otomatik olarak uygulamak üzere Kotlin Android uzantılarını kullanır. Başka bir işlem yapmanız gerekmez.
@Parcelize
data class MarsProperty (MarsPropertysınıf tanımını,Parcelable'ı genişletecek şekilde değiştirin.
İstendiğindeandroid.os.Parcelable'ı içe aktarın.MarsPropertysı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.ktadlı kişiyi aç.onCreateView()içinde, fotoğraf ızgarası bağdaştırıcısını başlatan satırların altına, genel bakış görünümü modelindennavigatedToSelectedPropertyöğesini gözlemlemek için aşağıda gösterilen satırları ekleyin. İstendiğinde
içe aktarınandroidx.lifecycle.Observerveandroidx.navigation.fragment.findNavController.
Gözlemci, lambda'dakiMarsProperty—itdeğerinin null olup olmadığını test eder. Null değilsefindNavController()ile parçadan gezinme denetleyicisini alır. Görünüm modelineLiveDatadeğerini null durumuna sıfırlamasını söylemek içindisplayPropertyDetailsComplete()işlevini çağırın. Böylece uygulamaOverviewFragmentöğesine döndüğünde gezinmeyi yanlışlıkla tekrar tetiklemezsiniz.
viewModel.navigateToSelectedProperty.observe(this, Observer {
if ( null != it ) {
this.findNavController().navigate(
OverviewFragmentDirections.actionShowDetail(it))
viewModel.displayPropertyDetailsComplete()
}
})detail/DetailFragment.ktadlı kişiyi aç. Bu satırı,onCreateView()yöntemindekisetLifecycleOwner()çağrısının hemen altına ekleyin. Bu satır, Safe Args'dan seçilenMarsPropertynesneyi alır.
Kotlin'in null olmayan onaylama operatörünün (!!) kullanıldığına dikkat edin.selectedPropertyyoksa korkunç bir şey olmuştur ve kodun aslında null işaretçi oluşturmasını istersiniz. (Üretim kodunda bu hatayı bir şekilde ele almanız gerekir.)
val marsProperty = DetailFragmentArgs.fromBundle(arguments!!).selectedProperty- Yeni bir
DetailViewModelFactoryalmak için bu satırı ekleyin.DetailViewModelörneğini almak içinDetailViewModelFactorykullanırsınız. Başlangıç uygulamasındaDetailViewModelFactory'nın bir uygulaması bulunur. Bu nedenle, burada yapmanız gereken tek şey onu başlatmaktır.
val viewModelFactory = DetailViewModelFactory(marsProperty, application)- Son olarak, fabrikadan
DetailViewModelalmak ve tüm parçaları bağlamak için bu çizgiyi ekleyin.
binding.viewModel = ViewModelProviders.of(
this, viewModelFactory).get(DetailViewModel::class.java)- Uygulamayı derleyip çalıştırın ve herhangi bir Mars mülkünün fotoğrafına dokunun. Söz konusu mülkün ayrıntıları için ayrıntı parçası gösterilir. Genel bakış sayfasına dönmek için geri düğmesine dokunun. Ayrıntı ekranının hâlâ biraz seyrek olduğunu göreceksiniz. Mülk verilerini bu ayrıntılar sayfasına ekleme işlemini sonraki görevde tamamlarsınız.
Şu anda ayrıntılar sayfasında yalnızca genel bakış sayfasında görmeye alıştığınız Mars fotoğrafı gösteriliyor. MarsProperty sınıfında ayrıca bir mülk türü (kiralama veya satın alma) ve mülk fiyatı bulunur. Ayrıntılar ekranında bu değerlerin her ikisi de yer almalıdır. Kiralık mülklerin, fiyatın aylık değer olduğunu belirtmesi faydalı olur. Bu iki şeyi uygulamak için görünüm modelinde LiveData dönüşümlerini kullanırsınız.
res/values/strings.xmladlı kişiyi aç. Başlangıç kodu, ayrıntı görünümü için dizeler oluşturmanıza yardımcı olmak üzere aşağıda gösterilen dize kaynaklarını içerir. Fiyat için, mülk türüne bağlı olarakdisplay_price_monthly_rentalkaynağını veyadisplay_pricekaynağı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.ktadlı kişiyi aç. Sınıfın en altına aşağıdaki kodu ekleyin. İstenirse
İçe aktar'ıandroidx.lifecycle.Transformationstıklayın.
Bu dönüşüm, ilk görevdeki testle aynı testi kullanarak seçilen mülkün kiralık olup olmadığını test eder. Mülk kiralıksa dönüştürme, Kotlinwhen {}anahtarıyla kaynaklardan uygun dizeyi seçer. Bu dizelerin her ikisinin de sonunda bir sayı olması gerekir. Bu nedenle,property.pricesonrasında birleştirme yaparsınız.
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
Rsınıfını içe aktarın.
import com.example.android.marsrealestate.RdisplayPropertyPricedönüşümünden sonra aşağıda gösterilen kodu ekleyin. Bu dönüşüm, mülk türünün kiralık olup olmamasına bağlı olarak birden fazla dize kaynağını birleştirir.
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.xmladlı kişiyi aç. Yapılacak tek bir işlem kaldı:LiveDatadönüşümleriyle oluşturduğunuz yeni dizeleri ayrıntı görünümüne bağlamak. Bunu yapmak için özellik türü metni için metin alanının değeriniviewModel.displayPropertyType, fiyat değeri metni için metin alanının değerini iseviewModel.displayPropertyPriceolarak 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ı derleyip çalıştırın. Artık tüm mülk verileri, ayrıntılar sayfasında düzgün bir şekilde biçimlendirilmiş olarak görünüyor.

Android Studio projesi: MarsRealEstateFinal
Bağlama ifadeleri
- Bağlı veriler üzerinde matematik veya koşullu testler gibi basit programatik işlemler gerçekleştirmek için XML düzen dosyalarında bağlama ifadelerini kullanın.
- Düzen dosyanızdaki sınıflara referans vermek için
<import>etiketi içindeki<data>etiketini kullanın.
Web hizmeti sorgu seçenekleri
- Web hizmetlerine yapılan istekler isteğe bağlı parametreler içerebilir.
- İstekteki sorgu parametrelerini belirtmek için Retrofit'te
@Queryek açıklamasını kullanın.
Udacity kursu:
Android geliştirici belgeleri:
- 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 geçirme (Güvenli Argümanlar da açıklanır)
TransformationssınıfıViewModelProvidersınıfıViewModelProvider.Factorysınıfı
Diğer:
Bu bölümde, bir eğitmenin yönettiği kurs kapsamında bu codelab'i tamamlayan öğrenciler için olası ödevler listelenmektedir. Eğitmen, aşağıdakileri yapmalıdır:
- Gerekirse ödev atayın.
- Öğrencilere ev ödevi ödevlerini nasıl göndereceklerini bildirin.
- Ödevlere not verin.
Eğitmenler bu önerileri istedikleri kadar kullanabilir ve uygun olduğunu düşündükleri diğer ödevleri verebilirler.
Bu codelab'i kendi başınıza tamamlıyorsanız bilginizi test etmek için bu ödevleri kullanabilirsiniz.
Bu soruları yanıtlayın
1. Soru
XML düzen dosyasındaki <import> etiketi ne işe yarar?
▢ Bir düzen dosyasını diğerine dahil etme.
▢ Kotlin kodunu düzen dosyasına yerleştirin.
▢ Verilere bağlı mülklere erişim izni verin.
▢ Bağlama ifadelerinde sınıflara ve sınıf üyelerine referans vermenizi sağlar.
2. Soru
Retrofit'te bir REST web hizmeti çağrısına nasıl sorgu seçeneği eklersiniz?
▢ Sorguyu istek URL'sinin sonuna ekleyin.
▢ İsteği yapan işleve sorgu için bir parametre ekleyin ve bu parametreyi @Query ile açıklama olarak 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ını Android Kotlin Hakkında Temel Bilgiler codelab'leri açılış sayfasında bulabilirsiniz.