CategoriesAndroidProgramming

Tips Android Developing dengan Kotlin

dalam membuat aplikasi android kita seringkali terpaku pada satu metode, padahal metode tersebut telah usang dan sudah digantikan dengan metode lain yang lebih efektif. kita memang harus selalu update kalau jadi seorang Software Engineer, termasuk update juga tentang metode-metode dalam developing aplikasi. kali ini kita akan membahas metode-metode apa yang disarankan untuk dipakai saat men-develop aplikasi android saat artikel ini ditulis.

1. Gunakan ActivityResultLauncher saat ingin mendapatkan result dari Intent

beberapa dari kita mungkin sering menggunakan StartActivityForResult untuk mendapatkan result dari intent seperti ini

fun openSomeActivityForResult() {
    val intent = Intent(this, SomeActivity::class.java);
    startActivityForResult(intent, 123);
}

override fun onActivityResult (requestCode:Int, resultCode:Int, data:Intent) {
    if (resultCode == Activity.RESULT_OK && requestCode == 123) {
        doSomeOperations();
    }
}

method tersebut kini sudah usang dan digantikan dengan method yang lebih efektif yaitu ActivityResultLauncher, yang implementasinya adalah seperti ini :

fun openSomeActivityForResult() {
    val intent = Intent(this, SomeActivity::class.java)
    resultLauncher.launch(intent)
}

var resultLauncher : ActivityResultLauncher<Intent> = registerForActivityResult(StartActivityForResult()) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        // There are no request codes
        val data: Intent? = result.data
        doSomeOperations()
    }
}

ActivityResultLauncher tidak memerlukan requestCode karena result dari intent akan diproses pada satu variabel khusus, berbeda dengan StartActivityForResult yang memerlukan requestCode karena semua result dari Intent akan diproses di satu function sehingga membuat kode kita kurang clean code karena kode tidak Single Responsibility karena ada satu function yang menjalankan banyak jenis operasi.

2. Gunakan DIFF_CALLBACK pada RecyclerView.Adapter

beberapa dari kita pasti sering menggunakan method notifyDatasetChanged() untuk memberitahu kepada adapter kalo ada perubahan di dataset Adapter seperti pada kode di bawah ini

private val data = arrayListOf<Model>()
    
fun setData(items:List<Model>) {
    data.clear()
    data.addAll(items)
    notifyDataSetChanged()
}

sebenarnya tidak ada salahnya tapi untuk sekarang tidak disarankan dan pasti akan keluar garis warna kuning di bawah method notifyDatasetChanged() jika kalian tetap memakainya.

ada metode yang disarankan untuk mengatur masalah dataset di RecyclerView.Adapter. metode itu adalah DIFF_CALLBACK. prinsip dari metode DIFF_CALLBACK adalah membandingkan data yang ada pada dataset, jika ada data baru yang berbeda maka akan masuk ke dataset. contoh penerapannya adalah seperti di bawah ini :

inisialisasi variabel berikut ke dalam class Adapter kalian (bukan class ViewHolder)

private val differCallback = object : DiffUtil.ItemCallback<Model>() {
        override fun areItemsTheSame(oldItem: Model, newItem: Model): Boolean {
            return oldItem.id == newItem.id
        }

        override fun areContentsTheSame(oldItem: Model, newItem: Model): Boolean {
            return oldItem == newItem
        }

    }

    val differ = AsyncListDiffer(this, differCallback)

untuk modelnya sesuaikan dengan dataclass yang kalian pakai di Adapter. lalu atur itemCount dan onBindViewHoldernya jadi seperti berikut :

    override fun getItemCount(): Int = differ.currentList.size

    override fun onBindViewHolder(holder: StoryViewHolder, position: Int) {
        holder.bind(differ.currentList[position])
        holder.setIsRecyclable(false)
    }

inner class StoryViewHolder(private val binding: ItemStoryBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(item: StoryModel) {
            ...
        }
    }

untuk memasukkan data ke RecyclerView yang menggunakan DIFF_CALLBACK bisa menggunakan kode seperti berikut :

recyclerViewAdapter.differ.submitList(result)

seperti itu saja tanpa perlu kita membuat variabel List dan function setData.

3. Gunakan Extension

dengan menggunakan Extension kita bisa mempersedikit kode karena Extension bisa digunakan berulang ulang. contoh penerapan extension adalah seperti berikut :

pada contoh berikut kita akan menggunakan Glide untuk memasang gambar dari internet ke ImageView kita. kita seringkali menggunakannya dengan cara seperti berikut :

Glide.with(context)
     .load(url)
     .into(imageView)

jika ada imageview lain kita mungkin akan menggunakan kode yang sama untuk mendapatkan gambarnya. sekarang kita coba membuat Extension untuk ImageView, buat satu function diluar class Activity / Fragment / Adapter yang kita pakai.

fun ImageView.setImageFromUrl(context: Context, url: String) {
    Glide
        .with(context)
        .load(url)
        .into(this)
}

class MainActivity : AppCompatActivity() {
   ....
}

contoh di atas adalah cara membuat Extension. kita bikin satu function baru dengan menyebutkan Component yang ingin kita pakai (disini adalah ImageView) lalu diikutin titik, nama function dan parameter yang dipakai. untuk memakainya di Activity hanya perlu di inisialisasi dengan cara sebagai berikut :

binding.ivUserPhoto.setImageFromUrl(this, "https://www.example.com")

hanya perlu menggunakan methodnya langsung dibelakang variabel component nya. sama seperti saat kita ingin meng set text (kalau pakai TextView)

4. Gunakan lateinit atau lazy saat menginisialisasi variabel yang belum ditentukan value nya

sebisa mungkin hindari menggunakan variabel nullable saat menggunakan kotlin seperti kode di bawah ini

private var courseId: String? = null

disini lateinit dan lazy dikhususkan untuk menghindari penggunaan variabel yang nullable. lateinit bisa digunakan saat value dari variabel tersebut bisa di dapatkan saat Activity sudah start seperti contohnya adalah saat meng inisialisasi variabel untuk viewBinding :

class MainActivity : AppCompatActivity() {
    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        ....
    }
}

seperti kita lihat, value dari variabel binding baru ditentukan saat onCreate dijalankan karena variabel binding membutuhkan parameter layoutInflater dari Activity yang mana bisa didapatkan saat Activity tersebut sudah di buat.

lalu bagaimana untuk lazy ? lazy digunakan untuk variabel yang immutable / tidak bisa diganti value nya. contoh penggunaan lazy adalah seperti ini :

class MainActivity : AppCompatActivity() {
    private val messageView : TextView by lazy {
        findViewById(R.id.message_view) as TextView
    }

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

fun onSayHello() {
        messageView.text = "Hello"
    }
}

lalu apa bedanya dengan kita menginisialisasi langsung tanpa lazy ? lazy menggunakan thread-safety mode sehingga membuat proses inisialisasi nya lebih cepat dan terhindar dari error NPE.

Kotlin mempermudah kita dalam Android Developing dengan membuat method-method yang bisa menghindarkan kita dari Error yang menghambat proses developing. jangan lupa mengupdate terus versi kotlin kalian agar bisa menampilkan warning jika ada method yang tidak efesien lagi untuk digunakan.

Published by Ahmad Saifur Ridlo

Android Developer at Algostudio.net

Leave a Reply

Your email address will not be published. Required fields are marked *