KTX’in nimetlerinden faydalanalım

Merhaba arkadaşlar,
Bu yazımda projelerde kullanmayı çok sevdiğim, developer dostu Kotlin extension functions’dan (KTX) bahsedeceğim. Kolay okunabilir kod yazmaya önem veriyorsanız ve daha önce kullanmadıysanız eminim siz de çok seveceksiniz.
Extensions aslında yeni bir teknoloji ya da Kotlin diline özgü yazılan yepyeni bir özellik değil. Temelde Java dilinde yazılan API ların işlevselliğini genişleten bir kütüphane diyebiliriz. İşin güzel tarafı extensionları kendi oluşturduğumuz API içerisinde uygulayabildiğimiz gibi kullandığımız herhangi bir third party library’e de uygulayabiliyoruz. (Aşağıda bahsettiğim Glide örneğinde olduğu gibi)
Kod örnekleri üzerinden extension kullanırsak kodumuz nasıl görünürü inceleyelim.

Projemizde konum bilgisi isteyeceğimiz bir activity olsun. İlk olarak permission check yapmamız gerekiyor ve aşağıdaki gibi bir kod kullanıyoruz.
val hasPermission = ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
if (!hasPermission) {
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 0)
}
Peki şöyle bir extension function olsa elimizde.. Bu kodu hem daha kısa bir kod parçacığına dönüştürsek, hem de sadece ilgili activity’de değil istediğimiz her yerde çağırabilsek? Hatta her projemize dahil edebileceğimiz bir common library oluşturup (bakınız gitsubmodule) extension olarak bu library’e eklesek?
fun Activity.hasPermission(permission: String): Boolean {
return ActivityCompat.checkSelfPermission(
this,
permission
) == PackageManager.PERMISSION_GRANTED
}
Ve activity’mize gidip permission check için aşağıdaki kodu kullansak ;)
if (!hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
// request permission
}
Göze daha sade ve kolay okunabilir geliyor değil mi?
Activityimize bir textView ekleyelim ve aldığımız konumu formatlayarak textViewde gösterelim.
fun Activity.findAndSetText(@IdRes id: Int, text: String) {
findViewById<TextView>(id).text = text
}
fun Activity.showLocation(@IdRes id: Int, location: Location?) {
if (location != null) {
findAndSetText(id, location.asString(Location.FORMAT_DEGREES))
} else {
findAndSetText(id, "Location unknown")
}
}
fun Location.asString(format: Int = Location.FORMAT_DEGREES): String {
val latitude = Location.convert(latitude, format)
val longitude = Location.convert(longitude, format)
return "current latitude : $latitude - current longitude : $longitude"
}
Uygulamamızda web servisten gelen url bilgisine göre imajları göstermek için Glide kütüphanesini kullandığımızı varsayalım. Aşağıdaki fonksiyonu uygulama genelinde ihtiyaç duyulan yerlerde çağırabiliriz.
fun ImageView.downloadFromUrl(url: String?, progressDrawable: CircularProgressDrawable){
val options = RequestOptions()
.placeholder(progressDrawable)
.error(R.mipmap.ic_launcher_round)
Glide.with(context)
.setDefaultRequestOptions(options)
.load(url)
.into(this)
}fun placeholderProgressDrawable(context: Context) : CircularProgressDrawable {
return CircularProgressDrawable(context).apply {
strokeWidth = 4f
centerRadius = 20f
start()
}
}fun downloadImage(view: ImageView, url:String?) {
view.downloadFromUrl(url, placeholderProgressDrawable(view.context))
}
Ya da ürünü sepete eklerken şöyle bir extension property kullansak güzel olmaz mı?
internal val Product.sendToBasket: Basket
get() = Basket(
this.productId, this.productName, 1, this.productPrice
)
Regular expression için de extension function kullansak hiç fena olmaz.
fun String.isEmailValid(): Boolean {
return !TextUtils.isEmpty(this) && android.util.Patterns.EMAIL_ADDRESS.matcher(this).matches()
}
Örnekler çoğaltılabilir. Ktx gereksiz kod tekrarını önlemek ve Open/Closed Prensibine sadık kalarak kod yazmak için oldukça güzel bir kütüphane. Ne demişler? Don’t Repeat Yourself!