Skip to content

Commit

Permalink
增加bindWithPayloads
Browse files Browse the repository at this point in the history
  • Loading branch information
junixapp committed Jan 14, 2022
1 parent 1a79978 commit 20577d4
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 23 deletions.
7 changes: 5 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ android {

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation project(":easy-adapter")
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.blankj:utilcodex:1.31.0'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.github.bumptech.glide:glide:4.12.0'
}

2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lxj.easyadapter.sample">

<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
Expand Down
102 changes: 90 additions & 12 deletions app/src/main/java/com/lxj/easyadapter/sample/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,94 @@ import android.graphics.Color
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.blankj.utilcode.util.CloneUtils
import com.blankj.utilcode.util.GsonUtils
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestOptions
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.lxj.easyadapter.*

import kotlinx.android.synthetic.main.activity_main.*
import java.lang.reflect.Type
import java.util.*
import java.util.concurrent.CopyOnWriteArrayList
import com.bumptech.glide.request.transition.DrawableCrossFadeFactory




class MainActivity : AppCompatActivity() {

internal var userList: MutableList<User> = ArrayList()
private var adapter: EasyAdapter<User>? = null
private var multiItemTypeAdapter: MultiItemTypeAdapter<User>? = null

val url = "https://img1.baidu.com/it/u=1925715390,133119052&fm=253&fmt=auto&app=138&f=JPEG?w=400&h=400"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
userList.add(User(name = "盛大"))
userList.add(User(name = "都是"))
userList.add(User(name = "CEAD"))
userList.add(User(name = "大图"))
add.setOnClickListener {
val old = deepCopy()
val range = (0 until userList.size)
userList.add(if(range.isEmpty()) 0 else range.random(), User(id = UUID.randomUUID().toString(), name = "随机添加 - ${(0..1000).random()}" ))
DiffUtil.calculateDiff(UserDiffCallback(old, userList)).dispatchUpdatesTo(recyclerView.adapter!!)
}
del.setOnClickListener {
if(userList.isNullOrEmpty()) return@setOnClickListener
val range = (0 until userList.size)
val old = deepCopy()
userList.removeAt(range.random())
DiffUtil.calculateDiff(UserDiffCallback(old, userList)).dispatchUpdatesTo(recyclerView.adapter!!)
}
update.setOnClickListener {
if(userList.isNullOrEmpty()) return@setOnClickListener
val index = (0 until userList.size).random()
val old = deepCopy()
userList[index].name += " - 随机更新"
DiffUtil.calculateDiff(UserDiffCallback(old, userList)).dispatchUpdatesTo(recyclerView.adapter!!)
}
replace.setOnClickListener {
if(userList.isNullOrEmpty()) return@setOnClickListener
val index = (0 until userList.size).random()
val old = deepCopy()
userList[index] = User(name = "我是随机替换的")
DiffUtil.calculateDiff(UserDiffCallback(old, userList)).dispatchUpdatesTo(recyclerView.adapter!!)
}
move.setOnClickListener {
if(userList.isNullOrEmpty()) return@setOnClickListener
val old = deepCopy()
userList.reverse()
DiffUtil.calculateDiff(UserDiffCallback(old, userList)).dispatchUpdatesTo(recyclerView.adapter!!)
}
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.itemAnimator = null

//prepare data
for (i in 0..6) {
userList.add(User("本杰明 - $i", i * 2, i))
}
// for (i in 0..6) {
// userList.add(User("本杰明 - $i", i * 2, i))
// }

// testHeader()
testMultiItem()
}

fun deepCopy(): List<User>{
val json = GsonBuilder().create().toJson(userList)
return GsonBuilder().create().fromJson<List<User>>(json, object : TypeToken<List<User>>() {}.type)
}

private fun testHeader() {
adapter = object : EasyAdapter<User>(userList, R.layout.item) {
override fun bind(holder: ViewHolder, user: User, position: Int) {
Expand Down Expand Up @@ -88,10 +144,10 @@ class MainActivity : AppCompatActivity() {
multiItemTypeAdapter = MultiItemTypeAdapter<User>(userList)
.apply {
addItemDelegate(OneDelegate())
addItemDelegate(TwoDelegate())
addHeaderView(createView("Multi Header view1111"))
addHeaderView(createView("Multi Header view22222"))
addFootView(createView("Multi Footer view"))
// addItemDelegate(TwoDelegate())
// addHeaderView(createView("Multi Header view1111"))
// addHeaderView(createView("Multi Header view22222"))
// addFootView(createView("Multi Footer view"))
setOnItemClickListener(object : MultiItemTypeAdapter.OnItemClickListener {
override fun onItemClick(view: View, holder: RecyclerView.ViewHolder, position: Int) {
Toast.makeText(this@MainActivity, "position: $position", Toast.LENGTH_SHORT).show()
Expand All @@ -108,13 +164,35 @@ class MainActivity : AppCompatActivity() {
internal inner class OneDelegate : ItemDelegate<User> {

override fun isThisType(item: User, position: Int): Boolean {
return position % 2 != 0
return true
// return position % 2 != 0
}
override fun bind(holder: ViewHolder, user: User, position: Int) {
holder.setText(android.R.id.text1, "name: " + user.name + " - " + position)
holder.setText(R.id.name, user.name)
Glide.with(this@MainActivity)
.load(url).transition(DrawableTransitionOptions.withCrossFade(1000))
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.placeholder(R.mipmap.ic_launcher_round)
.into(holder.getView<ImageView>(R.id.avatar))
}

//布局更新
override fun bindWithPayloads(
holder: ViewHolder,
t: User,
position: Int,
payloads: List<Any>
) {
if(payloads.isNullOrEmpty()) return
val bundle = payloads[0] as Bundle
val name = bundle.getString("name") ?: ""
if(!name.isNullOrEmpty()){
holder.setText(R.id.name, name)
}
}

override fun getLayoutId(): Int = android.R.layout.simple_list_item_1
override fun getLayoutId(): Int = R.layout.adapter_one
}

internal inner class TwoDelegate : ItemDelegate<User> {
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/com/lxj/easyadapter/sample/User.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package com.lxj.easyadapter.sample

import java.util.*

data class User(var name: String = "", var age: Int = 0, var id: Int = 0)

data class User(var name: String = "", var age: Int = 0, var id: String = UUID.randomUUID().toString())
29 changes: 29 additions & 0 deletions app/src/main/java/com/lxj/easyadapter/sample/UserDiffCallback.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.lxj.easyadapter.sample

import android.os.Bundle
import androidx.recyclerview.widget.DiffUtil

class UserDiffCallback(var oldData: List<User>?, var newData: List<User>?) : DiffUtil.Callback() {
override fun getOldListSize() = oldData?.size ?: 0
override fun getNewListSize() = newData?.size ?: 0

override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
if(oldData.isNullOrEmpty() || newData.isNullOrEmpty()) return false
return oldData!![oldItemPosition].id == newData!![newItemPosition].id
}

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldData!![oldItemPosition].name == newData!![newItemPosition].name
}

//局部更新 areItemsTheSame为true && areContentsTheSame==false 调用
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
val oldItem = oldData!![oldItemPosition]
val newItem = newData!![newItemPosition]
val bundle = Bundle()
if(oldItem.name != newItem.name){
bundle.putString("name", newItem.name)
}
return bundle
}
}
37 changes: 36 additions & 1 deletion app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,46 @@
android:orientation="vertical">


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<Button
android:id="@+id/add"
android:text="添加"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/del"
android:text="删除"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/update"
android:text="更新"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/replace"
android:text="替换"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/move"
android:text="移动"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>

</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:splitMotionEvents="false" />
</LinearLayout>

19 changes: 19 additions & 0 deletions app/src/main/res/layout/adapter_one.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:padding="12dp"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<ImageView
android:id="@+id/avatar"
android:layout_width="40dp"
android:layout_height="40dp"/>
<TextView
android:id="@+id/name"
android:layout_marginLeft="10dp"
android:textColor="#222222"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ interface ItemDelegate<T> {

fun bind(holder: ViewHolder, t: T, position: Int)

fun bindWithPayloads(holder: ViewHolder, t: T, position: Int, payloads: List<Any>) {
bind(holder, t, position)
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,22 @@ class ItemDelegateManager<T> {
"No ItemDelegate added that matches position=$position in data source")
}

fun convert(holder: ViewHolder, item: T, position: Int) {
fun convert(holder: ViewHolder, item: T, position: Int, payloads: List<Any>? = null) {
val delegatesCount = delegates.size()
for (i in 0 until delegatesCount) {
val delegate = delegates.valueAt(i)

if (delegate.isThisType(item, position)) {
delegate.bind(holder, item, position)
if (payloads.isNullOrEmpty()){
delegate.bind(holder, item, position)
}else{
delegate.bindWithPayloads(holder, item, position, payloads)
}
return
}
}
throw IllegalArgumentException(
"No ItemDelegateManager added that matches position=$position in data source")
// throw IllegalArgumentException(
// "No ItemDelegateManager added that matches position=$position in data source")
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ open class MultiItemTypeAdapter<T>(var data: List<T>) : RecyclerView.Adapter<Vie

fun onViewHolderCreated(holder: ViewHolder, itemView: View) { }

fun convert(holder: ViewHolder, t: T) {
mItemDelegateManager.convert(holder, t, holder.adapterPosition - headersCount)
fun convert(holder: ViewHolder, t: T, payloads: List<Any>? = null) {
mItemDelegateManager.convert(holder, t, holder.adapterPosition - headersCount, payloads)
}

protected fun isEnabled(viewType: Int): Boolean {
Expand Down Expand Up @@ -90,6 +90,16 @@ open class MultiItemTypeAdapter<T>(var data: List<T>) : RecyclerView.Adapter<Vie
convert(holder, data[position - headersCount])
}

override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: List<Any>) {
if (isHeaderViewPos(position)) {
return
}
if (isFooterViewPos(position)) {
return
}
convert(holder, data[position - headersCount], payloads)
}

override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
WrapperUtils.onAttachedToRecyclerView(
Expand Down

0 comments on commit 20577d4

Please sign in to comment.