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ş
Oluşturduğunuz Android uygulamalarının neredeyse tamamının bir noktada internete bağlanması gerekir. Bu ve sonraki codelab'lerde, verileri almak ve görüntülemek için bir web hizmetine bağlanan bir uygulama oluşturacaksınız.  Ayrıca, ViewModel, LiveData ve RecyclerView ile ilgili önceki codelab'lerde öğrendiklerinizi temel alacaksınız. 
Bu codelab'de, ağ katmanını oluşturmak için topluluk tarafından geliştirilen kitaplıkları kullanırsınız. Bu, verilerin ve resimlerin getirilmesini büyük ölçüde basitleştirir. Ayrıca uygulamanın, resimleri arka plan iş parçacığında yükleme ve yüklenen resimleri önbelleğe alma gibi bazı Android en iyi uygulamalarına uymasına yardımcı olur. Kodun eşzamansız veya engellemeyen bölümleri (ör. web hizmetleri katmanıyla iletişim kurma) için uygulamayı Kotlin'in eş yordamlarını kullanacak şekilde değiştirirsiniz. İnternet yavaşsa veya kullanılamıyorsa kullanıcının ne olduğunu anlaması için uygulamanın kullanıcı arayüzünü de güncelleyeceksiniz.
Bilmeniz gerekenler
- Parçacık oluşturma ve kullanma
 - Parçalar arasında gezinme ve parçalar arasında veri aktarmak için 
safeArgskullanma ViewModel,ViewModelProvider.Factory,LiveDataveLiveDatadönüşümleri dahil olmak üzere mimari bileşenleri kullanma- Uzun süre çalışan görevler için coroutine'leri kullanma
 
Neler öğreneceksiniz?
- REST web hizmetinin ne olduğu
 - İnternetteki bir REST web hizmetine bağlanmak ve yanıt almak için Retrofit kitaplığını kullanma.
 - JSON yanıtını bir veri nesnesine ayrıştırmak için Moshi kitaplığını kullanma.
 
Yapacaklarınız
- Bir başlangıç uygulamasını, web hizmeti API isteği oluşturacak ve yanıtı işleyecek şekilde değiştirin.
 - Retrofit kitaplığını kullanarak uygulamanız için bir ağ katmanı uygulayın.
 - Moshi kitaplığıyla web hizmetinden gelen JSON yanıtını uygulamanızın canlı verilerine ayrıştırın.
 - Kodu basitleştirmek için Retrofit'in coroutine desteğini kullanın.
 
Bu codelab'de (ve sonraki codelab'lerde) MarsRealEstate adlı bir başlangıç uygulamasıyla ç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 web hizmetine 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.

Bu codelab'de oluşturduğunuz uygulamanın sürümünde çok fazla görsel öğe bulunmaz. Uygulamanın, internete bağlanmak ve bir web hizmeti kullanarak ham mülk verilerini indirmek için ağ katmanı kısmına odaklanılır. Verilerin doğru şekilde alındığından ve ayrıştırıldığından emin olmak için Mars'taki mülk sayısını metin görünümünde yazdırmanız yeterlidir:

.
MarsRealEstate uygulamasının mimarisinde iki ana modül bulunur:
RecyclerViewile oluşturulmuş, küçük resim mülk görsellerinin yer aldığı bir ızgara içeren genel bakış snippet'i.- Her mülkle ilgili bilgileri içeren bir ayrıntı görünümü parçası.
 

Uygulamada her parça için bir ViewModel bulunur. Bu codelab'de ağ hizmeti için bir katman oluşturursunuz ve ViewModel doğrudan bu ağ katmanıyla iletişim kurar.  Bu, önceki codelab'lerde ViewModel, Room veritabanıyla iletişim kurarken yaptığınıza benzer.
Genel bakış ViewModel, Mars'taki emlak bilgileri için ağ çağrısı yapmaktan sorumludur. Ayrıntı ViewModel, ayrıntı parçasında gösterilen tek Mars arazisiyle ilgili ayrıntıları içerir.  Her ViewModel için, veriler değiştiğinde uygulama kullanıcı arayüzünü güncellemek üzere yaşam döngüsüne duyarlı veri bağlama ile LiveData kullanırsınız.  
Gezinme bileşenini hem iki parça arasında gezinmek hem de seçilen özelliği bağımsız değişken olarak iletmek için kullanırsınız.
Bu görevde, MarsRealEstate için başlangıç uygulamasını indirip çalıştıracak ve projenin yapısını tanıyacaksınız.
1. adım: Parçaları ve gezinmeyi keşfedin
- MarsRealEstate başlangıç uygulamasını indirip Android Studio'da açın.
 app/java/MainActivity.ktinceleyin. Uygulama her iki ekran için de parçalar kullandığından etkinliğin tek görevi, etkinliğin düzenini yüklemektir.app/res/layout/activity_main.xmlinceleyin. Etkinlik düzeni, gezinme dosyasında tanımlanan iki parçanın ana makinesidir. Bu düzen,NavHostFragmentöğesini ve ilişkili gezinme denetleyicisininav_graphkaynağıyla başlatır.app/res/navigation/nav_graph.xmladlı kişiyi aç. Burada iki parça arasındaki gezinme ilişkisini görebilirsiniz. Gezinme grafiğiStartDestination,overviewFragmentöğesini işaret eder. Bu nedenle, uygulama başlatıldığında genel bakış parçası oluşturulur.
2. adım: Kotlin kaynak dosyalarını ve veri bağlamayı keşfedin
- Proje bölmesinde app > java'yı genişletin. MarsRealEstate uygulamasının üç paket klasörü olduğunu unutmayın:  
detail,networkveoverview. Bunlar, uygulamanızın üç ana bileşenine (genel bakış ve ayrıntı parçaları ile ağ katmanının kodu) karşılık gelir.
   app/java/overview/OverviewFragment.ktadlı kişiyi aç.OverviewFragment,OverviewViewModel'ı geç başlatır. Bu,OverviewViewModel'ın ilk kez kullanıldığında oluşturulduğu anlamına gelir.onCreateView()yöntemini inceleyin. Bu yöntem, veri bağlama kullanarakfragment_overviewdüzenini genişletir, bağlama yaşam döngüsü sahibini kendisi olarak ayarlar (this) vebindingnesnesindekiviewModeldeğişkenini buna göre ayarlar. Yaşam döngüsü sahibi ayarlandığı için veri bağlamada kullanılan tümLiveData, değişiklikler için otomatik olarak gözlemlenir ve kullanıcı arayüzü buna göre güncellenir.app/java/overview/OverviewViewModeladlı kişiyi aç. Yanıt birLiveDataolduğu ve bağlama değişkeninin yaşam döngüsünü ayarladığımız için bu değişkende yapılan tüm değişiklikler uygulama kullanıcı arayüzünü günceller.initbloğunu inceleyin.ViewModeloluşturulduğundagetMarsRealEstateProperties()yöntemi çağrılır.getMarsRealEstateProperties()yöntemini inceleyin. Bu başlangıç uygulamasında bu yöntem, yer tutucu bir yanıt içerir. Bu codelab'in amacı, internetten aldığınız gerçek verileri kullanarakViewModeliçindeki yanıtıLiveDatagüncellemek.app/res/layout/fragment_overview.xmladlı kişiyi aç. Bu, bu codelab'de çalıştığınız genel bakış parçasının düzenidir ve görünüm modeli için veri bağlamayı içerir.OverviewViewModeldosyasını içe aktarır veViewModeldosyasındaki yanıtıTextViewdosyasına bağlar. Daha sonraki codelab'lerde, metin görünümünüRecyclerViewiçinde bir resim ızgarasıyla değiştireceksiniz.- Uygulamayı derleyip çalıştırın. Bu uygulamanın mevcut sürümünde gördüğünüz tek şey başlangıç yanıtı olan "Set the Mars API Response here!" (Mars API yanıtını buraya ayarlayın) ifadesidir.
 
 
Mars emlak verileri, REST web hizmeti olarak bir web sunucusunda depolanır. REST mimarisini kullanan web hizmetleri, standart web bileşenleri ve protokolleri kullanılarak oluşturulur.
URI'ler aracılığıyla bir web hizmetine standartlaştırılmış bir şekilde istekte bulunursunuz. Tanıdık web URL'si aslında bir URI türüdür ve bu kursta her ikisi de birbirinin yerine kullanılır. Örneğin, bu derse ait uygulamada aşağıdaki sunucudan tüm verileri alırsınız:
https://android-kotlin-fun-mars-server.appspot.com
Tarayıcınıza aşağıdaki URL'yi yazarsanız Mars'taki tüm mevcut gayrimenkullerin listesini görürsünüz.
https://android-kotlin-fun-mars-server.appspot.com/realestate
Bir web hizmetinden gelen yanıt genellikle yapılandırılmış verileri temsil etmek için kullanılan bir değişim biçimi olan JSON olarak biçimlendirilir. JSON hakkında daha fazla bilgiyi sonraki görevde edineceksiniz. Ancak kısa bir açıklama yapmak gerekirse JSON nesnesi, bazen sözlük, karma eşlem veya ilişkisel dizi olarak da adlandırılan bir anahtar/değer çiftleri koleksiyonudur. JSON nesneleri koleksiyonu, JSON dizisidir ve web hizmetinden yanıt olarak aldığınız dizidir.
Bu verilerin uygulamaya aktarılması için uygulamanızın bir ağ bağlantısı oluşturması, bu sunucuyla iletişim kurması, ardından yanıt verilerini alıp uygulamada kullanılabilecek bir biçimde ayrıştırması gerekir. Bu codelab'de, bu bağlantıyı oluşturmak için Retrofit adlı bir REST istemci kitaplığı kullanacaksınız.
1. adım: Retrofit bağımlılıklarını Gradle'a ekleyin
- build.gradle (Module: app) dosyasını açın.
 dependenciesbölümüne Retrofit kitaplıkları için şu satırları ekleyin:
implementation "com.squareup.retrofit2:retrofit:$version_retrofit"
implementation "com.squareup.retrofit2:converter-scalars:$version_retrofit"
Sürüm numaralarının proje Gradle dosyasında ayrı olarak tanımlandığını unutmayın. İlk bağımlılık Retrofit 2 kitaplığına, ikinci bağımlılık ise Retrofit skaler dönüştürücüsüne aittir.  Bu dönüştürücü, Retrofit'in JSON sonucunu String olarak döndürmesini sağlar. İki kitaplık birlikte çalışır.
- Projeyi yeni bağımlılıklarla yeniden oluşturmak için Şimdi Senkronize Et'i tıklayın.
 
2. adım: MarsApiService'i uygulama
Retrofit, web hizmetindeki içeriğe göre uygulama için bir ağ API'si oluşturur. Web hizmetinden verileri getirir ve verilerin kodunu çözmeyi ve bunları yararlı nesneler şeklinde döndürmeyi bilen ayrı bir dönüştürücü kitaplığı üzerinden yönlendirir. Retrofit, XML ve JSON gibi popüler web veri biçimleri için yerleşik destek içerir. Retrofit, istekleri arka plan iş parçacıklarında çalıştırmak gibi kritik ayrıntılar da dahil olmak üzere ağ katmanının büyük bir kısmını sizin için oluşturur.
MarsApiService sınıfı, uygulamanın ağ katmanını tutar. Yani bu, ViewModel öğenizin web hizmetiyle iletişim kurmak için kullanacağı API'dir.  Bu sınıf, Retrofit hizmeti API'sini uygulayacağınız yerdir.  
app/java/network/MarsApiService.ktadlı kişiyi aç. Şu anda dosyada yalnızca bir şey var: web hizmetinin temel URL'si için bir sabit.
private const val BASE_URL = 
   "https://android-kotlin-fun-mars-server.appspot.com"- Bu sabitin hemen altında, Retrofit nesnesi oluşturmak için bir Retrofit oluşturucu kullanın.  İstendiğinde 
retrofit2.Retrofitveretrofit2.converter.scalars.ScalarsConverterFactoryöğelerini içe aktarın. 
private val retrofit = Retrofit.Builder()
   .addConverterFactory(ScalarsConverterFactory.create())
   .baseUrl(BASE_URL)
   .build()
Retrofit'in bir web hizmetleri API'si oluşturmak için en az iki şeye ihtiyacı vardır: web hizmetinin temel URI'si ve bir dönüştürücü fabrikası.  Dönüştürücü, Retrofit'e web hizmetinden geri aldığı verilerle ne yapması gerektiğini söyler.  Bu durumda, Retrofit'in web hizmetinden bir JSON yanıtı getirmesini ve bunu String olarak döndürmesini istersiniz.  Retrofit'te dizeleri ve diğer temel türleri destekleyen bir ScalarsConverter bulunur. Bu nedenle, oluşturucuda addConverterFactory() işlevini ScalarsConverterFactory örneğiyle çağırırsınız.  Son olarak, Retrofit nesnesini oluşturmak için build() işlevini çağırırsınız.
- Retrofit oluşturucuya yapılan çağrının hemen altında, Retrofit'in HTTP isteklerini kullanarak web sunucusuyla nasıl iletişim kuracağını tanımlayan bir arayüz tanımlayın.  İstendiğinde 
retrofit2.http.GETveretrofit2.Callöğelerini içe aktarın. 
interface MarsApiService {
    @GET("realestate")
    fun getProperties():
            Call<String>
}Şu anda amaç, web hizmetinden JSON yanıt dizesini almak ve bunu yapmak için yalnızca bir yönteme ihtiyacınız var: getProperties().  Retrofit'e bu yöntemin ne yapması gerektiğini söylemek için @GET ek açıklamasını kullanın ve bu web hizmeti yönteminin yolunu veya uç noktasını belirtin.  Bu durumda uç nokta realestate olarak adlandırılır. getProperties() yöntemi çağrıldığında Retrofit, uç noktayı realestate temel URL'ye (Retrofit oluşturucusunda tanımladığınız) ekler ve bir Call nesnesi oluşturur. İstek başlatmak için Call nesnesi kullanılır.
MarsApiServicearayüzünün altında, Retrofit hizmetini başlatmak içinMarsApiadlı bir herkese açık nesne tanımlayın.
object MarsApi {
    val retrofitService : MarsApiService by lazy { 
       retrofit.create(MarsApiService::class.java) }
}Retrofit create() yöntemi, MarsApiService arayüzüyle Retrofit hizmetini oluşturur.  Bu çağrı maliyetli olduğundan ve uygulamanın yalnızca bir Retrofit hizmeti örneğine ihtiyacı olduğundan, MarsApi adlı bir genel nesne kullanarak hizmeti uygulamanın geri kalanına sunar ve Retrofit hizmetini orada geç başlatırsınız. Kurulum tamamlandığına göre, uygulamanız MarsApi.retrofitService işlevini her çağırdığında MarsApiService işlevini uygulayan tekil bir Retrofit nesnesi alır.
3. adım: OverviewViewModel'da web hizmetini çağırın
app/java/overview/OverviewViewModel.ktadlı kişiyi aç.getMarsRealEstateProperties()yöntemine gidin.
private fun getMarsRealEstateProperties() {
   _response.value = "Set the Mars API Response here!"
}Bu yöntem, Retrofit hizmetini çağıracağınız ve döndürülen JSON dizesini işleyeceğiniz yerdir. Şu anda yanıt için yalnızca bir yer tutucu dize var.
- Yanıtı "Set the Mars API Response here!" (Mars API yanıtını buraya ayarlayın) olarak ayarlayan yer tutucu satırı silin.
 getMarsRealEstateProperties()içine aşağıda gösterilen kodu ekleyin. İstendiğinderetrofit2.Callbackvecom.example.android.marsrealestate.network.MarsApiöğelerini içe aktarın.MarsApi.retrofitService.getProperties()yöntemi,Callnesnesini döndürür. Ardından, arka plan iş parçacığında ağ isteğini başlatmak için söz konusu nesnedeenqueue()işlevini çağırabilirsiniz.
MarsApi.retrofitService.getProperties().enqueue( 
   object: Callback<String> {
})- Kırmızı renkte altı çizili olan 
objectkelimesini tıklayın. Kod > Uygulama yöntemleri'ni seçin. Listeden hemonResponse()hem deonFailure()simgesini seçin.
Android Studio, her yöntemde yapılacaklar listesiyle birlikte kodu ekler: 
override fun onFailure(call: Call<String>, t: Throwable) {
       TODO("not implemented") 
}
override fun onResponse(call: Call<String>, 
   response: Response<String>) {
       TODO("not implemented") 
}onFailure()içinde, YAPILACAK İŞLER'i silin ve_responsedeğerini aşağıdaki örnekte gösterildiği gibi bir hata mesajı olarak ayarlayın._response, metin görünümünde neyin gösterileceğini belirleyen birLiveDatadizesidir. Her eyaletin_responseLiveData.
onFailure()geri çağırma işlevini güncellemesi gerekir. Bu işlev, web hizmeti yanıtı başarısız olduğunda çağrılır. Bu yanıt için_responsedurumunu,Throwablebağımsız değişkenindeki mesajla birleştirilmiş"Failure: "olarak ayarlayın.
override fun onFailure(call: Call<String>, t: Throwable) {
   _response.value = "Failure: " + t.message
}onResponse()içinde, YAPILACAKLAR'ı silin ve_responseöğesini yanıt gövdesine ayarlayın. İstek başarılı olduğunda ve web hizmeti yanıt döndürdüğündeonResponse()geri çağırma işlevi çağrılır.
override fun onResponse(call: Call<String>, 
   response: Response<String>) {
      _response.value = response.body()
}4. adım: İnternet iznini tanımlayın
- MarsRealEstate uygulamasını derleyip çalıştırın.  Uygulamanın hata vererek hemen kapandığını unutmayın. 
   - Android Studio'da Logcat sekmesini tıklayın ve günlükteki hatayı not edin. Hata, şu gibi bir satırla başlar:
 
Process: com.example.android.marsrealestate, PID: 10646 java.lang.SecurityException: Permission denied (missing INTERNET permission?)
Hata mesajında, uygulamanızda INTERNET izninin eksik olabileceği belirtiliyor. İnternete bağlanmak güvenlik sorunlarına yol açar. Bu nedenle uygulamalar varsayılan olarak internete bağlanmaz. Android'e uygulamanın internete erişmesi gerektiğini açıkça söylemeniz gerekir.
app/manifests/AndroidManifest.xmladlı kişiyi aç. Bu satırı<application>etiketinden hemen önce ekleyin:
<uses-permission android:name="android.permission.INTERNET" />- Uygulamayı tekrar derleyip çalıştırın.  İnternet bağlantınızla ilgili her şey doğru çalışıyorsa Mars Property verilerini içeren JSON metnini görürsünüz.

 - Uygulamayı kapatmak için cihazınızda veya emülatörünüzde Geri düğmesine dokunun.
 - Cihazınızı veya emülatörünüzü uçak moduna alın, ardından uygulamayı Son Kullanılanlar menüsünden yeniden açın ya da Android Studio'dan yeniden başlatın.
 

- Uçak modunu tekrar kapatın.
 
Artık Mars web hizmetinden bir JSON yanıtı alıyorsunuz. Bu, harika bir başlangıç. Ancak gerçekten ihtiyacınız olan şey büyük bir JSON dizesi değil, Kotlin nesneleridir. Moshi adlı bir kitaplık vardır. Bu kitaplık, JSON dizesini Kotlin nesnelerine dönüştüren bir Android JSON ayrıştırıcısıdır. Retrofit, Moshi ile çalışan bir dönüştürücüye sahiptir. Bu nedenle, bu amaçlarınız için harika bir kitaplıktır.
Bu görevde, web hizmetinden gelen JSON yanıtını yararlı Mars Property Kotlin nesnelerine ayrıştırmak için Retrofit ile birlikte Moshi kitaplığını kullanacaksınız. Uygulamayı, işlenmemiş JSON'u göstermek yerine döndürülen Mars Özellikleri sayısını gösterecek şekilde değiştirirsiniz.
1. adım: Moshi kitaplığı bağımlılıklarını ekleyin
- build.gradle (Module: app) dosyasını açın.
 - Bağımlılıklar bölümüne, Moshi bağımlılıklarını eklemek için aşağıda gösterilen kodu ekleyin. Retrofit'te olduğu gibi 
$version_moshi, proje düzeyindeki Gradle dosyasında ayrı olarak tanımlanır. Bu bağımlılıklar, temel Moshi JSON kitaplığı ve Moshi'nin Kotlin desteği için destek ekler. 
implementation "com.squareup.moshi:moshi:$version_moshi"
implementation "com.squareup.moshi:moshi-kotlin:$version_moshi"dependenciesbloğunda Retrofit scalar dönüştürücüsünün satırını bulun:
implementation "com.squareup.retrofit2:converter-scalars:$version_retrofit"- Bu satırı 
converter-moshikullanacak şekilde değiştirin: 
implementation "com.squareup.retrofit2:converter-moshi:$version_retrofit"- Projeyi yeni bağımlılıklarla yeniden oluşturmak için Şimdi Senkronize Et'i tıklayın.
 
2. adım: MarsProperty veri sınıfını uygulayın
Web hizmetinden aldığınız JSON yanıtının örnek girişi şu şekilde görünür:
[{"price":450000,
"id":"424906",
"type":"rent",
"img_src":"http://mars.jpl.nasa.gov/msl-raw-images/msss/01000/mcam/1000ML0044631300305227E03_DXXX.jpg"},
...]Yukarıda gösterilen JSON yanıtı, köşeli parantezlerle belirtilen bir dizidir.  Dizi, süslü parantezlerle çevrili JSON nesneleri içerir.  Her nesne, iki nokta üst üste işaretiyle ayrılmış bir ad-değer çifti grubu içerir. Adlar tırnak içine alınır. Değerler sayı veya dize olabilir. Dizeler de tırnak içine alınır. Örneğin, bu mülk için price değeri 450.000 TL, img_src ise resim dosyasının sunucudaki konumu olan bir URL'dir. 
Yukarıdaki örnekte, her Mars özelliği girişinin şu JSON anahtar ve değer çiftlerine sahip olduğuna dikkat edin:
price: Mars mülkünün fiyatı (sayı olarak).id: Mülkün kimliği (dize olarak).type:"rent"veya"buy".img_src: Resmin URL'si dize olarak.
Moshi, bu JSON verilerini ayrıştırır ve Kotlin nesnelerine dönüştürür. Bunun için ayrıştırılan sonuçları depolamak üzere bir Kotlin veri sınıfına sahip olması gerekir. Bu nedenle, bir sonraki adım bu sınıfı oluşturmaktır.
app/java/network/MarsProperty.ktadlı kişiyi aç.- Mevcut 
MarsPropertysınıf tanımını aşağıdaki kodla değiştirin: 
data class MarsProperty(
   val id: String, val img_src: String,
   val type: String,
   val price: Double
)MarsProperty sınıfındaki her değişkenin JSON nesnesindeki bir anahtar adına karşılık geldiğini unutmayın.  JSON'daki türlerle eşleşmek için String dışındaki tüm değerler için price nesnelerini kullanırsınız. price, Double türündedir.  Double, herhangi bir JSON sayısını temsil etmek için kullanılabilir.
Moshi, JSON'u ayrıştırırken anahtarları ada göre eşleştirir ve veri nesnelerini uygun değerlerle doldurur.
img_srctuşunun satırını aşağıdaki satırla değiştirin. İstendiğindecom.squareup.moshi.Jsoniçe aktarın.
@Json(name = "img_src") val imgSrcUrl: String,Bazen bir JSON yanıtındaki anahtar adları, Kotlin özelliklerini kafa karıştırıcı hale getirebilir veya kodlama stilinizle eşleşmeyebilir. Örneğin, JSON dosyasındaki img_src anahtarı alt çizgi kullanırken Kotlin özellikleri genellikle büyük ve küçük harflerden oluşan birleşik kelimeler ("camel case") kullanır. 
Veri sınıfınızda JSON yanıtındaki anahtar adlarından farklı değişken adları kullanmak için @Json ek açıklamasını kullanın. Bu örnekte, veri sınıfındaki değişkenin adı imgSrcUrl'dır. Değişken, @Json(name = "img_src") kullanılarak img_src JSON özelliğiyle eşlenir.
3. adım: MarsApiService ve OverviewViewModel'i güncelleyin
MarsProperty veri sınıfı kullanıma sunulduğundan artık ağ API'sini ve ViewModel'yi Moshi verilerini içerecek şekilde güncelleyebilirsiniz.  
network/MarsApiService.ktadlı kişiyi aç.ScalarsConverterFactoryiçin eksik sınıf hataları görebilirsiniz. Bunun nedeni, 1. adımda yaptığınız Retrofit bağımlılığı değişikliğidir. Bu hataları en kısa sürede düzeltmeniz gerekir.- Dosyanın en üstünde, Retrofit oluşturucudan hemen önce Moshi örneğini oluşturmak için aşağıdaki kodu ekleyin.  İstendiğinde 
com.squareup.moshi.Moshivecom.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactoryöğelerini içe aktarın. 
private val moshi = Moshi.Builder()
   .add(KotlinJsonAdapterFactory())
   .build()Retrofit ile yaptığınıza benzer şekilde, burada Moshi oluşturucuyu kullanarak bir moshi nesnesi oluşturursunuz.  Moshi'nin ek açıklamalarının Kotlin ile düzgün çalışması için KotlinJsonAdapterFactory ekleyin ve ardından build() çağrısı yapın.  
- Retrofit oluşturucuyu 
ScalarConverterFactoryyerineMoshiConverterFactorykullanacak şekilde değiştirin ve yeni oluşturduğunuzmoshiörneğini iletin. İstendiğinderetrofit2.converter.moshi.MoshiConverterFactoryiçe aktarın. 
private val retrofit = Retrofit.Builder()
   .addConverterFactory(MoshiConverterFactory.create(moshi))
   .baseUrl(BASE_URL)
   .build()ScalarConverterFactoryiçin içe aktarma işlemini de silin.
Silinecek kod:
import retrofit2.converter.scalars.ScalarsConverterFactory- Retrofit'in 
Call<String>yerineMarsPropertynesnelerinin listesini döndürmesi içinMarsApiServicearayüzünü güncelleyin. 
interface MarsApiService {
   @GET("realestate")
   fun getProperties():
      Call<List<MarsProperty>>
}OverviewViewModel.ktadlı kişiyi aç.getMarsRealEstateProperties()yöntemindegetProperties().enqueue()adlı kişiye yapılan aramaya gidin.Callback<String>olan bağımsız değişkenienqueue()olarakCallback<List<MarsProperty>>ile değiştirin. İstendiğindecom.example.android.marsrealestate.network.MarsPropertyiçe aktarın.
MarsApi.retrofitService.getProperties().enqueue( 
   object: Callback<List<MarsProperty>> {onFailure()içinde, bağımsız değişkeniCall<String>yerineCall<List<MarsProperty>>olarak değiştirin:
override fun onFailure(call: Call<List<MarsProperty>>, t: Throwable) {onResponse()bağımsız değişkenlerinde aynı değişikliği yapın:
override fun onResponse(call: Call<List<MarsProperty>>, 
   response: Response<List<MarsProperty>>) {onResponse()gövdesinde,_response.valueiçin mevcut atamayı aşağıda gösterilen atamayla değiştirin.response.body()artıkMarsPropertynesnelerinin bir listesi olduğundan bu listenin boyutu, ayrıştırılan özelliklerin sayısıdır. Bu yanıt mesajı, söz konusu tesis sayısını yazdırır:
_response.value = 
   "Success: ${response.body()?.size} Mars properties retrieved"- Uçak modunun kapalı olduğundan emin olun.  Uygulamayı derleyip çalıştırın. Bu kez mesajda web hizmetinden döndürülen özelliklerin sayısı gösterilmelidir:

 
Artık Retrofit API hizmeti çalışıyor ancak uygulamanız gereken iki geri çağırma yöntemi içeren bir geri çağırma kullanıyor. Bir yöntem başarıyı, diğeri ise başarısızlığı ele alır ve başarısızlık sonucu istisnaları bildirir. Geri çağırma işlevleri yerine istisna işleme ile birlikte eş yordamlar kullanabilseydiniz kodunuz daha verimli ve okunması daha kolay olurdu. Retrofit, coroutine'leri entegre eden bir kitaplığa sahiptir.
Bu görevde, ağ hizmetinizi ve ViewModel'yı eş yordam kullanacak şekilde dönüştürürsünüz.  
1. adım: Coroutine bağımlılıklarını ekleyin
- build.gradle (Module: app) dosyasını açın.
 - Bağımlılıklar bölümünde, temel Kotlin eşrutin kitaplıkları ve Retrofit eşrutin kitaplığı için destek ekleyin:
 
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version_kotlin_coroutines" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version_kotlin_coroutines" implementation "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:$version_retrofit_coroutines_adapter"
- Projeyi yeni bağımlılıklarla yeniden oluşturmak için Şimdi Senkronize Et'i tıklayın.
 
2. adım: MarsApiService ve OverviewViewModel'i güncelleyin
MarsApiService.ktiçinde Retrofit oluşturucuyuCoroutineCallAdapterFactorykullanacak şekilde güncelleyin. Tam oluşturucu artık şu şekilde görünüyor:
private val retrofit = Retrofit.Builder()
        .addConverterFactory(MoshiConverterFactory.create(moshi))
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .baseUrl(BASE_URL)
        .build()Çağrı bağdaştırıcıları, Retrofit'in varsayılan Call sınıfı dışında bir şey döndüren API'ler oluşturmasına olanak tanır.  Bu durumda CoroutineCallAdapterFactory, getProperties() tarafından döndürülen Call nesnesini Deferred nesnesiyle değiştirmemize olanak tanır.
getProperties()yöntemindeCall<List<MarsProperty>>değeriniDeferred<List<MarsProperty>>olarak değiştirin. İstendiğindekotlinx.coroutines.Deferrediçe aktarın. TamgetProperties()yöntemi şu şekilde görünür:
@GET("realestate")
fun getProperties():
   Deferred<List<MarsProperty>>Deferred arayüzü, sonuç değeri döndüren bir eşzamanlılık işi tanımlar (Deferred, Job'dan devralınır). Deferred arayüzü, değer hazır olana kadar kodunuzun engellemeden beklemesine neden olan ve ardından bu değeri döndüren await() adlı bir yöntem içerir. 
OverviewViewModel.ktadlı kişiyi aç.initbloğundan hemen önce bir coroutine işi ekleyin:
private var viewModelJob = Job()- Ana dağıtıcıyı kullanarak bu yeni iş için bir ortak yordam kapsamı oluşturun:
 
private val coroutineScope = CoroutineScope(
   viewModelJob + Dispatchers.Main )Dispatchers.Main dağıtıcı, çalışması için kullanıcı arayüzü iş parçacığını kullanır.  Retrofit tüm işlemlerini arka plan iş parçacığında yaptığından kapsam için başka bir iş parçacığı kullanmaya gerek yoktur. Bu sayede, sonuç aldığınızda MutableLiveData değerini kolayca güncelleyebilirsiniz.
getMarsRealEstateProperties()içindeki tüm kodu silin. Buradaenqueue()çağrısı veonFailure()ileonResponse()geri çağırmaları yerine eş yordamlar kullanacaksınız.getMarsRealEstateProperties()içinde, eş yordamı başlatın:
coroutineScope.launch { 
}
Retrofit'in ağ görevi için döndürdüğü Deferred nesnesini kullanmak için bir coroutine içinde olmanız gerekir. Bu nedenle, burada yeni oluşturduğunuz coroutine'i başlatırsınız.  Ana iş parçacığında kod yürütmeye devam ediyorsunuz ancak artık eşzamanlılığı yönetmek için eş yordamları kullanıyorsunuz.
- Başlatma bloğunun içinde 
retrofitServicenesnesindegetProperties()işlevini çağırın: 
var getPropertiesDeferred = MarsApi.retrofitService.getProperties()MarsApi hizmetinden getProperties() çağrısı yapıldığında, arka plan iş parçacığında ağ çağrısı oluşturulup başlatılır ve bu görev için Deferred nesnesi döndürülür. 
- Ayrıca başlatma bloğunun içine, istisnaları işlemek için bir 
try/catchbloğu ekleyin: 
try {
} catch (e: Exception) {
  
}try {}bloğunun içinde,Deferrednesnesindeawait()işlevini çağırın:
var listResult = getPropertiesDeferred.await()Deferred nesnesinde await() işlevini çağırmak, değer hazır olduğunda ağ çağrısından sonucu döndürür. await() yöntemi engelleme yapmaz. Bu nedenle Mars API hizmeti, mevcut iş parçacığını engellemeden verileri ağdan alır. Bu, kullanıcı arayüzü iş parçacığı kapsamında olduğumuz için önemlidir. Görev tamamlandıktan sonra kodunuz kaldığı yerden yürütülmeye devam eder.  Bu işlem, istisnaları yakalayabilmeniz için try {} içinde gerçekleşir.  
- Ayrıca 
try {}bloğunun içinde,await()yönteminden sonra başarılı yanıt için yanıt mesajını güncelleyin: 
_response.value = 
   "Success: ${listResult.size} Mars properties retrieved"catch {}bloğunda hata yanıtını işleyin:
_response.value = "Failure: ${e.message}"
Tam getMarsRealEstateProperties() yöntemi artık şu şekilde görünür:
private fun getMarsRealEstateProperties() {
   coroutineScope.launch {
       var getPropertiesDeferred = 
          MarsApi.retrofitService.getProperties()
       try {          
           _response.value = 
              "Success: ${listResult.size} Mars properties retrieved"
       } catch (e: Exception) {
           _response.value = "Failure: ${e.message}"
       }
   }
}- Sınıfın en altına şu kodla bir 
onCleared()geri çağırma ekleyin: 
override fun onCleared() {
   super.onCleared()
   viewModelJob.cancel()
}Bu ViewModel kullanan OverviewFragment kaybolacağından, ViewModel yok edildiğinde veri yükleme işlemi durdurulmalıdır. ViewModel yok edildiğinde yüklemeyi durdurmak için onCleared() öğesini geçersiz kılarak işi iptal edersiniz.
- Uygulamayı derleyip çalıştırın. Bu kez de önceki görevdekiyle aynı sonucu (özellik sayısıyla ilgili bir rapor) elde edersiniz ancak bu kez daha basit bir kod ve hata işleme ile.
 
Android Studio projesi: MarsRealEstateNetwork
REST web hizmetleri
- Web hizmeti, uygulamanızın istekte bulunmasını ve veri almasını sağlayan bir internet hizmetidir.
 - Yaygın web hizmetleri REST mimarisini kullanır. REST mimarisi sunan web hizmetleri, RESTful hizmetleri olarak bilinir. RESTful web hizmetleri, standart web bileşenleri ve protokolleri kullanılarak oluşturulur.
 - URI'ler aracılığıyla standartlaştırılmış bir şekilde REST web hizmetine istekte bulunursunuz.
 - Bir web hizmetini kullanmak için uygulamanın ağ bağlantısı oluşturması ve hizmetle iletişim kurması gerekir. Ardından uygulama, yanıt verilerini alıp ayrıştırmalı ve uygulamanın kullanabileceği bir biçime dönüştürmelidir.
 - Retrofit kitaplığı, uygulamanızın bir REST web hizmetine istekte bulunmasını sağlayan bir istemci kitaplığıdır.
 - Retrofit'e web hizmetine gönderdiği ve web hizmetinden aldığı verilerle ne yapacağını söylemek için dönüştürücüler kullanın.  Örneğin, 
ScalarsConverterdönüştürücü, web hizmeti verileriniStringveya başka bir temel öğe olarak ele alır. - Uygulamanızın internete bağlanmasını sağlamak için Android manifestine 
"android.permission.INTERNET"iznini ekleyin. 
JSON ayrıştırma
- Bir web hizmetinden gelen yanıt genellikle yapılandırılmış verileri temsil etmek için kullanılan yaygın bir değişim biçimi olan JSON olarak biçimlendirilir.
 - JSON nesnesi, anahtar/değer çiftlerinden oluşan bir koleksiyondur. Bu koleksiyona bazen sözlük, karma eşleme veya ilişkisel dizi de denir.
 - JSON nesneleri koleksiyonu, JSON dizisidir. Bir web hizmetinden yanıt olarak JSON dizisi alırsınız.
 - Anahtar/değer çiftindeki anahtarlar tırnak içine alınır. Değerler sayı veya dize olabilir. Dizeler de tırnak işaretleriyle çevrilidir.
 - Moshi kitaplığı, JSON dizesini Kotlin nesnelerine dönüştüren bir Android JSON ayrıştırıcısıdır. Retrofit, Moshi ile çalışan bir dönüştürücüye sahiptir.
 - Moshi, bir JSON yanıtındaki anahtarları, aynı ada sahip bir veri nesnesindeki özelliklerle eşleştirir.
 - Bir anahtar için farklı bir özellik adı kullanmak istiyorsanız bu özelliği 
@Jsonek açıklaması ve JSON anahtar adı ile açıklama olarak ekleyin. 
Retrofit ve coroutine'ler
- Çağrı bağdaştırıcıları, Retrofit'in varsayılan 
Callsınıfı dışında bir şey döndüren API'ler oluşturmasına olanak tanır.Callyerine eş yordamDeferredkullanmak içinCoroutineCallAdapterFactorysınıfını kullanın. - Değer hazır olana kadar engellemeden beklemesi ve ardından değerin döndürülmesi için 
Deferrednesnesindeawait()yöntemini kullanın. 
Udacity kursu:
Android geliştirici belgeleri:
Kotlin belgeleri:
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
Retrofit'in web hizmetleri API'si oluşturmak için ihtiyaç duyduğu iki temel şey nedir?
▢ Web hizmetinin temel URI'si ve bir GET sorgusu.
▢ Web hizmetinin temel URI'si ve bir dönüştürücü fabrikası.
▢ Web hizmetine ağ bağlantısı ve yetkilendirme jetonu.
▢ Bir dönüştürücü fabrikası ve yanıt için bir ayrıştırıcı.
2. Soru
Moshi kitaplığının amacı nedir?
▢ Bir web hizmetinden verileri geri almak için.
▢ Web hizmeti isteğinde bulunmak için Retrofit ile etkileşim kurmak.
▢ Bir web hizmetinden gelen JSON yanıtını Kotlin veri nesnelerine ayrıştırmak için.
▢ Kotlin nesnelerini, JSON yanıtındaki anahtarlarla eşleşecek şekilde yeniden adlandırmak için.
3. Soru
Retrofit çağrı adaptörleri ne için kullanılır?
▢ Retrofit'in coroutine'leri kullanmasını sağlarlar.
▢ Web hizmeti yanıtını Kotlin veri nesnelerine dönüştürürler.
▢ Bir Retrofit çağrısını web hizmeti çağrısına dönüştürürler.
▢ Retrofit'te varsayılan Call sınıfı dışında bir şey döndürme özelliği eklenir.
Bir 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.