Tìm hiểu Dagger 2 trong Android – Bắt đầu từ cơ bản

9
Dịch vụ dạy kèm gia sư lập trình

Trong bài viết về kiến trúc MVP trong Android, mình đã từng giới thiệu thư viện Dragger2, một thư viện Dependency Injection mạnh mẽ và hữu ích dành cho phát triển Android. Bài viết này mình sẽ chia sẻ cách sử dụng Dagger 2 trong Android, rất rất cơ bản để các bạn mới cũng có thể hiểu và áp dụng được.

Trước đây khi mình mới học lập trình, mình cũng bắt đầu tìm hiểu về quy tắc viết clean code SOLID. Thực sự nó làm mình tẩu hỏa nhập ma với hàng loạt khái niệm như: Dependency Injection, Provider, Component, Module, Scope

Do vậy, mình đã tự hứa với bản thân rằng khi nào mình đã hiểu rõ về quy tắc này thì lập tức phải làm ngay một bài viết để chia sẻ lại cho mọi người (cũng vừa giúp mình ghi nhớ lại).

Và đây là một phần trong kế hoạch đó, một bài viết về Dagger 2, một thư viện hỗ trợ bạn thực hiện nguyên tắc Dependency Injection( một phần trong triết lý SOLID).

Note: Bài viết tìm hiểu Dagger này chỉ dành cho các bạn mới học lập trình thôi nhé! Hay những ai đang bắt đầu tiếp cận với nguyên tắc viết code clean SOLID. Những khái niệm, cách tiếp cận trong bài viết này rất cơ bản, những kiến thức tối thiểu cần phải biết để trở thành developer chuyên nghiệp. Mình xin lỗi các bậc tiền bối nếu có múa rìu qua mắt thợ nhé!
Tìm hiểu dagger Dagger 2 trong Android cho người mới
Tìm hiểu dagger Dagger 2 trong Android

Tìm hiểu Dagger 2 trong Android

#Khởi tạo dự án Android

Trước khi bạn bắt đầu đọc bài viết này, bạn đã biết đến các khái niệm như Function, Class và Member Variables rồi đúng không?

Và bạn cũng biết cách tạo một dự án trong Android Studio rồi chứ? Thậm chí Android Studio bây giờ còn hỗ trợ tạo dự án với những tính năng cơ bản mà bạn không cần phải nhúng tay code.

Tuy nhiên, để tiện theo dõi, chúng ta sẽ tạo một dự án với một Empty Activity. Sau đó thêm một TextView.

Và đây là code của MainActivity:

class MainActivity : AppCompatActivity() {

    val info = Info()

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

        text_view.text = info.text

    }
}

class Info  {
    val text = "Hello Dagger 2"
}

#Chuyển Class Info ra khỏi Activity…

Trong các dự án thực tế, mình không chỉ có mỗi một biến info như thế kia. Ngoài ra, thông tin Info mình còn muốn chia sẻ giữa các Activity với nhau nữa.

Nếu chúng ta khởi tạo Info trong MainActivity sẽ làm cho code không được clean. Việc kế thừa code sẽ trở nên khó khăn hơn.

Do đó, thay vì chúng ta tạo một class Info trong MainActivity. Mình muốn thông tin ( và các biến thành viên khác nữa) được tạo ở một nơi khác.

Bạn có biết hành động này gọi là gì không? Đó chính là Dependencies Injection.

Hướng dẫn sử dụng Dagger 2 trong Android cho người mới

Lúc này code của chúng ta thay vì khỏi tạo và định nghĩa Info bên trong MainActivity. Chúng ta sẽ truyền Info vào.

class MainActivity(val info:Info) : AppCompatActivity()

Ồ! Có gì đó sai sai trong đoạn code trên. Dường như Android không cho phép truyền tham số vào MainActivity. Vậy phải làm sao đây?

Nếu bạn có kinh nghiệm lập trình Android thì bạn sẽ nghĩ đến class Application. Chúng ta sẽ truyền tham số cho MainActivity từ class Application. Tuy nhiên, ở đây chúng ta không làm thế, chúng ta sẽ sử dụng Dagger2.

🔥 Rất có ích cho bạn: Quy tắc viết Code Clean trong Android

#Ứng dụng của Dagger 2 trong Android

Với Dagger2, giờ đây chúng ta có thể làm cho Info xuất hiện một cách kì diệu.

Đầu tiên, chúng ta sẽ loại bỏ được đoạn code khai báo khởi tạo class Info: val info = Info();

Ngoài Dagger 2 có thể làm được điều này, thì chỉ có David Copperfield mới làm được 🙂

Thực ra, chúng ta vẫn phải truyền Info vào MainActivity nhưng không phải thông qua việc dùng hàm khởi tạo như trên.

Tạm thời, code sẽ như sau:

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

        text_view.text = info.text

    }
}

class Info  {
    val text = "Hello Dagger 2"
}

Từ khóa lateinit là khởi tạo sau.  Chúng ta không muốn info là NULL, nó phải được khởi tạo và có giá trị.

Lưu ý: Đoạn code trên vẫn chưa chạy được. Nếu bạn thử chạy sẽ gặp lỗi CRASH vì đối tượng Info chưa được khởi tạo mà bạn lại gọi info.text

Đừng lo lắng, chúng ta sẽ thực sự bắt đầu với Dagger 2, xem nó khởi tạo Info như nào nhé!

#Thêm thư viện Dagger 2 trong Android Studio

Cũng giống như bất kì thư viện nào khác, bạn khai báo dagger 2 trong mục dependencies  như sau:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    // ... other dependencies ...
    implementation 'com.google.dagger:dagger:2.13'
    kapt 'com.google.dagger:dagger-compiler:2.13'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

Sau đó nhớ Sync lại dự án.

#Giới thiệu đôi chút về @ Component

Theo định nghĩa chính thức thì @component là 1 interface dùng để làm cầu nối giữa module và injection.

Trong bài viết này, mình muốn tạo một component mà cho phép mình tạo các biến info thành viên.

@Component
interface MagicBox {
    fun poke(app: MainActivity)
}

Để mình giải thích cho rõ ràng hơn chút. Bạn có thể tưởng tượng rằng MagicBox sẽ được sử dụng để poke MainActivity như hình minh họa bên dưới và cung cấp Info cho MainActivity.

Hướng dẫn sử dụng Dagger 2 trong Android cho người mới

Việc của chúng ta là đưa Info vào MagicBox, còn lại hãy để Dagger2 lo.

Mình tin rằng sẽ có nhiều bạn thắc mắc: Tại sao cứ cố tạo MagicBox với Dagger2 chi cho mệt, thay vì tạo luôn Info trực tiếp trong MainActivity như ban đầu ấy, có sao đâu?

Giả sử, chúng ta có rất nhiều member variable khác (ngoài biến info ra). Và nhiều Class hay Activity khác cũng cần đến chúng. Thế lúc đó các class đó cũng sẽ phải tự tạo các member variables tương tự của riêng mình.

Duplicate code là đây chứ đâu!

Tìm hiểu Dagger 2 trong Android cho người mới

Bạn đã hiểu vai trò của MagicBox chưa!?

🔥 Đọc thêm: Chia sẻ mã nguồn Flashlight 3D Android giá 69$

#Đưa Info vào @Component…Giới thiệu @Inject

Okay, giờ chúng ta sẽ đưa Info vào @Component…

Mình đoán là một số bạn sẽ nghĩ nếu chúng ta tự đưa Info vào @Component thì @Component có gì đặc biệt đâu. Chúng ta cũng có thể tạo một class bình thường để làm điều đó mà.

Thực tế thì chúng ta không cần phải truyền Info vào MagicBox. Chúng ta chỉ cần thêm một annotation vào ngay trước class Info. Sau đó Dagger 2 sẽ tự biết phải làm gì.

Và annotation đó chính là @Inject.

class Info @Inject constructor() {
    val text = "Hello Dagger 2"
}

Bạn có thể thêm @Inject vào bất cứ class/Object nào bạn muốn. Dagger2 sẽ kết nối class đó tới MagicBox.

#Xây dựng MagicBox

Có một điều đặc biệt là MagicBox được khai báo là một Interface. Về nguyên tắc, để sử dụng Interface, chúng ta cần phải implement nó.

Tuy nhiên, ai sẽ implement Interface? MainActivity chăng?

Không phải. Với Dagger2 trong Android, khi bạn đã khai báo MagicBox với annotation @Component, bạn chỉ cần gọi hàm trong MagicBox thông qua static class với tên là: DaggerMagicBox.

Kiểu như sau:

DaggerMagicBox.create().poke()

Tuy nhiên, chương trình vẫn CRASH!!!

Bởi vì dagger 2 trong android không được tạo bất kì biến thành viên (member variables) nào khi chưa được phép.

Vì vây, để thông báo cho Dagger 2 biết biến nào được phép tạo bằng cách thêm annotation @Inject vào trước biến đó là được.

@Inject lateinit var info: Info

Code hoàn chỉnh sẽ như sau:

class MainActivity : AppCompatActivity() {

    @Inject lateinit var info: Info

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        DaggerMagicBox.create().poke(this)
        text_view.text = info.text
    }
}

class Info @Inject constructor() {
    val text = "Hello Dagger 2"
}

@Component
interface MagicBox {
    fun poke(app: MainActivity)
}

Nói thì dông dài nhưng code thì có tý tẹo thôi ah.

#Tạm kết

Như vậy mình đã hướng dẫn các bạn tìm hiểu Dagger cùng với cách Dependency Injection với Dagger2 trong Android.

Các bạn có thể download toàn bộ code của bài viết tại đây:

Nếu bài viết có chỗ nào khó hiểu thì để lại bình luận để mọi người cùng hỗ trợ nhé!

Cám ơn bạn đã theo dõi!

Đọc thêm:

Nguồn: Medium

Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng
Bài trướcXử lý JSON trong Android- Cách làm không thể dễ hơn
Bài tiếp theoTải và cài đặt JDK (Java Development Kit) từng bước chi tiết
Sơn Dương
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é !

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

avatar
  Theo dõi bình luận  
Mới nhất Cũ nhất Nhiều voted nhất
Thông báo
cuong
Guest
cuong

Bạn có code thuần java cho bài này không ạ

cuong
Guest
cuong

Chào bạn,
Cho mình hỏi nếu mình dùng Java thì “lateinit var Info” mình có thể thay bằng lệnh gì tương ứng nhỉ.
Mình cảm ơn

constant
Guest
constant

đây là bài dịch mà, đã từng đọc bài này bằng tiếng Anh

Tiến
Guest
Tiến

Thank bạn!
Bài viết của bạn rất hay!

Tâm
Guest
Tâm

Bạn có thể viết thêm một vài bài về Dagger 2 nửa không ạ !
Xin cám ơn nhiều !