Xây dựng ứng dụng Viblo trên android bằng kotlin sử dụng lib jsoup (Phần 2) - Áp dụng data binding cho kotlin
Bài đăng này đã không được cập nhật trong 7 năm
Như ở phần 1 mình giới thiệu thì khi chưa dùng data binding với mỗi 1 recycler view mình lại phải tạo 1 adapter cho nó như thế rất tốn code , mất thời gian và khá chán -> Chính vì thế ở phần này mình sẽ hướng dẫn các bạn áp dụng data binding vào kotlin và tạo 1 single adapter chung để tiết kiệm thời gian và công sức sau này khi sử dụng recycler view
1. Cấu hình
Code : build.gradle Chúng ta cần cấu hình như sau trong file build.gradle Bên kotlin cấu hình phức tạp hơn java khá nhiều (khá buồn)
apply plugin: 'kotlin-kapt'
và kapt trong android
android {
...
kapt {
generateStubs = true
}
...
}
cuối cùng là com.android.databinding:compiler trong dependencies
dependencies {
...
kapt 'com.android.databinding:compiler:3.0.1'
...
}
2. SingleAdapter
2.1. SingleAdapter
Code : SingleAdapter.kt
Chúng ta set giá trị cho 3 biến có thể lấy trong layout là : - position : Vị trí của item - data : giá trị của item - listener : bắt sự kiện cho item và 3 variable được lấy từ simple_place_holder.xml đây có thể là 1 layout tiêu chuẩn của 1 item recycler view
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val data = mDataList[position]
holder.getBinding().setVariable(BR.position, position)
holder.getBinding().setVariable(BR.data, data)
holder.getBinding().setVariable(BR.listener, mPresenter)
if (mDecorator != null) {
mDecorator!!.decorator(holder, position, getItemViewType(position))
}
holder.getBinding().executePendingBindings()
}
Có 2 interface : Presenter dùng cho các listener ko cần viewholder , Decorator dùng cho các listener cần tương tác , chỉnh sửa phức tạp hơn với viewholder
interface Presenter
interface Decorator {
fun decorator(holder: ViewHolder, position: Int, viewType: Int)
}
2.2. simple_place_holder.xml
Tạo file simple_place_holder.xml có chứa các variable là data, listener, position
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="data"
type="com.asia.viblo.model.BaseModel"/>
<variable
name="listener"
type="com.asia.viblo.model.BaseModel"/>
<variable
name="position"
type="int"/>
</data>
<View android:tag="placeholder"/>
</layout>
3. Ứng dụng với PostFragment.kt
Code : PostFragment.kt
3.1. Khởi tạo recycler view
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initRecyclerPost()
}
private fun initRecyclerPost() {
mPostAdapter = SingleAdapter(context, R.layout.item_post)
mPostAdapter.setPresenter(BaseListener(activity)) // set listener for item recycler view
recyclerPost.adapter = mPostAdapter
recyclerPost.layoutManager = LinearLayoutManager(context)
}
3.2. Update data vào adapter
override fun onUpdateData(data: Post?) {
// nothing
}
override fun onUpdateDataList(dataList: MutableList<Post>?) {
mPostAdapter.setData(dataList) // update data vào adapter
mProgressDialog.dismiss()
updateViewNextBackBottom()
}
3.3. BaseListener.kt
Code : BaseListener.kt
Chứa tất cả các listener của adapter
Code
class BaseListener(activity: Activity) : OnClickTag, OnClickDetail, OnClickComment {
private val mActivity: Activity = activity
override fun onOpenTag(tagUrl: String) {
val intent = Intent(mActivity, TagsActivity::class.java)
intent.putExtra(extraUrl, tagUrl)
mActivity.startActivity(intent)
}
override fun onOpenAuthorComment(authorUrl: String) {
}
override fun onOpenAllAuthorComment(authorUrlList: MutableList<String>?) {
}
override fun onOpenDetail(url: String, isVideo: Boolean) {
val intent = when {
url.contains("/s/") -> Intent(mActivity, SeriesActivity::class.java)
url.contains("/q/") -> Intent(mActivity, QuestionsActivity::class.java)
isVideo -> Intent(mActivity, WebViewActivity::class.java)
else -> Intent(mActivity, PostDetailActivity::class.java)
}
intent.putExtra(extraUrl, url)
mActivity.startActivity(intent)
}
override fun onOpenAuthor(baseModel: BaseModel) {
val intent = Intent(mActivity, AuthorActivity::class.java)
intent.putExtra(extraData, baseModel)
mActivity.startActivity(intent)
}
}
3.4. item_recycler_post.xml
Code : item_recycler_post.xml
<data>
<import type="android.text.TextUtils"/>
<variable
name="data"
type="com.asia.viblo.model.post.Post"/>
<variable
name="listener"
type="com.asia.viblo.listener.BaseListener"/>
</data>
- Cách set các listener cho view
...
android:onClick="@{() -> listener.onOpenDetail(data.postUrl, data.isVideo)}"
...
android:onClick="@{() -> listener.onOpenAuthor(data)}"
...
android:onClick="@{() -> listener.onOpenAuthor(data)}"
3.5. Các tạo các include layout
<include
android:id="@+id/layoutStatus"
layout="@layout/include_layout_status"
app:clips="@{data.clips}"
app:comments="@{data.comments}"
app:posts="@{data.posts}"
app:score="@{data.score}"
app:views="@{data.views}"/>
<include
android:id="@+id/layoutStats"
layout="@layout/include_layout_stats"
app:followers="@{data.followers}"
app:post="@{data.post}"
app:reputation="@{data.reputation}"/>
3.5.1. include_layout_status.xml
Code : include_layout_status.xml Các lấy dự liệu từ các biến trên :
<include
android:id="@+id/layoutStatus"
layout="@layout/include_layout_status"
app:clips="@{data.clips}"
app:comments="@{data.comments}"
app:posts="@{data.posts}"
app:score="@{data.score}"
app:views="@{data.views}"/>
Khi gọi
app:clips="@{data.clips}"
nó sẽ truyền dữ liệu vào
<variable
name="clips"
type="String"/>
Tương tự với các biến khác
3.5.2. include_layout_stats.xml
Tương tự như 3.5.1 thôi Code : include_layout_stats.xml
3.6.
Source Code
All rights reserved