Mở đầu
Tôi thích dùng realm trong dự án vì tốc độ và tính linh hoạt khi lắng nghe sự thay đổi dữ liệu từ database,
Thế nhưng điều đó không còn khi tôi làm việc với một dự án xây dựng theo mô hình clean architecture bởi tính độc lập giữa các tầng trong dự án.
Cách
Có cách nào không? có chứ và có nhiều, chúng ta cùng thử liệt kê nhé:
Realm + Broadcast Receiver —> quá tốn tài nguyên, cần phải viết hàm đăng ký lắng nghe và hủy đăng ký của Broadcast Receiver
Realm + Live Data —> hay, nhưng live data là của android mà tầng nghiệp vụ (Domain) thì không nên chứa android trong đó
Realm + Rx —> hay, nhưng yêu cầu toàn bộ luồng xử lý sẽ phải xử lý trong luồng main thread (ảnh hưởng đến UI)
Vậy còn cách nào nữa không nhỉ, tôi đã rất tuyệt vọng cho đến khi Flow trong Coroutines xuất hiện tính linh hoạt trong đa luồng đã thu hút tôi tìm hiểm
thật tuyệt khi tôi đã tìm ra giải pháp cho nó =)), giờ thì cùng thử code nào
Code
Code Base
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <span class="token annotation builtin">@OptIn</span><span class="token punctuation">(</span>ExperimentalCoroutinesApi<span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span> <span class="token keyword">fun</span> <span class="token operator"><</span>S <span class="token operator">:</span> RealmObject<span class="token punctuation">,</span> R<span class="token operator">></span> <span class="token function">handlerAndReturnListFlow</span><span class="token punctuation">(</span>block<span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-></span> RealmQuery<span class="token operator"><</span>S<span class="token operator">></span><span class="token punctuation">)</span><span class="token operator">:</span> Flow<span class="token operator"><</span>List<span class="token operator"><</span>R<span class="token operator">></span><span class="token operator">></span> <span class="token operator">=</span> callbackFlow <span class="token punctuation">{</span> <span class="token keyword">val</span> results <span class="token operator">=</span> <span class="token function">block</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">findAllAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">!!</span> <span class="token keyword">val</span> realm <span class="token operator">=</span> results<span class="token punctuation">.</span>realm<span class="token operator">!!</span> <span class="token keyword">val</span> listener <span class="token operator">=</span> RealmChangeListener<span class="token operator"><</span>RealmResults<span class="token operator"><</span>S<span class="token operator">></span><span class="token operator">></span> <span class="token punctuation">{</span> t <span class="token operator">-></span> <span class="token function">offer</span><span class="token punctuation">(</span>realm<span class="token punctuation">.</span><span class="token function">copyFromRealm</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> results<span class="token punctuation">.</span><span class="token function">addChangeListener</span><span class="token punctuation">(</span>listener<span class="token punctuation">)</span> <span class="token function">offer</span><span class="token punctuation">(</span>realm<span class="token punctuation">.</span><span class="token function">copyFromRealm</span><span class="token punctuation">(</span>results<span class="token punctuation">)</span><span class="token punctuation">)</span> awaitClose <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>realm<span class="token punctuation">.</span>isClosed<span class="token punctuation">)</span> <span class="token punctuation">{</span> results<span class="token punctuation">.</span><span class="token function">removeChangeListener</span><span class="token punctuation">(</span>listener<span class="token punctuation">)</span> realm<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">flowOn</span><span class="token punctuation">(</span>Dispatchers<span class="token punctuation">.</span>Main<span class="token punctuation">)</span> <span class="token comment">// đẩy bộ lắng nghe thay đổi dữ liệu vào trong luồng main để tận dụng cơ chế looper của main</span> <span class="token comment">/*.flowOn(android.os.Handler(HandlerThread("RealmDb").apply { start() }.looper).asCoroutineDispatcher("db"))*/</span> <span class="token comment">// đẩy bộ lắng nghe thay đổi dữ liệu vào trong luồng background, nhưng hãy chắc chắn rằng bạn quản lý tốt về thread</span> <span class="token punctuation">.</span><span class="token function">map</span> <span class="token punctuation">{</span> <span class="token comment">// chuyển đổi entity database S sang entity R</span> <span class="token punctuation">}</span> |
Code in Database
1 2 3 4 | <span class="token keyword">fun</span> <span class="token function">getAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> handlerAndReturnListFlow <span class="token punctuation">{</span> Realm<span class="token punctuation">.</span><span class="token function">getDefaultInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">where</span><span class="token punctuation">(</span>TestObject<span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">.</span>java<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Code in Repository
1 2 | <span class="token keyword">fun</span> <span class="token function">getAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> testDb<span class="token punctuation">.</span><span class="token function">getAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span> |
Code in UseCase
1 2 | <span class="token keyword">fun</span> <span class="token function">execute</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span> testRepository<span class="token punctuation">.</span><span class="token function">getAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span> |
Code in ViewModel
1 2 3 | <span class="token keyword">fun</span> listTest <span class="token operator">=</span> getAllTest<span class="token punctuation">.</span><span class="token function">execute</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">asLiveData</span><span class="token punctuation">(</span>Dispatchers<span class="token punctuation">.</span>IO<span class="token punctuation">)</span> <span class="token comment">// yêu cầu xử lý trong luồng backgroud</span> |
Code in Activity
1 2 3 4 | viewModel<span class="token punctuation">.</span>listTest<span class="token punctuation">.</span><span class="token function">observe</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">{</span> Log<span class="token punctuation">.</span><span class="token function">d</span><span class="token punctuation">(</span><span class="token string">"HoangAnhTuan95Ptit"</span><span class="token punctuation">,</span> <span class="token string">"onCreate: <span class="token interpolation"><span class="token delimiter variable">${</span>it<span class="token punctuation">.</span>size<span class="token delimiter variable">}</span></span>"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Tài liệu tham khảo
Tự nghĩ ra =))), có thể sắp tới mình sẽ viết một bài trên medium
Kết
Tôi hi vọng sẽ giúp ích cho bạn trong quá trình làm việc với realm trong clean architecture, Nếu có bất kỳ thắc mắc nào thì đừng ngần ngại comment vào bài viết, tôi sẽ cố gắng trả lời. Cảm ơn