[Android]Hướng dẫn tạo và sử dụng event bus đơn giản với RxJava

Khi thực hiện xây dựng một ứng dụng, việc truyền và tiếp nhận các sự kiện cũng như các object giữa các activity, fragment, service… luôn là điều cần thiết. Có nhiều cách để thực hiện, thông thường sẽ dùng intent hoặc có thể dùng thư viện EventBus. Trong bài viết này mình sẽ hướng

Khi thực hiện xây dựng một ứng dụng, việc truyền và tiếp nhận các sự kiện cũng như các object giữa các activity, fragment, service… luôn là điều cần thiết. Có nhiều cách để thực hiện, thông thường sẽ dùng intent hoặc có thể dùng thư viện EventBus.

Trong bài viết này mình sẽ hướng dẫn tạo và sử dụng event bus đơn giản hiệu quả hơn với Subject trong RxJava bằng ngôn ngữ kotlin.

Trước tiên mình cùng nhắc lại kiến thức cơ bản về Subject trong RxJava.

1. Định nghĩa về Subject trong RxJava:

Theo trang Reactive, Subject được định nghĩa như sau:

A Subject is a sort of bridge or proxy that is available in some implementations of ReactiveX that acts both as an observer and as an Observable. Because it is an observer, it can subscribe to one or more Observables, and because it is an Observable, it can pass through the items it observes by reemitting them, and it can also emit new items.

Có thể hiểu như sau:

Subject là 1 đối tượng trong RxJava, là 1 loại cầu nối có sẵn trong RX. Subject hoạt động như Observable và Observer, nên có sức mạnh của cả 2. Nó như là một observer nên có thể đăng kí một hoặc nhiều Observable. Cũng là một Observable nên nó có thể bắn ra các item mới cho Observer.
Có 4 loại Subject là: AsyncSubject, BehaviorSubject, ReplaySubject và PublishSubject

AsyncSubject

QJ4bjf.md.png

Một AsyncSubject chỉ phát ra value cuối cùng và chỉ khi nguồn observable hoàn tất.

BehaviorSubject

QJ4pma.md.png

Khi có một observer đăng kí BehaviorSubject thì nó sẽ bắt đầu phát ra item được phát gần đây nhất.

ReplaySubject

T6HhHD.md.png

ReplaySubject sẽ phát ra tất cả item mà nó có cho bất kì observer nào đăng kí nó.

PublishSubject

T2nArP.md.png

PublishSubject sẽ phát ra item cho các observer nào đã đăng kí nó tại thời điểm đó.

Đây là loại subject rõ ràng nhất. Chúng ta sẽ dùng publishSubject để tạo event bus. Cùng đi vào phần chính của bài viết.

2. Tạo và sử dụng Event Bus:

Bước 1: Tạo Event Bus:

Trước tiên bạn cần implement thư viện RxJava vào build.gradle(app):

implementation 'io.reactivex.rxjava3:rxjava:3.0.0'

Tạo Event bus sử dụng câu lệnh sau:

val eventBus:PublishSubject<T> by lazy {PublishSubject.create()}

Trong đó:

  • PublishSubject<T>: T là kiểu dữ liệu bạn muốn phát đi.

Để dễ dàng trong việc xử lí event mình sẽ dùng kiểu dữ liệu HashMap<String, Any>. Tương ứng như sau: String: mô tả tên event, Any: là kiểu dữ liệu được phát ra với event tương ứng.

Nhằm phục vụ gửi và lắng nghe sự kiện cho toàn ứng dụng mình sẽ khai báo biến eventBus tại class App như sau:

classApp:Application(){
  companion object {
      val eventBus:PublishSubject<HashMap<String,Any>> by lazy {PublishSubject.create()}}}

Bước 2: Gửi sự kiện:

Thực hiện phát các event bằng câu lệnh sau:

  eventBus.onNext(data)

Hãy định nghĩa một object Event, tại đây chứa các const là tên các event trong ứng dụng và các fun dùng để gửi sự kiện. Điều này giúp bạn có thể dễ dàng quản lí và nắm bắt tất cả các sự kiện trong ứng dụng.

Ví dụ: Giả sử ứng dụng của bạn có 2 sự kiện cần được phát đi là:

  • Sự kiện 1: Thông báo người dùng đã cập nhật email thành công với data là tên email mới
  • Sự kiện 2: Thông báo muốn finish chat activity
object Event{// định nghĩa các Event trong ứng dụngconst val EVENT_UPDATED_EMAIL_SUCCESS ="UPDATED_EMAIL_SUCCESS"const val EVENT_FINISH_CHAT ="FINISH_CHAT"// Thực hiện phát các sự kiện
    fun updatedEmailSuccess(newEmail:String){// Lệnh phát sự kiện với data là newEmailApp.eventBus.onNext(hashMapOf(EVENT_UPDATED_EMAIL_SUCCESS tonewEmail))}
    fun finishChatActivity(){// Lệnh phát sự kiện không có dataApp.eventBus.onNext(hashMapOf(EVENT_FINISH_CHAT to""))}}

Tại activity bạn mong muốn phát ra sự kiện bạn chỉ cần gọi fun phát event tương ứng. Trong trường hợp này, sau khi người dùng thực hiện cập nhật email thành công bạn muốn phát event, thực hiện lệnh sau:

Event.updatedEmailSuccess("[email protected]")

Bước 3: Đăng kí lắng nghe sự kiện:

Thực hiện đăng kí để lắng nghe sự kiện bằng lệnh sau:

  eventBus.subscribe{//tiếp nhận sự kiện}

Theo kiến thức ta nắm được ở phần 1, hoạt động của PublishSubject là chỉ phát ra item cho các observer đã đăng kí nó tại thời điểm đó. Do đó, ở mỗi activity hoặc fragment ta nên đăng kí lắng nghe eventBus ở hàm onCreate để có thể lắng nghe ngay tại thời điểm phát của tất cả các sự kiện của ứng dụng trong thời gian hoạt động của activity hoặc fragment, sau đó dựa theo key event để có thể tiếp nhận nhưng event mong muốn, ta thực hiện như sau:
Theo ví dụ trên ứng dụng có 2 sự kiện, bây giờ ta sẽ thực hiện xử lí sự kiện người dùng cập nhật thành công email tại InfoUserActivity và xử lí xự kiện finish chat tại ChatActivity.

  • Tại fun onCreate của InfoUserActivity:
App.eventBus.subscribe{
          it[Event.EVENT_UPDATED_EMAIL_SUCCESS]?.let { data ->(it as String?)?.let { newEmail ->//thực hiện update text hiển thị thông tin email của người dùng
              tvEmail.text = newEmail
             }}}
  • Tại fun onCreate của ChatActivity:
App.eventBus.subscribe{
          it[Event.EVENT_FINISH_CHAT]?.let {//thực hiện finish activityfinish()}}

Ngoài ra để tiện sử dụng và giảm việc lặp code đăng kí lắng nghe sự kiện giữa các activity hoặc fragment. Thông thường, mình sẽ thực hiện đăng kí lắng nghe sự kiện tại BaseActivity hoặc BaseFragment(thực hiện tương tự như trên), sau đó override fun đó tại các Activity hoặc Fragment mong muốn.

Bước 4: Huỷ đăng kí.

Khi thiết lập đăng kí lắng nghe sự kiện sẽ trả về một Disposable, ta chỉ cần dispose nó ở fun onDestroy của activity hoặc fragment, thực hiện huỷ đăng kí như sau:

classChatActivity:AppCompatActivity(){
    lateinit var viewBiding:ActivityChatBinding//khai báo disposableprivatevar disposable:Disposable?=null
    override fun onCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)
        viewBiding =ActivityMainBinding.inflate(layoutInflater)setContentView(viewBiding.root)// thực hiện đăng kí lắng nghe sự kiện
        disposable =App.eventBus.subscribe {
            it[Event.EVENT_FINISH_CHAT]?.let {//thực hiện finish activityfinish()}}}

    override fun onDestroy(){super.onDestroy()//huỷ đăng kí
        disposable?.dispose()}}

Lưu ý: Nếu bạn thực hiện đăng kí tại BaseActivity hoặc BaseFragment thì thực hiện huỷ đăng kí tương tự tại fun onDestroy của BaseActivity hoặc BaseFragment nhé.

Tổng kết:

Trên đây mình đã nêu ra đầy đủ và chi tiết các bước để tạo và sử dụng event bus thông qua PublishSubject. Bài viết này viết chủ yếu dựa trên kinh nghiệm làm việc qua các dự án của bản thân mình. Hi vọng giúp ích cho mọi người. Cùng ứng dụng và trải nghiệm sự đơn giản, tiện lợi này.

Trong bài này có tham khảo:
http://reactivex.io/documentation/subject.html

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ