Lời mở đầu
Tình cờ mình có cơ hội được tham gia vào một dự án sử dụng React-Native
và kiến trúc Redux
, quả thực mình cảm thấy rất hứng thú với Redux
. Đó cũng là lý do mà mình muốn áp dụng kiến trúc Redux
vào ứng dụng Android.
Thư viện mà mình sử dụng trong bài viết này có tên gọi là Kdux
Redux là gì
Redux là một predictable state management tool
cho các ứng dụng JS. Nó giúp bạn viết các ứng dụng hoạt động một cách nhất quán, chạy trong các môi trường khác nhau (client, server, and native) và dễ dàng để test.
Chi tiết
Redux gồm các thành phần chính:
- Store: Là nơi quan lý những
State
hay còn gọi là trạng thái của ứng dụng. - Actions: Là nơi mà bạn định nghĩa các event mà ứng dụng muốn giao tiếp đến những
State
được quản lý trongStore
thông qua phương thứcstore.dispatch()
. - Reducers: Là tầng xử lý, chúng sẽ lấy những trạng thái hiện tại, thông qua các event được định nghĩa trong
Actions
, ứng với mỗi action, chúng sẽ trả về một trạng thái mới.
Bắt đầu
Chúng ta sẽ bắt đầu làm một ứng dụng đếm số đơn giản.
- Khởi tạo một
State
12<span class="token keyword">data</span> <span class="token keyword">class</span> <span class="token function">CounterState</span><span class="token punctuation">(</span><span class="token keyword">val</span> number<span class="token operator">:</span> Int <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token operator">:</span> State - Khởi tạo một
Action
123456789101112<span class="token keyword">sealed</span> <span class="token keyword">class</span> CounterAction<span class="token operator">:</span> Action <span class="token punctuation">{</span><span class="token keyword">object</span> INCREASE<span class="token operator">:</span> <span class="token function">CounterAction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token keyword">object</span> DECREASE<span class="token operator">:</span> <span class="token function">CounterAction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token keyword">companion</span> <span class="token keyword">object</span> <span class="token punctuation">{</span><span class="token keyword">fun</span> <span class="token function">increaseAction</span><span class="token punctuation">(</span>dispatch<span class="token operator">:</span> Dispatch<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token function">dispatch</span><span class="token punctuation">(</span>INCREASE<span class="token punctuation">)</span><span class="token keyword">fun</span> <span class="token function">decreaseAction</span><span class="token punctuation">(</span>dispatch<span class="token operator">:</span> Dispatch<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token function">dispatch</span><span class="token punctuation">(</span>DECREASE<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">}</span> - Khởi tạo một
Reducer
123456789101112<span class="token keyword">class</span> CounterReducer<span class="token operator">:</span> Reducer<span class="token operator"><</span>CounterState<span class="token operator">></span> <span class="token punctuation">{</span><span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">reduce</span><span class="token punctuation">(</span>state<span class="token operator">:</span> CounterState<span class="token punctuation">,</span> action<span class="token operator">:</span> Action<span class="token punctuation">)</span><span class="token operator">:</span> CounterState <span class="token punctuation">{</span><span class="token keyword">return</span> <span class="token keyword">when</span> <span class="token punctuation">(</span>action<span class="token punctuation">)</span> <span class="token punctuation">{</span>CounterAction<span class="token punctuation">.</span>INCREASE <span class="token operator">-></span> state<span class="token punctuation">.</span><span class="token function">copy</span><span class="token punctuation">(</span>number <span class="token operator">=</span> state<span class="token punctuation">.</span>number <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span>CounterAction<span class="token punctuation">.</span>DECREASE <span class="token operator">-></span> state<span class="token punctuation">.</span><span class="token function">copy</span><span class="token punctuation">(</span>number <span class="token operator">=</span> state<span class="token punctuation">.</span>number <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token keyword">else</span> <span class="token operator">-></span> state<span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span> - CounterActivity1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465<span class="token keyword">class</span> CounterActivity<span class="token operator">:</span> <span class="token function">AppCompatActivity</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> Enhancer<span class="token operator"><</span>CounterState<span class="token operator">></span> <span class="token punctuation">{</span><span class="token keyword">private</span> <span class="token keyword">val</span> store<span class="token operator">:</span> Store<span class="token operator"><</span>CounterState<span class="token operator">></span> <span class="token keyword">by</span> lazy <span class="token punctuation">{</span><span class="token function">Store</span><span class="token punctuation">(</span><span class="token function">CounterReducer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token function">CounterState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token comment">// applyMiddleware(...)</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token comment">/*** Nếu bạn muốn xem lịch sử thay đổi của các trạng thái,* Kdux có cung cấp cho chúng ta một công cụ gọi là KduxDevTools.* Chúng ta sẽ khởi tạo store thông qua thương thức composeWithDevTools.** private val store: Store<CounterState> by lazy {* composeWithDevTools(* CounterReducer(),* CounterState()* // applyMiddleware(...)* )* }*/</span><span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onCreate</span><span class="token punctuation">(</span>savedInstanceState<span class="token operator">:</span> Bundle<span class="token operator">?</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">onCreate</span><span class="token punctuation">(</span>savedInstanceState<span class="token punctuation">)</span><span class="token function">setContentView</span><span class="token punctuation">(</span>R<span class="token punctuation">.</span>layout<span class="token punctuation">.</span>activity_counter<span class="token punctuation">)</span>btnIncrease<span class="token punctuation">.</span><span class="token function">setOnClickListener</span> <span class="token punctuation">{</span>CounterAction<span class="token punctuation">.</span><span class="token function">increaseAction</span> <span class="token punctuation">{</span> store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span>it<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span>btnDecrease<span class="token punctuation">.</span><span class="token function">setOnClickListener</span> <span class="token punctuation">{</span>CounterAction<span class="token punctuation">.</span><span class="token function">decreaseAction</span> <span class="token punctuation">{</span> store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span>it<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token comment">// btnUndo.setOnClickListener {</span><span class="token comment">// store.dispatch(KduxDevToolAction.UNDO)</span><span class="token comment">// }</span><span class="token comment">// btnRedo.setOnClickListener {</span><span class="token comment">// store.dispatch(KduxDevToolAction.REDO)</span><span class="token comment">// }</span><span class="token comment">// btnReset.setOnClickListener {</span><span class="token comment">// store.dispatch(KduxDevToolAction.RESET)</span><span class="token comment">// }</span><span class="token punctuation">}</span><span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onStart</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">onStart</span><span class="token punctuation">(</span><span class="token punctuation">)</span>store<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onStop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">onStop</span><span class="token punctuation">(</span><span class="token punctuation">)</span>store<span class="token punctuation">.</span><span class="token function">unsubscribe</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">enhance</span><span class="token punctuation">(</span>state<span class="token operator">:</span> CounterState<span class="token punctuation">)</span> <span class="token punctuation">{</span>txtNumber<span class="token punctuation">.</span>text <span class="token operator">=</span> <span class="token string">"<span class="token interpolation"><span class="token delimiter variable">${</span>state<span class="token punctuation">.</span>number<span class="token delimiter variable">}</span></span>"</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
Kết quả
Tổng kết
Redux là một tool giúp bạn có thể quản lý các trạng thái của ứng dụng. Ngoài ra nó giúp tách biệt các login function, dễ dàng cho việc kiểm thử.
Hy vọng với bài viết này, phần nào giúp các bạn hiểu được cách hoạt động của Redux
. Chúc các bạn thành công.