Mẹo viết code Kotlin cho Android developer không nên bỏ qua

0
Dịch vụ dạy kèm gia sư lập trình
Bài này thuộc phần 5 của 5 phần trong series Kotlin Android cơ bản

Kotlin hiện đã trở thành ngôn ngữ chính để lập trình ứng dụng Android, bên cạnh Java đã có phần già nua. Khi mới chuyển sang sử dụng Kotlin, chắc chắn bạn sẽ có đôi chút bỡ ngỡ. Nhưng mình đảm bảo, càng về sau, bạn càng cảm thấy khoái “anh chàng” Kotlin này.

Bài viết này, mình sẽ chia sẻ một số kinh nghiệm, kotlin tips trick để bạn viết code nhàn hơn, gọn gàng và nhanh hơn.

Cài đặt Kotlin

Hiện nay, bản Android Studio mới nhất đã tích hợp sẵn Kotlin, nên bạn không cần phải cài đặt thêm gì cả.

Mình chỉ lưu ý một vài điểm ch dự án của bạn.

Một là, để tạo mới một kotlin class, bạn chọn:

  • File > New > Kotlin file/class
  • Hoặc File > New > Kotlin activity

Phần đuôi mở rộng của các tệp kotlin là .kt

Hai là, Android Studio có một plugin hỗ trợ viết mã Kotlin rất tốt, bạn nên sử dụng nó cho dự án của mình. Mở build.gradle (module level), thêm dòng sau:

apply plugin: 'kotlin-android-extensions'

Nếu bạn tạo dự án Kotlin từ đầu bằng Android Studio thì chắc chắn trong build.gradle (application level) sẽ có đoạn code kiểu như sau:

buildscript {
   ext.kotlin_version = '1.0.2'
   repositories {
       jcenter()
   }
   dependencies {
       classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

       // NOTE: Do not place your application dependencies here; they belong
       // in the individual module build.gradle files
   }
}

Ok, việc thiết lập để dự án sử dụng được Kotlin chỉ có vậy thôi. Ngoài ra, bạn có thể tham khảo các bài viết làm quen với Kotlin cùng VNTALKING tại đây:

Kotlin tips hay không nên bỏ qua

Dưới đây là một số thủ thuật/tính năng của Kotlin mà cá nhân mình thấy nó khá hay ho, đặc biệt là so với cách viết của Java.

1. Tính năng Static Layout Import

Trước đây, khi viết ứng dụng Android, không ai là không biết tới từ khóa: findViewById() để tạo một reference từ code Java tới View trong layout XML. Nhiều khi, với layout có nhiều View cần phải reference, bạn nhìn code khai báo findViewById() rất rất là nhiều.

Cũng có một số giải pháp khắc phục điều này, như sử dụng thư viện Butterknife, giúp tiết kiện thao tác khai báo đó. Đến Kotlin, nó còn cải tiến thêm một bước nữa, bằng cách cho phép import tất cả reference tới View chỉ bằng một lần import.

Chúng ta cùng ví dụ minh họa dưới đây:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="co.ikust.kotlintest.MainActivity">

    <TextView
        android:id="@+id/helloWorldTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</RelativeLayout>

Còn đây là đoạn mã trong Activity:

import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        helloWorldTextView.text = "Hello World!"
    }
}
Kotlin cũng giống như Javascript, không cần thiết phải có dấu chấm phẩy ( ; ) cuối mỗi dòng lệnh.

Như bạn thấy, chúng ta không cần phải khai báo findViewById() gì hết, truy xuất thằng vào view thông qua ID của nó.

helloWorldTextView.text = "Hello World!"

Góc chú ý:

  • Trong hàm setContentView(R.layout.activity_main) phải trỏ tới đúng layout nhé. Tránh hiện tượng “râu ông này cắm cằm bà kia“. Nếu bạn trỏ nhầm layout, tất nhiên là bạn gọi reference từ ID của View sẽ bị NULL, ứng dụng sẽ bị crash.
  • Riêng với Fragment, bạn nên khai báo setContentView() trong hàm onCreateView(), sử dụng các reference để thiết lập UI trong onViewCreated().

2. Viết POJO class trong Kotlin

So với tính năng static layout import, việc viết POJO (Plain Old Java Object) class bằng Kotlin còn ngắn gọn hơn nữa (so với Java).

Viết POJO class để làm gì? POJO class thực chất là các data class, mục đích để bạn định nghĩa dữ liệu kiểu Object, dùng để lưu dữ liệu vào DB, parse JSON…

Ví dụ, chúng ta có một JAVA class như sau:

public class User {
   private String firstName;
  
   private String lastName;

   public String getFirstName() {
       return firstName;
   }

   public void setFirstName(String firstName) {
       this.firstName = firstName;
   }

   public String getLastName() {
       return lastName;
   }

   public void setLastName(String lastName) {
       this.lastName = lastName;
   }
}

Với Kotlin, mã nguồn sẽ ngắn gọn hơn rất nhiều.

  • Đầu tiên là bạn không cần phải viết từ khóa public, vì mặc định mọi thứ trong kotlin là public rồi.
  • Không cần phải viết hàm get/set. Trong Kotlin, bạn truy xuất trực tiếp vào properties.

Do đó, với đoạn code Java trên, khi chuyển thành Kotlin thì chỉ còn như sau:

class User {
   var firstName: String? = null

   var lastName: String? = null
}

Ngắn gọn mà vẫn dễ hiểu phải không!?

Còn rất nhiều điều hay ho khi bạn viết và khai báo POJO class, mời bạn đọc thêm chi tiết tại bài viết này: Khởi tạo Class trong Kotlin đơn giản và hiệu quả

3. Lambda Expressions

Lambda expressions là một tính năng được giới thiệu trong bản JAVA 8, được rất nhiều người ưu thích. Tuy nhiên, trên Android thì cũng mới chỉ hỗ trợ java 7, không biết bây giờ thì thế này. Điều đó đã khiến các lập trình viên đi tìm giải pháp thay thế, có thể kể tới Retrolambda

Nhưng nếu bạn sử dụng Kotlin thì lại đơn giản, bạn được hỗ trợ sẵn rồi, không cần cài gì thêm cả.

Về phần này, mình đã có một bài viết riêng để giải thích và hướng dẫn làm rất chi tiết, đừng bỏ qua nhé: Tìm hiểu Higher-Order Functions và Lambda trong Kotlin

4. Null-safety

Một trong những thứ khiến bạn ám ảnh và đau đầu nhất trong Java, đó chính là lỗi NullPointerException. Khi chuyển sang Kotlin, với tính năng Null-safety, cơn đau đầu đó sẽ chấm dứt.

Với Kotlin, chỉ duy nhất những lỗi sau mới gây ra NullPointerException:

  • Bạn cố tình throw ra NullPointerException
  • Sử dụng toán tử !! (sẽ đề cập ở phần dưới bài viết)
  • Nếu thuộc tính lateinit được truy xuất trong hàm khởi tạo trước khi nó được tạo. Lúc này bạn sẽ gặp lỗi anUninitializedPropertyAccessException

Theo mặc định, tất cả các biến, thuộc tính của Object đều là non-null (không thể giữ giá trị null)  – Trừ khi chúng được khai báo là nullable.

Như đề cập ở trên, để khai báo một biến có thể null, bạn chỉ cần thêm dấu hỏi chấm vào sau kiểu dữ liệu. Ví dụ:

val number: Int? = null

Khi đã khai báo như trên mà bạn lại cố tình gọi hàm để tạo NullPointerException như này:

val number: Int? = null
number.toString()

Đoạn code sẽ không được complie vì không vượt qua được null check của chương trình. Nhưng nếu bạn thêm điều kiện check null thì lại OK

val number: Int? = null

if(number != null) {
    number.toString();
}

Hoặc viết gọn hơn:

val number: Int? = null
number?.toString()

Toán tử !!

Đôi khi, bạn muốn chương trình có thể bắn ra NullPointerException như JAVA để khi test gặp lỗi mà biết mà sửa. Bạn có thể sử dụng toán tử !!

Đoạn code này sẽ bắn ra NullPointerException:

val number: Int? = null
number!!.toString()

Thuộc tính lateinit

Có một trường hợp khi sử dụng thuộc tính lateinit mà có thể gây lỗi tương tự NullPointerException.

Chúng ta cùng xem xét ví dụ sau:

class InitTest {
    lateinit var s: String;

    init {
        val len = this.s.length
    }

}

Đoạn code khi compile sẽ không vấn đề gì cả. Nhưng khi chạy chương trình, ngay khi instance của đối tượng TestClass được, bạn sẽ gặp lỗi UninitializedPropertyAccessException.

Nguyên nhân như mình đã đề cập ở trên, do bạn truy xuất vào thuộc tính s trước khi nó được khởi tạo.

5. Hàm with()

Hàm with() rất hữu ích khi bạn cần truy xuất vào nhiều thuộc tính của cùng một đối tượng. Nó giúp bạn đỡ phải gõ nhiều tên đối tượng để gọi thuộc tính.

with(helloWorldTextView) {
    text = "Hello World!"
    visibility = View.VISIBLE
}

6. Chuyển một Object sang Map

Có một use case phổ biến đó là lưu trữ giá trị của các thuộc tính vào một mảng Map. Điều này bạn thường thấy với các ứng dụng làm việc với RESTful API khi cần parse JSON.

Sau đây là một ví dụ:

class User(val map: Map<String, Any?>) {
    val name: String by map
    val age: Int     by map
}

Khi sử dụng như sau:

val user = User(mapOf(
    "name" to "John Doe",
    "age"  to 25
))

7. Collections và Functional Operations

Với sự hỗ trợ của lambdas, các thao tác với Collection trong Kotlin được nâng lên tầm cao mới.

Đầu tiên, Kotlin có sự phân biệt giữa mutable collection và immutable  collection.

Ví dụ: Có hai phiên bản của Iterable interface

  • Iterable
  • MutableIterable

Tương tự, cũng có hai phiên bản của List, Set và Map interfaces.

Ví dụ: toán tử any sẽ trả về giá trị true nếu có ít nhất một phần tử thỏa mãn điều kiện.

val list = listOf(1, 2, 3, 4, 5, 6)
assertTrue(list.any { it % 2 == 0 })

Và còn rất nhiều tính năng khác nữa, các bạn có thể tham khảo thêm trong trang tài lệu chính thức của Kotlin.

Tạm kết

Trên đây chỉ là một số Kotlin tips, những tính năng hay ho mà Kotlin cung cấp. Nếu bạn càng làm việc nhiều với Kotlin, chắc chắn bạn sẽ ngày càng thêm yêu ngôn ngữ này.

Mình hi vọng bài viết này sẽ giúp ích cho các bạn trong dự án sắp tới.

Nguồn tham khảo: toptal

Xem tiếp các bài trong Series
Phần trước: Sử dụng Volley library Android để thao tác với Network API
Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng
Bài trướcLàm thế nào ghép (concat) mảng trong Javascript?
Bài tiếp theoKhái niệm Hoisting Javascript là gì? Tại sao lại cần chú ý!
Tên đầy đủ là Dương Anh Sơn. Tốt nghiệp ĐH Bách Khoa Hà Nội. Mình bắt đầu nghiệp coder khi mà ra trường chẳng xin được việc đúng chuyên ngành. Mình tin rằng chỉ có chia sẻ kiến thức mới là cách học tập nhanh nhất. Các bạn góp ý bài viết của mình bằng cách comment bên dưới nhé !

Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Thông báo