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ş
Uygulamanız için sorunsuz bir kullanıcı deneyimi oluşturmanın en önemli önceliklerinden biri, kullanıcı arayüzünün her zaman duyarlı ve sorunsuz çalıştığından emin olmaktır. Kullanıcı arayüzü performansını iyileştirmenin bir yolu, veritabanı işlemleri gibi uzun süreli görevleri arka plana taşımaktır.
Bu codelab'de, veritabanı iletimini ana iş parçacığının dışında gerçekleştirmek için Kotlin eş yordamlarını kullanarak TrackMySleepquality uygulamasının kullanıcıya yönelik kısmını uyguluyorsunuz.
Bilmeniz gerekenler
Aşağıdaki konular hakkında bilgi sahibi olmalısınız:
- Bir etkinlik, parçalar, görünümler ve tıklama işleyiciler kullanarak temel bir kullanıcı arayüzü (UI) oluşturma.
- Parçalar arasında gezinme ve parçalar arasında basit verileri iletmek için
safeArgs
kullanma. - Modelleri görüntüleyin, model fabrikalarını, dönüşümleri ve
LiveData
'i görüntüleyin. Room
veritabanı oluşturma, DAO oluşturma ve varlıkları tanımlama.- Mesaj dizisi oluşturma ve çoklu işleme kavramları hakkında bilgi sahibiyseniz bu yöntem yararlıdır.
Neler öğreneceksiniz?
- Android'de ileti dizilerinin işleyiş şekli.
- Veritabanı işlemlerini ana iş parçacığının dışına taşımak için Kotlin eş yordamlarını kullanma.
- Biçimlendirilmiş veriler
TextView
içinde nasıl görüntülenir?
Yapacaklarınız
- Veritabanındaki verileri toplamak, depolamak ve görüntülemek için TrackMySleepquality uygulamasını genişletin.
- Uzun süreli veritabanı işlemlerini arka planda çalıştırmak için eş yordam kullanın.
- Gezinmeyi ve atıştırmalık çubuğunun görüntülenmesini tetiklemek için
LiveData
politikasını kullanın. - Düğmeleri etkinleştirmek ve devre dışı bırakmak için
LiveData
öğesini kullanın.
Bu codelab'de, TrackMySleepquality uygulamasının görünüm modelini, eş yordamlarını ve veri görüntüleme bölümlerini oluşturursunuz.
Uygulamada, aşağıdaki resimde gösterildiği gibi parçalarla temsil edilen iki ekran vardır.
Solda gösterilen ilk ekranda izlemeyi başlatmak ve durdurmak için düğmeler bulunur. Ekranda kullanıcının tüm uyku verileri gösterilir. Temizle düğmesi, uygulamanın kullanıcı için topladığı tüm verileri kalıcı olarak siler.
Sağ tarafta gösterilen ikinci ekran uyku kalitesi puanı seçmek içindir. Uygulamada, puan sayısal olarak gösterilir. Uygulama, geliştirme amacıyla hem yüz simgelerini hem de sayısal eşdeğerlerini gösterir.
Kullanıcının akışı şu şekildedir:
- Kullanıcı uygulamayı açar ve uyku izleme ekranı sunulur.
- Kullanıcı Başlat düğmesine dokunur. Bu işlem, başlangıç zamanını kaydeder ve gösterir. Başlat düğmesi devre dışıdır ve Durdur düğmesi etkindir.
- Kullanıcı Durdur düğmesine dokunur. Bu işlem, bitiş zamanını kaydeder ve uyku kalitesi ekranını açar.
- Kullanıcı bir uyku kalitesi simgesi seçer. Ekran kapanır ve izleme ekranında uyku bitiş zamanı ve uyku kalitesi görüntülenir. Durdur düğmesi devre dışıdır ve Başlat düğmesi etkindir. Uygulama başka bir gece için hazır.
- Veritabanında veri olduğunda Temizle düğmesi etkinleştirilir. Kullanıcı Temizle düğmesine dokunduğunda, tüm verileri geri dönüş olmaksızın silinir. "Emin misiniz?" diye bir mesaj yoktur.
Bu uygulama, tam mimari bağlamında aşağıda gösterildiği gibi basitleştirilmiş bir mimari kullanır. Uygulama yalnızca aşağıdaki bileşenleri kullanır:
- Kullanıcı arayüzü denetleyicisi
- Modeli ve
LiveData
öğelerini görüntüleyin - Oda veritabanı
Bu görevde biçimlendirilmiş uyku izleme verilerini görüntülemek için bir TextView
kullanırsınız. (Son arayüz bu değildir. Başka bir codelab'de daha iyi bir yöntem öğreneceksiniz.)
Önceki codelab'de oluşturduğunuz TrackMySleepquality uygulamasıyla devam edebilir veya bu codelab için başlangıç uygulamasını indirebilirsiniz.
1. Adım: Başlangıç uygulamasını indirin ve çalıştırın
- GitHub'dan TrackMySleepquality-Coroutines-Starter uygulamasını indirin.
- Uygulamayı oluşturup çalıştırın. Uygulama,
SleepTrackerFragment
parçasının kullanıcı arayüzünü gösteriyor ancak veri yok. Düğmeler, dokunmaya yanıt vermez.
2. Adım: Kodu inceleyin
Bu codelab'in başlangıç kodu, 6.1 Oda veritabanı kod laboratuvarının çözüm kodu ile aynıdır.
- res/layout/activity_main.xml dosyasını açın. Bu düzende
nav_host_fragment
parçası bulunur. Ayrıca<merge>
etiketine dikkat edin.merge
etiketi, düzenleri eklerken gereksiz düzenleri ortadan kaldırmak için kullanılabilir. Bu etiketin kullanılması iyi bir fikirdir. Gereksiz düzene örnek olarak ConstraintLayout > LinearLayout > TextView verilebilir. Bu durumda sistem, Doğrusal Düzen'i ortadan kaldırabilir. Bu tür optimizasyonlar, görüntüleme hiyerarşisini basitleştirebilir ve uygulama performansını iyileştirebilir. - Gezinme klasöründe navigasyon.xml sayfasını açın. İki parça ve bunları bağlayan gezinme işlemleri görebilirsiniz.
- Düzen klasöründe, XML düzenini görmek için uyku izleyici parçasını çift tıklayın. Aşağıdakilere dikkat edin:
- Düzen verileri, veri bağlamayı etkinleştirmek için bir
<layout>
öğesine sarmalanır. ConstraintLayout
ve diğer görünümler<layout>
öğesinin içinde düzenlenir.- Dosyada bir yer tutucu
<data>
etiketi vardır.
Başlangıç uygulaması, kullanıcı arayüzü için boyutlar, renkler ve stil de sağlar. Uygulama; Room
veritabanı, DAO ve SleepNight
varlığı içeriyor. Önceki codelab'i tamamlamadıysanız kodun bu yönlerini kendiniz araştırdığınızdan emin olun.
Artık veritabanınız ve kullanıcı arayüzünüz olduğuna göre veri toplamanız, verileri veritabanına eklemeniz ve verileri göstermeniz gerekir. Tüm bu işlemler görünüm modelinde yapılır. Uyku izleyici görüntüleme modeliniz, düğme tıklamalarını işleme alır, DAO üzerinden veritabanıyla etkileşime geçer ve LiveData
üzerinden kullanıcı arayüzüne veri sağlar. Tüm veritabanı işlemlerinin ana kullanıcı arayüzü ileti dizisinden çalıştırılması ve bu işlemi eş yordamlar kullanarak gerçekleştirmeniz gerekir.
1. Adım: SleepTrackerViewModel ekleyin
- sleeptracker paketinde SleepTrackerViewModel.kt'yi açın.
- Hem başlangıç uygulamasında size sunulan hem de aşağıda gösterilen
SleepTrackerViewModel
sınıfını inceleyin. DersinAndroidViewModel()
tarihinde sona ereceğini unutmayın. Bu sınıf,ViewModel
ile aynıdır ancak uygulama bağlamını parametre olarak alır ve mülk olarak kullanılabilir hale getirir. Buna daha sonra ihtiyacınız olacaktır.
class SleepTrackerViewModel(
val database: SleepDatabaseDao,
application: Application) : AndroidViewModel(application) {
}
2. Adım: SleepTrackerViewModelFactory ekleyin
- sleeptracker paketinde SleepTrackerViewModelFactory.kt'yi açın.
- Fabrika için sizin için sağlanan kodu aşağıda görebilirsiniz:
class SleepTrackerViewModelFactory(
private val dataSource: SleepDatabaseDao,
private val application: Application) : ViewModelProvider.Factory {
@Suppress("unchecked_cast")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(SleepTrackerViewModel::class.java)) {
return SleepTrackerViewModel(dataSource, application) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
Aşağıdakileri göz önünde bulundurun:
- Sağlanan
SleepTrackerViewModelFactory
,ViewModel
ile aynı bağımsız değişkeni alır veViewModelProvider.Factory
kapsamını genişletir. - Fabrika içinde kod,
create()
öğesini geçersiz kılar. Bu, tüm sınıf türlerini bağımsız değişken olarak alır veViewModel
döndürür. - Kod,
create()
gövdesinde mevcut birSleepTrackerViewModel
sınıfının olup olmadığını kontrol eder. Böyle bir etkinlik varsa sınıfının bir örneğini döndürür. Aksi halde, kod bir istisna oluşturur.
3. Adım: SleepTrackerFragment'u güncelleyin
SleepTrackerFragment
içinde uygulama bağlamına dair bir referans alın. ReferansıonCreateView()
alanına,binding
değerinin altına yerleştirin. Görüntü modeli fabrika sağlayıcısına iletmek için bu parçanın bağlı olduğu uygulamaya referans vermeniz gerekir.
Değernull
iserequireNotNull
Kotlin işleviIllegalArgumentException
değerini döndürür.
val application = requireNotNull(this.activity).application
- DAO referansı aracılığıyla veri kaynağınıza referans vermeniz gerekir.
onCreateView()
içindereturn
öncesinde birdataSource
tanımlayın. Veritabanının DAO'suna referans almak içinSleepDatabase.getInstance(application).sleepDatabaseDao
kullanın.
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
onCreateView()
içindereturn
öncesindeviewModelFactory
öğesinin bir örneğini oluşturun. DeğerlendirmeyidataSource
veapplication
geçmeniz gerekir.
val viewModelFactory = SleepTrackerViewModelFactory(dataSource, application)
- Fabrikanız hazır olduğuna göre
SleepTrackerViewModel
uygulamasına başvurabilirsiniz.SleepTrackerViewModel::class.java
parametresi, bu nesnenin çalışma zamanı Java sınıfını belirtir.
val sleepTrackerViewModel =
ViewModelProviders.of(
this, viewModelFactory).get(SleepTrackerViewModel::class.java)
- Bitmiş kodunuz şu şekilde görünmelidir:
// Create an instance of the ViewModel Factory.
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
val viewModelFactory = SleepTrackerViewModelFactory(dataSource, application)
// Get a reference to the ViewModel associated with this fragment.
val sleepTrackerViewModel =
ViewModelProviders.of(
this, viewModelFactory).get(SleepTrackerViewModel::class.java)
Şu ana kadar onCreateView()
yöntemi kullanıldı:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Get a reference to the binding object and inflate the fragment views.
val binding: FragmentSleepTrackerBinding = DataBindingUtil.inflate(
inflater, R.layout.fragment_sleep_tracker, container, false)
val application = requireNotNull(this.activity).application
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
val viewModelFactory = SleepTrackerViewModelFactory(dataSource, application)
val sleepTrackerViewModel =
ViewModelProviders.of(
this, viewModelFactory).get(SleepTrackerViewModel::class.java)
return binding.root
}
4. Adım: Görünüm modeli için veri bağlama ekleyin
Temel ViewModel
yönergesini ayarladığınızda ViewModel
öğesini kullanıcı arayüzüne bağlamak için SleepTrackerFragment
ürününde veri bağlamayı ayarlama işlemini tamamlamanız gerekir.
fragment_sleep_tracker.xml
düzen dosyasında:
<data>
blokunun içinde,SleepTrackerViewModel
sınıfına referans veren bir<variable>
oluşturun.
<data>
<variable
name="sleepTrackerViewModel"
type="com.example.android.trackmysleepquality.sleeptracker.SleepTrackerViewModel" />
</data>
SleepTrackerFragment
içinde:
- Geçerli etkinliği, bağlamanın yaşam döngüsü sahibi olarak ayarlayın. Bu kodu
onCreateView()
yönteminin içine,return
ifadesinden önce ekleyin:
binding.setLifecycleOwner(this)
sleepTrackerViewModel
bağlama değişkeninisleepTrackerViewModel
değerine atayın. Bu kodu,onCreateView()
içinde,SleepTrackerViewModel
etiketinin oluşturulduğu kodun altına yerleştirin:
binding.sleepTrackerViewModel = sleepTrackerViewModel
- Bağlama nesnesini yeniden oluşturmanız gerekeceğinden muhtemelen bir hata görürsünüz. Hatadan kurtulmak için projeyi temizleyip yeniden oluşturun.
- Son olarak, her zaman olduğu gibi, kodunuzun hatasız bir şekilde oluşturulduğundan ve çalıştığından emin olun.
Kotlinler uzun süreli işleri zarif ve verimli bir şekilde başarmanın en iyi yoludur. Kotlin eş yordamları, geri çağırmaya dayalı kodu sıralı koda dönüştürmenizi sağlar. Sıralı olarak yazılan kodlar genelde daha kolay okunur ve hatta istisnalar gibi dil özellikleri kullanılabilir. En sonunda, eş yordamlar ve geri çağırmalar aynı işlemi yapar: Uzun süreli bir görevden bir sonuç elde edilene kadar bekler ve yürütmeye devam ederler.
Coroutine'ler aşağıdaki özelliklere sahiptir:
- Korintinler eşzamansızdur ve engelleyici değildir.
- Zaman damgaları, eşzamansız kodu sıralı hale getirmek için askıya alma işlevlerini kullanır.
Soroutin'ler eşzamansızdır.
Korintin, programınızın ana yürütme adımlarından bağımsız olarak çalışır. Bu, paralel veya ayrı bir işleyen üzerinde olabilir. Ayrıca, uygulamanın geri kalanı giriş beklerken biraz işleme koyulabilirsiniz. Eş zamansızlığın önemli yanlarından biri, net bir şekilde bekleyene kadar sonucun beklenmemesidir.
Örneğin, araştırma gerektiren bir sorunuz olduğunu ve bir iş arkadaşınızdan cevabı bulmasını istediğinizi varsayalım. Çalışıyorlar ve çalışıyorlar. Sanki bu işi ayrı ayrı ileti dizisinde yapıyorlar ve ayrı bir iş parçacığında çalışıyorlar. İş arkadaşınız geri gelip cevabın ne olduğunu söyleyene kadar yanıta bağlı olmayan başka çalışmalar yapmaya devam edebilirsiniz.
Sitede bloke edici öğeler yok.
Engellemeyen, bir coroutine'in ana veya kullanıcı arayüzü iş parçacığını engellemediği anlamına gelir. Bu nedenle, coroutine'ler için kullanıcı arayüzü etkileşimi her zaman öncelikli olduğundan kullanıcılar her zaman mümkün olduğunca sorunsuz bir deneyim yaşar.
Coroutine'lar, eşzamansız kodu sıralı hale getirmek için askıya alma işlevlerini kullanır.
Anahtar kelime suspend
, Kotlin® tarafından bir işlevi veya işlev türünü eş yordamlar için kullanılabilecek şekilde işaretleme yöntemidir. Coroutine, suspend
ile işaretlenmiş bir işlevi çağırdığında, işlev normal bir işlev çağrısı gibi döndürülene kadar engellemek yerine sonuç hazır olana kadar eş yordam yürütmeyi askıya alır. Ardından eş yordam, kaldığı yerden devam eder.
Korint askıya alınmış ve bir sonucu bekliyorken, üzerinde çalıştığı ileti dizisinin engellemesini kaldırır. Bu şekilde, diğer işlevler veya eş yordamlar çalışabilir.
suspend
anahtar kelimesi, kodun çalıştığı ileti dizisini belirtmez. Askıya alma işlevi bir arka plan ileti dizisinde veya ana ileti dizisinde çalışabilir.
Kotlin kullanmak için üç şeye ihtiyacınız vardır:
- İş
- Sevk görevlisi
- Kapsam
İş: Temel olarak, bir iş iptal edilebilir olan herhangi bir şeydir. Her coroutine'in bir işi vardır ve coroutine'i iptal etmek için bu işi kullanabilirsiniz. İşler, üst-alt hiyerarşileri halinde düzenlenebilir. Bir üst işin iptal edilmesi, işin tüm alt işçilerini hemen iptal eder. Bu, her bir eş yordamı manuel olarak iptal etmekten çok daha kolaydır.
Gönderim görevlisi: Kariyer, çeşitli ileti dizilerinde çalışacak coroutine'ler gönderir. Örneğin, Dispatcher.Main
görevleri ana ileti dizisinde çalıştırır ve Dispatcher.IO
, paylaşılan G/Ç görevlerini paylaşılan bir ileti dizisi havuzuna boşaltır.
Kapsam: coroutine® scope, eş yordamın çalıştırıldığı bağlamı tanımlar. Kapsam, bir eş yordam işi ve görev dağıtıcıyla ilgili bilgileri birleştirir. Kapsamlar, eş yordamları takip eder. Bir eş yordamı başlattığınızda, kapsam dahilinde olan coroutine'i hangi kapsamın takip edeceğini belirttiğiniz anlamına gelir.
Kullanıcının uyku verileriyle aşağıdaki şekillerde etkileşimde bulunabilmesini istersiniz:
- Kullanıcı, Başlat düğmesine dokunduğunda uygulama, yeni bir uyku gecesi oluşturur ve uyku gecesini veritabanında depolar.
- Kullanıcı Durdur düğmesine dokunduğunda uygulama, geceyi bir bitiş zamanı ile günceller.
- Kullanıcı Temizle düğmesine dokunduğunda uygulama, veritabanındaki verileri siler.
Bu veritabanı işlemleri uzun sürebilir, dolayısıyla ayrı bir ileti dizisinde çalıştırılmalıdır.
1. Adım: Veritabanı işlemleri için eş yordamlar oluşturun
Uyku İzleyici uygulamasında Başlat düğmesine dokunulduğunda, SleepTrackerViewModel
içinde yeni bir SleepNight
örneği oluşturmak ve bu örneği veritabanında depolamak için bir işlev çağırmak istersiniz.
Düğmelerden herhangi birine dokunduğunuzda, SleepNight
oluşturma veya güncelleme gibi bir veritabanı işlemi tetiklenir. Bu nedenle ve diğer uygulamalarda, uygulama düğmeleri için tıklama işleyiciler uygulamak üzere eş yordamlar kullanırsınız.
- Uygulama düzeyinde
build.gradle
dosyasını açın ve eş yordamların bağımlılıklarını bulun. Coroutine'leri kullanmak için sizin için eklenen bu bağımlılara ihtiyacınız vardır.$coroutine_version
,build.gradle
projesi dosyasındacoroutine_version =
'1.0.0'
olarak tanımlanır.
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version"
SleepTrackerViewModel
dosyasını açın.- Sınıfın gövdesinde
viewModelJob
öğesini tanımlayın ve ona birJob
örneği atayın. BuviewModelJob
, görünüm modeli artık kullanılmadığında ve yok edildiğinde bu görünüm modeli tarafından başlatılan tüm eş yordamları iptal etmenize olanak tanır. Bu şekilde, geri dönmeleri gereken bir yordam yakalanmazsınız.
private var viewModelJob = Job()
- Sınıfın sonunda
onCleared()
öğesini geçersiz kılın ve tüm eş yordamları iptal edin.ViewModel
yıkıldığındaonCleared()
çağrılır.
override fun onCleared() {
super.onCleared()
viewModelJob.cancel()
}
viewModelJob
ifadesinin tanımının hemen altında, coroutine'ler için biruiScope
tanımlayın. Kapsam, eş zamanlı olarak hangi iş parçacığının çalıştırılacağını belirler ve kapsamın iş hakkında da bilgi sahibi olması gerekir. Kapsam almak için birCoroutineScope
örneği isteyin ve bir görevliye ve bir işe geçin.
Dispatchers.Main
kullanımı, uiScope
ürününde başlatılan eş yordamların ana iş parçacığında çalıştırılacağı anlamına gelir. ViewModel
tarafından başlatılan çoğu eş yordam için bu makul bir durumdur. Çünkü bu eş yordamlar işlendikten sonra kullanıcı arayüzünde bir güncelleme gerçekleşir.
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
uiScope
tanımının altında, geceyi yerleştirmek içintonight
adında bir değişken tanımlayın. Verileri gözlemleyip değiştirebilmeniz gerektiğinden değişkenMutableLiveData
olmalıdır.
private var tonight = MutableLiveData<SleepNight?>()
tonight
değişkenini en kısa sürede başlatmak içintonight
tanımının altında birinit
bloku oluşturun veinitializeTonight()
çağrısı yapın.initializeTonight()
öğesini bir sonraki adımda tanımlıyorsunuz.
init {
initializeTonight()
}
init
blokunun altındainitializeTonight()
özelliğini uygulayın.uiScope
bölgesinde bir eş yordam başlatın. İçeride,getTonightFromDatabase()
çağrısı yaparak veritabanındakitonight
değerini alın vetonight.value
hedefine atayın.getTonightFromDatabase()
öğesini bir sonraki adımda tanımlıyorsunuz.
private fun initializeTonight() {
uiScope.launch {
tonight.value = getTonightFromDatabase()
}
}
getTonightFromDatabase()
'yi uygulama. BaşlatılmışSleepNight
değeri yoksa boş birSleepNight
döndüren birprivate suspend
işlevi olarak tanımlayın. İşlevin bir şey döndürmesi gerektiğinden bu bir hata oluşturur.
private suspend fun getTonightFromDatabase(): SleepNight? { }
-
getTonightFromDatabase()
fonksiyonunun gövdesinde,Dispatchers.IO
bağlamında çalışan bir eş yordamdan sonucu döndürün. Veritabanından veri almak G/Ç işlemi olduğundan ve kullanıcı arayüzüyle herhangi bir ilgisi olmadığından G/Ç dağıtıcısını kullanın.
return withContext(Dispatchers.IO) {}
- İade blokunun içinde, koridorun bu gece (en yeni gece) veritabanından çıkmasına izin verin. Başlangıç ve bitiş zamanları aynı değilse (gece zaten tamamlandıysa)
null
değerini döndürün. Aksi takdirde geceyi iade edin.
var night = database.getTonight()
if (night?.endTimeMilli != night?.startTimeMilli) {
night = null
}
night
Tamamladığınız getTonightFromDatabase()
askıya alma işlevi aşağıdaki gibi görünecektir. Başka hata olmamalıdır.
private suspend fun getTonightFromDatabase(): SleepNight? {
return withContext(Dispatchers.IO) {
var night = database.getTonight()
if (night?.endTimeMilli != night?.startTimeMilli) {
night = null
}
night
}
}
2. Adım: Başlat düğmesi için tıklama işleyici ekleyin
Artık Başlat düğmesi için tıklama işleyici olan onStartTracking()
'yi uygulayabilirsiniz. Yeni bir SleepNight
oluşturmanız, bunu veritabanına eklemeniz ve tonight
adlı kullanıcıya atamanız gerekir. onStartTracking()
yapısı initializeTonight()
yapısına benzeyecektir.
onStartTracking()
için işlev tanımıyla başlayın.SleepTrackerViewModel
dosyasına tıklama işleyicilerinionCleared()
üzerine yerleştirebilirsiniz.
fun onStartTracking() {}
- Devam etmek ve kullanıcı arayüzünü güncellemek için bu sonuca ihtiyacınız olduğundan
onStartTracking()
içindeuiScope
içinde bir eş yordam başlatın.
uiScope.launch {}
- Coroutine lansmanında yeni bir
SleepNight
oluşturun. Bu zaman, başlangıç zamanını belirtir.
val newNight = SleepNight()
- Coroutine lansmanındayken
newNight
veritabanını eklemek içininsert()
numaralı telefonu arayın. Buinsert()
askıya alma işlevini henüz tanımlamadığınız için bir hata mesajı göreceksiniz. (Bu, aynı addaki DAO işlevi değildir.)
insert(newNight)
- Ayrıca eş yordam lansmanında,
tonight
uygulamasını güncelleyin.
tonight.value = getTonightFromDatabase()
onStartTracking()
değerinin altında,insert()
öğesini bağımsız değişkeni olarakSleepNight
ifadesini alanprivate suspend
işlevi olarak tanımlayın.
private suspend fun insert(night: SleepNight) {}
insert()
gövdesinde, G/Ç bağlamında bir eş yordam başlatın ve DAO'daninsert()
işlevini çağırarak veritabanına geceyi ekleyin.
withContext(Dispatchers.IO) {
database.insert(night)
}
fragment_sleep_tracker.xml
düzen dosyasında, daha önce ayarladığınız veri bağlama büyüsünü kullanarakonStartTracking()
için tıklama işleyiciyistart_button
öğesine ekleyin.@{() ->
işlevi gösterimi, bağımsız değişken içermeyen vesleepTrackerViewModel
içinde tıklama işleyicisini çağıran bir lambda işlevi oluşturur.
android:onClick="@{() -> sleepTrackerViewModel.onStartTracking()}"
- Uygulamanızı oluşturup çalıştırın. Başlat düğmesine dokunun. Bu işlemle veri oluşturulur, ancak henüz hiçbir şey göremezsiniz. Bu sorunu sonra da düzeltirsiniz.
fun someWorkNeedsToBeDone { uiScope.launch { suspendFunction() } } suspend fun suspendFunction() { withContext(Dispatchers.IO) { longrunningWork() } }
3. Adım: Verileri görüntüleyin
SleepTrackerViewModel
, DAO'da getAllNights()
LiveData
döndürdüğü için nights
değişkeni LiveData
öğesine referans veriyor.
Veritabanındaki veriler her değiştiğinde LiveData
nights
en son verileri gösterecek şekilde güncellenir. Hiçbir zaman LiveData
özelliğini açıkça ayarlamanız veya güncellemeniz gerekmez. Room
, verileri veritabanıyla eşleşecek şekilde günceller.
Ancak, bir metin görünümünde nights
görüntülerseniz nesne referansı gösterilir. Nesnenin içeriğini görmek için verileri biçimlendirilmiş bir dizeye dönüştürün. nights
, veritabanından yeni veriler aldığında yürütülen Transformation
eşlemesini kullanır.
Util.kt
dosyasını açıpformatNights()
öğesinin tanımı ve ilişkiliimport
ifadelerinin açıklamasını kaldırın. Android Studio'da kodun açıklamasını kaldırmak için//
ile işaretlenen tüm kodu seçin veCmd+/
veyaControl+/
tuşlarına basın.formatNights()
öğesinin, HTML biçimli bir dize olanSpanned
türünü döndürdüğüne dikkat edin.- strings.xml dosyasını açın. Uyku verilerini görüntülemek için dize kaynaklarını biçimlendirmek üzere
CDATA
kullanımına dikkat edin. - SleepTrackerViewModel'i açın.
SleepTrackerViewModel
sınıfında,uiScope
tanımının altındanights
adlı bir değişken tanımlayın. Veritabanından tüm geceleri alın ve bunlarınights
değişkenine atayın.
private val nights = database.getAllNights()
nights
öğesinin tanımının hemen altına,nights
kodununightsString
biçimine dönüştürmek için gerekli kodu ekleyin.Util.kt
öğesindekiformatNights()
işlevini kullanın.Transformations
sınıfındanmap()
işlevinenights
değerini iletin. Dize kaynaklarınıza erişim elde etmek için eşleme işleviniformatNights()
çağrısı olarak tanımlayın.nights
ve birResources
nesnesi sağlayın.
val nightsString = Transformations.map(nights) { nights ->
formatNights(nights, application.resources)
}
fragment_sleep_tracker.xml
düzen dosyasını açın.TextView
ürünündekiandroid:text
özelliğinde artık kaynak dizeyinightsString
referansıyla değiştirebilirsiniz.
"@{sleepTrackerViewModel.nightsString}"
- Kodunuzu yeniden oluşturup uygulamayı çalıştırın. Başlangıç zamanına sahip tüm uyku verileriniz şimdi görünmelidir.
- Başlat düğmesine birkaç kez daha dokunursanız daha fazla veri görürsünüz.
Sonraki adımda Durdur düğmesi için işlevleri etkinleştirin.
4. Adım: Durdur düğmesi için tıklama işleyici ekleyin
Önceki adımla aynı kalıbı kullanarak, SleepTrackerViewModel.
içinde Durdur düğmesi için tıklama işleyiciyi uygulayın
ViewModel
ödeme listesineonStopTracking()
ekleyin.uiScope
uygulamasında bir eş yordam başlatın. Bitiş zamanı henüz belirlenmediyseendTimeMilli
öğesini geçerli sistem zamanına ayarlayın ve gece verileriyleupdate()
öğesini çağırın.
Kotlin işlevinde,return@
label
söz diziminin, iç içe yerleştirilmiş çeşitli işlevlerin yanı sıra bu ifadenin döndürdüğü işlevi belirtir.
fun onStopTracking() {
uiScope.launch {
val oldNight = tonight.value ?: return@launch
oldNight.endTimeMilli = System.currentTimeMillis()
update(oldNight)
}
}
update()
öğesini,insert()
uygulaması için kullandığınız kalıpla uygulayın.
private suspend fun update(night: SleepNight) {
withContext(Dispatchers.IO) {
database.update(night)
}
}
- Tıklama işleyiciyi kullanıcı arayüzüne bağlamak için
fragment_sleep_tracker.xml
düzen dosyasını açın ve tıklama işleyiciyistop_button
öğesine ekleyin.
android:onClick="@{() -> sleepTrackerViewModel.onStopTracking()}"
- Uygulamanızı derleyip çalıştırın.
- Başlat'a, ardından Durdur'a dokunun. Başlangıç zamanı, bitiş zamanı, değersiz bir uyku kalitesi ve uyku süresi görürsünüz.
5. Adım: Temizle düğmesi için tıklama işleyiciyi ekleyin
- Benzer şekilde,
onClear()
veclear()
uygulayın.
fun onClear() {
uiScope.launch {
clear()
tonight.value = null
}
}
suspend fun clear() {
withContext(Dispatchers.IO) {
database.clear()
}
}
- Tıklama işleyiciyi kullanıcı arayüzüne bağlamak için
fragment_sleep_tracker.xml
öğesini açın ve tıklama işleyiciyiclear_button
öğesine ekleyin.
android:onClick="@{() -> sleepTrackerViewModel.onClear()}"
- Uygulamanızı derleyip çalıştırın.
- Tüm verilerden kurtulmak için Temizle'ye dokunun. Daha sonra, yeni veriler oluşturmak için Başlat ve Durdur'a dokunun.
Android Studio projesi: TrackMySleepqualityCoroutines
- Uygulamanın kullanıcı arayüzü mimarisini ayarlamak için
ViewModel
,ViewModelFactory
ve veri bağlamayı kullanın. - Kullanıcı arayüzünün sorunsuz bir şekilde çalışmaya devam etmesi için tüm veritabanı işlemleri gibi uzun süreli görevlerde eş yordam kullanın.
- Korintinler eşzamansızdur ve engelleyici değildir. Eşzamansız kodu sıralı hale getirmek için
suspend
işlevlerini kullanırlar. - Bir eş yordam,
suspend
ile işaretlenmiş bir işlevi çağırdığında, bu işlev normal bir işlev çağrısı gibi döndürülene kadar engellemek yerine, sonuç hazır olana kadar yürütmeyi askıya alır. Sonra, sonuçta kaldığı yerden devam eder. - Engelleme ile askıya alma arasındaki fark, bir ileti dizisi engellendiyse başka bir işin gerçekleşmemesidir. Mesaj dizisi askıya alınırsa sonuç kullanılabilir hale gelene kadar başka çalışmalar gerçekleşir.
Coroutine başlatmak için bir iş, bir görev dağıtıcı ve bir kapsama ihtiyacınız vardır:
- Temel olarak iş, iptal edilebilen her şeydir. Her coroutine'in bir işi vardır ve coroutine'i iptal etmek için bir işten yararlanabilirsiniz.
- Gönderici, çeşitli ileti dizilerinde çalıştırılması için eş yordamlar gönderir.
Dispatcher.Main
, ana ileti dizisinde görevleri çalıştırırkenDispartcher.IO
, engelleme G/Ç görevlerini paylaşılan bir ileti dizisi havuzuna boşaltmak içindir. - Kapsam, iş ilanının çalıştırıldığı bağlamı tanımlamak için iş ve görev de dahil olmak üzere bilgileri birleştirir. Kapsamlar, eş yordamları takip eder.
Veritabanı işlemlerini tetikleyen tıklama işleyicileri uygulamak için şu kalıbı uygulayın:
- Sonuç, kullanıcı arayüzünü etkilediğinden ana veya kullanıcı arayüzü iş parçacığında çalışan bir eş zamanlı URL başlatın.
- Uzun süreli işi yapmak için askıya alma işlevini çağırın. Böylece, sonucu beklerken kullanıcı arayüzü iş parçacığını engellemezsiniz.
- Uzun süredir devam eden iş durumunun kullanıcı arayüzüyle bir ilgisi olmadığından G/Ç bağlamına geçin. Böylece çalışma, optimize edilmiş ve bu tür işlemler için ayrılmış bir ileti dizisi havuzunda çalışabilir.
- Ardından, işi yapmak için veritabanı işlevini çağırın.
Nesne her değiştiğinde bir LiveData
nesnesinden dize oluşturmak için bir Transformations
haritası kullanın.
Udacity kursu:
Android Geliştirici Dokümanları:
RoomDatabase
- Düzenleri <include/> ile yeniden kullanma
ViewModelProvider.Factory
SimpleDateFormat
HtmlCompat
Diğer dokümanlar ve makaleler:
- Fabrika deseni
- Coroutine codelab'i
- Coroutine'ler, resmi dokümanlar
- Elde edilen bağlam ve görev dağıtıcılar
Dispatchers
- Android Hız Sınırını Aşın
Job
launch
- Kotlin'de dönüş ve atlama
- CDATA, karakter verileri anlamına gelir. CDATA, bu dizeler arasındaki verilerin XML işaretlemesi olarak yorumlanabilecek ancak yorumlanmaması gereken verileri içerdiği anlamına gelir.
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
Aşağıdakilerden hangisi coroutine'lerin avantajlarından biridir?
- Engelleme yok
- Eşzamansız olarak çalışırlar.
- Bunlar, ana ileti dizisi dışındaki bir ileti dizisinde çalıştırılabilir.
- Böylece uygulamalar her zaman daha hızlı çalışır.
- İstisnadan yararlanabilirler.
- Doğrusal kod olarak yazılıp okunabilirler.
2. Soru
Askıya alma işlevi nedir?
suspend
anahtar kelimesiyle ek açıklamalı normal bir işlev.- Korintinlerin içinde çağrılabilecek bir işlev.
- Bir askıya alma işlevi çalışırken, çağrı dizisi askıya alınır.
- Askıya alma işlevleri her zaman arka planda çalışmalıdır.
3. Soru
Bir ileti dizisini engelleme ve askıya alma arasındaki fark nedir? Tüm doğru olanları işaretleyin.
- Yürütme engellendiğinde başka bir engellenen ileti dizisi üzerinde işlem yapılamaz.
- Yürütme askıya alındığında ileti dizisi, kaldırılan çalışmanın tamamlanmasını beklerken başka işlemler yapabilir.
- İleti dizileri beklenmeyeceği için hiçbir şey yapmayabileceğinden askıya almak daha verimlidir.
- İster engellenmiş ister askıya alınmış olsun, yürütme işlemi devam etmeden önce eş yordamın sonucunu beklemeye devam eder.
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.