Android ile yaygın Kotlin kalıplarını kullanma

Bu konuda, Kotlin dilinin en faydalı yönlerine odaklanacağız bazı ipuçları vereceğim.

Parçalarla çalışma

Aşağıdaki bölümlerde, Kotlin hakkında bilgi edinmek için Fragment özellikleri inceleyelim.

Devralındı

Kotlin'de class anahtar kelimesini kullanarak bir sınıf tanımlayabilirsiniz. Sonraki örnek olarak LoginFragment, Fragment etiketinin alt sınıfıdır. Hedeflerinizin her biri için alt sınıf ile üst sınıf arasında : operatörünü kullanarak devralma:

class LoginFragment : Fragment()

Bu sınıf beyanında, LoginFragment sınıfının çağrılmasından üst sınıfının kurucusu Fragment oldu.

LoginFragment içinde bir dizi yaşam döngüsü geri çağırmasını Fragment hesabınızdaki durum değişikliklerine yanıt verebilirsiniz. Bir işlevi geçersiz kılmak için override anahtar kelimesi, aşağıdaki örnekte gösterildiği gibi:

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
): View? {
    return inflater.inflate(R.layout.login_fragment, container, false)
}

Üst sınıftaki bir işleve başvuruda bulunmak için gösterildiği gibi super anahtar kelimesini kullanın aşağıdaki örnekte:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
}

Boş değer atanabilirliği ve başlatma

Önceki örneklerde, geçersiz kılınan yöntemlerdeki bazı parametreler son ekinde ? soru işareti bulunan türler. Bu, bağımsız değişkenlerin bu parametreler için iletilen değer null olabilir. Şunları yaptığınızdan emin olun: null atanabilirliğini güvenli bir şekilde nasıl ele alabileceğinizi öğrenin.

Kotlin'de, bir nesneyi tanımlarken nesnenin özelliklerini başlatmanız gerekir. Bunun anlamı, bir sınıfın bir örneğini aldığınızda erişilebilir özelliklerinden herhangi birine referans vermelidir. Fragment içindeki View nesneleri ancak Fragment#onCreateView çağrısına kadar şişirmeye hazır değildir. View için özellik başlatmayı ertelemenin bir yolunu bulmanız gerekiyor.

lateinit, özellik başlatmayı ertelemenize olanak tanır. lateinit kullanırken mülkünüzü en kısa sürede başlatmalısınız.

Aşağıdaki örnekte, tablodaki View nesneleri atamak için lateinit kullanımı gösterilmektedir onViewCreated:

class LoginFragment : Fragment() {

    private lateinit var usernameEditText: EditText
    private lateinit var passwordEditText: EditText
    private lateinit var loginButton: Button
    private lateinit var statusTextView: TextView

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        usernameEditText = view.findViewById(R.id.username_edit_text)
        passwordEditText = view.findViewById(R.id.password_edit_text)
        loginButton = view.findViewById(R.id.login_button)
        statusTextView = view.findViewById(R.id.status_text_view)
    }

    ...
}

SAM dönüşümü

Şunu uygulayarak Android'de tıklama etkinliklerini dinleyebilirsiniz: OnClickListener arayüzü. Button nesne bir setOnClickListener() içeriyor OnClickListener uygulamasını alan işlev.

OnClickListener, şunları yapmanız gereken tek bir soyut yönteme (onClick()) sahip. yardımcı olur. Çünkü setOnClickListener() her zaman bir OnClickListener bağımsız değişkendir ve OnClickListener her zaman aynı tek bir özete sahip olduğu için yöntemi kullanıldığında, bu uygulama Kotlin. Bu süreç Tek Soyut Yöntem dönüştürme, veya SAM dönüşümü.

SAM dönüşümü, kodunuzu önemli ölçüde daha temiz hale getirebilir. Aşağıdaki örnek OnClickListener uygulamak için SAM dönüşümünün nasıl kullanılacağını gösterir Button:

loginButton.setOnClickListener {
    val authSuccessful: Boolean = viewModel.authenticate(
            usernameEditText.text.toString(),
            passwordEditText.text.toString()
    )
    if (authSuccessful) {
        // Navigate to next screen
    } else {
        statusTextView.text = requireContext().getString(R.string.auth_failed)
    }
}

setOnClickListener() işlevine iletilen anonim işlev içindeki kod kullanıcı loginButton tıkladığında yürütülür.

Tamamlayıcı nesneler

Tamamlayıcı nesneler Birbirine bağlı değişkenleri ya da işlevleri tanımlamak için bir mekanizma ve belirli bir nesneyle bağlantılı olmamaları anlamına gelir. Tamamlayıcı nesneler, değişkenler ve yöntemler için Java'nın static anahtar kelimesini kullanmaya benzer.

Aşağıdaki örnekte TAG, String sabitidir. Benzersiz bir URL'ye ihtiyacınız yoktur. her LoginFragment örneği için String örneği oluşturur; bu nedenle bunu tamamlayıcı bir nesnede tanımlarsınız:

class LoginFragment : Fragment() {

    ...

    companion object {
        private const val TAG = "LoginFragment"
    }
}

TAG öğesini dosyanın en üst düzeyinde tanımlayabilirsiniz, ancak dosyasında da çok sayıda değişken, işlev ve sınıf bulunabilir üst düzeylerde de tanımlanmıştır. Tamamlayıcı nesneler bağlantı kurmaya yardımcı olur tanımlama, değişkenleri, fonksiyonları ve sınıf tanımını olduğunu görebilirsiniz.

Mülk yetkisi

Özellikleri başlatırken Android'de kullanılan bazı yaygın Fragment içinde ViewModel erişimi gibi alışkanlıklar. Fazlalıktan kaçınmak için Kotlin'in özellik yetkisi söz dizimini kullanabilirsiniz.

private val viewModel: LoginViewModel by viewModels()

Mülk yetkisi, yeniden kullanabileceğiniz yaygın bir uygulama sağlar en iyi uygulamaları paylaşacağız. Android KTX, sizin için bazı mülk yetkileri sağlar. Örneğin viewModels,ViewModel şu anki Fragment.

Mülk yetkilendirme, biraz performans yükü ekleyen yansıma kullanır. Ödün verme, geliştirme zamanından tasarruf sağlayan kısa ve öz bir söz dizimidir.

Boş değer atanabilirliği

Kotlin, baştan sona tür güvenliğini sağlayan katı değer atanabilirlik kuralları sağlar. en iyi şekilde yararlanabilirsiniz. Kotlin'de nesnelere yapılan referanslar varsayılandır. Değişkene null değer atamak için null değer tanımlamanız gerekir. değişkeni türünü belirtmek için temel türün sonuna ? ekleyin.

Örnek olarak, aşağıdaki ifade Kotlin'de yasa dışıdır. name bir türde String ve null olamaz:

val name: String = null

Null değere izin vermek için boş değerli bir String türünü (String?) aşağıdaki örnekte gösterilmektedir:

val name: String? = null

Birlikte çalışabilirlik

Kotlin'in katı kuralları, kodunuzu daha güvenli ve kısa hale getirir. Bu kurallar daha düşük uygulamanızın NullPointerException olabilir. Ayrıca, girin.

Android uygulaması yazarken genellikle Kotlin dışı koda da çağrıda bulunmanız gerekir. Android API'lerinin çoğu Java programlama dilinde yazılır.

Boş değer atanabilirliği, Java ile Kotlin'in davranış açısından farklılık gösterdiği önemli bir alandır. Java daha az katı değerdedir.

Örneğin, Account sınıfında String dahil birkaç mülk bulunur. name adlı mülkmızı kullanıyorsunuz. Java, Kotlin'in null değeriyle ilgili kurallarına sahip değildir. bunun yerine isteğe bağlı boşluk ek açıklamalarına boş değer atayıp atayamayacağınızı kontrol edin.

Android çerçevesi esas olarak Java'da yazıldığından, bu senaryoyu kullanmanız gerekir.

Platform türleri

Birname Java Account sınıfı, derleyici, String kodunun Kotlin'de String veya String?. Bu belirsizlik, platform türü, String!.

String!, Kotlin derleyicisi için özel bir anlama sahip değildir. String! temsil edebilir String veya String? olarak tanımlarsanız derleyici bir iki türe denk geliyor. Aşağıdaki durumda NullPointerException atma riskiyle karşı karşıya olduğunuzu unutmayın: değeri String olarak temsil eder ve boş değer atar.

Bu sorunu çözmek için her yazdığınızda geçersiz değer ek açıklamalarını kullanmanız gerekir. kod yazın. Bu ek açıklamalar hem Java hem de Kotlin geliştiricilerine yardımcı olur.

Örneğin, Java'da tanımlandığı şekliyle Account sınıfını aşağıda görebilirsiniz:

public class Account implements Parcelable {
    public final String name;
    public final String type;
    private final @Nullable String accessId;

    ...
}

Üye değişkenlerinden biri olan accessId, @Nullable boş bir değer alabileceğini gösterir. Kotlin, accessId hücresini tedavi eder String? olarak.

Bir değişkenin hiçbir zaman null olamayacağını belirtmek için @NonNull ek açıklamasını kullanın:

public class Account implements Parcelable {
    public final @NonNull String name;
    ...
}

Bu senaryoda name, Kotlin'de null olmayan bir String olarak kabul edilir.

Boş değer atanabilirlik notları, tüm yeni Android API'lerinde ve mevcut birçok mevcut Android API'leri. Birçok Java kitaplığı, null değer ek açıklamaları ekleyerek hem Kotlin hem de Java geliştiricilerini destekler.

Boş değer atanabilirliği işleme

Bir Java türünden emin değilseniz Java türünü null olarak değerlendirmelisiniz. Örneğin, Account sınıfının name üyesine ek açıklama eklenmediğinden, boş değerli bir String olarak kabul edilmelidir.

name değerini, başında veya sonunda yer almayacak şekilde kırpmak istiyorsanız sonda boşluk varsa Kotlin’in trim işlevini kullanabilirsiniz. Güvenli bir şekilde, String? için farklı yöntemler kullanabilirsiniz. Bu yöntemlerden biri, not-null onaylama operatörü, !!, aşağıdaki örnekte gösterildiği gibi:

val account = Account("name", "type")
val accountName = account.name!!.trim()

!! operatörü, sol tarafındaki her şeyi null olmayan bir şekilde işler. Dolayısıyla, bu durumda, name değerini null olmayan bir String olarak ele alıyorsunuz. ifadesi null ise uygulamanız bir NullPointerException atar. Bu operatör hızlı ve kolaydır, ancak NullPointerException örneklerini kodunuza yeniden ekleyin.

Daha güvenli bir seçenek, güvenli arama operatörünü, ?. kullanmaktır. şu örneği inceleyin:

val account = Account("name", "type")
val accountName = account.name?.trim()

Güvenli arama operatörü kullanıldığında name null değilse name?.trim(), başında veya sonunda boşluk olmayan bir ad değeridir. Eğer name null, name?.trim() sonucu null olur. Bunun anlamı, Uygulamanız bu ifadeyi yürütürken hiçbir zaman NullPointerException atamaz.

Güvenli arama operatörü sizi olası bir NullPointerException uygulamasından korurken, sonraki ifadeye boş değer iletir. Bunun yerine null değerini işleyebilirsiniz aşağıdaki gibi bir Elvis operatörü (?:) kullanarak örnek:

val account = Account("name", "type")
val accountName = account.name?.trim() ?: "Default name"

Elvis operatörünün sol tarafındaki ifadenin sonucu boş ise sağ taraftaki değer accountName öğesine atanır. Bu tekniği, normalde boş olacak bir varsayılan değer sağlamak için yararlıdır.

Aşağıda gösterildiği gibi, bir işlevden erken dönmek için Elvis operatörünü de kullanabilirsiniz. aşağıdaki örnekte:

fun validateAccount(account: Account?) {
    val accountName = account?.name?.trim() ?: "Default name"

    // account cannot be null beyond this point
    account ?: return

    ...
}

Android API değişiklikleri

Android API'leri giderek Kotlin dostu hale geliyor. Android'in, AppCompatActivity ve Fragment dahil olmak üzere en yaygın API'ler değer atanabilirlik ek açıklamaları ve Fragment#getContext gibi belirli çağrılar ve Kotlin dostu alternatifleri ortaya koyduk.

Örneğin, bir Fragment öğesinin Context öğesine erişmek hemen hemen her zaman boş değildir, Fragment içinde yaptığınız çağrıların çoğu Fragment sırasında gerçekleştiği için bir Activity (Context alt sınıfı) ile ilişkilidir. Bununla birlikte, Fragment#getContext her zaman null olmayan bir değer döndürmez çünkü Fragment öğesinin Activity öğesine bağlı olmadığı senaryolar. Dolayısıyla, Fragment#getContext türü boş değerli.

Fragment#getContext öğesinden döndürülen Context null olduğundan (ve ek açıklaması @Nullable olarak eklenmişse) Kotlin kodunuzda bunu Context? olarak işlemeniz gerekir. Bu, sorunları çözerken daha önce bahsedilen operatörlerden birini özellik ve işlevlerine erişmeden önce null atanabilir hale getirilebilir. Bunlardan bazıları için senaryolarda, Android bu kolaylığı sağlayan alternatif API'ler içerir. Örneğin, Fragment#requireContext, null olmayan bir Context değeri döndürür ve Context null olduğunda çağrılırsa bir IllegalStateException. Bu şekilde ekip sonuç olarak elde edilen Context değerini güvenli arama operatörleri veya çözümleri

Özellik başlatma

Kotlin'deki özellikler varsayılan olarak başlatılmaz. Başlatılması gerekir ilk kullanıma sunulduğunda.

Özellikleri ilk kullanıma birkaç farklı şekilde hazırlayabilirsiniz. Aşağıdaki örnek , bir index değişkenine sınıf bildirimi:

class LoginFragment : Fragment() {
    val index: Int = 12
}

Bu başlatma işlemi, bir başlatıcı bloğunda da tanımlanabilir:

class LoginFragment : Fragment() {
    val index: Int

    init {
        index = 12
    }
}

Yukarıdaki örneklerde, bir LoginFragment aşağıdaki durumlarda index başlatılır: somut olarak ortaya koyar.

Ancak nesne sırasında başlatılamayan bazı mülkleriniz olabilir inşaat işleri. Örneğin, web sitesindeki bir View Fragment; bu, düzenin önce şişirilmiş olması gerektiği anlamına gelir. Enflasyon, bir Fragment oluşturulduğunda gerçekleşmez. Arama sırasında olduğundan şişiriliyor Fragment#onCreateView

Bu senaryoyu ele almanın bir yolu, görünümü null ve aşağıdaki örnekte gösterildiği gibi en kısa sürede başlatın:

class LoginFragment : Fragment() {
    private var statusTextView: TextView? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)

            statusTextView = view.findViewById(R.id.status_text_view)
            statusTextView?.setText(R.string.auth_failed)
    }
}

Bu işlem beklendiği gibi çalışırken View için null değerleri yönetmeniz gerekir. her zaman yeni bir kaynak sağlar. View için lateinit kullanılması daha iyi bir çözümdür başlatma:

class LoginFragment : Fragment() {
    private lateinit var statusTextView: TextView

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)

            statusTextView = view.findViewById(R.id.status_text_view)
            statusTextView.setText(R.string.auth_failed)
    }
}

lateinit anahtar kelimesi, kurulduğundan emin olun. Mülkünüze başlatılmadan önce başvuruluyorsa Kotlin bir UninitializedPropertyAccessException fırlatıyor, bu yüzden mülkünüzü en kısa sürede başlatın.