Skip to content

Commit f3dbccb

Browse files
authored
Update README.md
1 parent b9928c4 commit f3dbccb

File tree

1 file changed

+74
-21
lines changed

1 file changed

+74
-21
lines changed

README.md

Lines changed: 74 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,12 @@ public void appendMatchFeature(@NonNull Set<Object> allMatchFeatures) {
176176
private val userInfoData = MutableLiveData<UserInfo>()
177177

178178
//在adapter里监听数据变化
179-
diffAdapter.addUpdateMediator(userInfoData, object : UpdateFunction<UserInfo, ItemViewData> {
179+
diffAdapter.addUpdateMediator(userInfoData, object : UpdatePayloadFunction<UserInfo, ItemViewData> {
180180
override fun providerMatchFeature(input: UserInfo): Any {
181181
return input.uid
182182
}
183183

184-
override fun applyChange(input: UserInfo, originalData: ItemViewData): ItemViewData {
184+
override fun applyChange(input: UserInfo, originalData: ItemViewData,, payloadKeys: MutableSet<String>): ItemViewData {
185185

186186
return originalData.userInfo = input
187187

@@ -194,17 +194,16 @@ fun asyncDataFetch(userInfo : UserInfo) {
194194
}
195195

196196
```
197-
这样当asyncDataFetch接收到数据变化的通知的时候,改变userInfoData的值,adapter里对应的Item就会更新。其中找到adapter中需要更新的Item是关键部分,主要由实现`UpdateFunction`来完成,实现`UpdateFunction`也很简单。
197+
这样当asyncDataFetch接收到数据变化的通知的时候,改变userInfoData的值,adapter里对应的Item就会更新。其中找到adapter中需要更新的Item是关键部分,主要由实现`UpdatePayloadFunction `来完成,实现`UpdatePayloadFunction `也很简单。
198198

199199
```java
200-
interface UpdateFunction<I,R extends BaseMutableData> {
200+
public abstract class UpdatePayloadFunction<I, R extends BaseMutableData> implements UpdateFunction<I,R > {
201201

202202
/**
203203
* 匹配所有数据,及返回类型为R的所有数据
204204
*/
205205
Object MATCH_ALL = new Object();
206206

207-
208207
/**
209208
* 提供一个特征,用来查找列表数据中和此特征相同的数据
210209
* @param input 用来提供查找数据和最终改变列表的数据 ,最终匹配的是allMatchFeatures里的数据,默认情况下就是uniqueItemFeature()
@@ -213,16 +212,23 @@ interface UpdateFunction<I,R extends BaseMutableData> {
213212
Object providerMatchFeature(@NonNull I input);
214213

215214
/**
216-
* 匹配到对应的数据,如果符合条件的数据有很多个,可能会被回调多次
215+
* 匹配到对应的数据,如果符合条件的数据有很多个,可能会被回调多次,不需要新建对象,主需要根据Input把originalData改变相应的值就行了
217216
* @param input 是数据改变的部分数据源
218217
* @param originalData 需要改变的数据项
219-
* @return 改变后的数据项
218+
* @param payloadKeys 用来标识改变后的数据哪些部分发生了改变,if payloadKeys is not empty ,
219+
* {@link com.silencedut.diffadapter.holder.BaseDiffViewHolder#updatePartWithPayload(BaseMutableData, Bundle, int)}
220+
* will be call rather than
221+
* {@link com.silencedut.diffadapter.holder.BaseDiffViewHolder#updateItem(BaseMutableData, int)}
222+
* @return 改变后的数据项,
223+
*
220224
*/
221-
R applyChange(@NonNull I input,@NonNull R originalData);
225+
226+
public abstract R applyChange(@NonNull I input, @NonNull R originalData, @NonNull Set<String> payloadKeys);
222227

223228
}
224229
```
225-
`UpdateFunction`用来提供异步数据获取到后数据用来和列表中的数据匹配的规则和根据规则找到需要更改的对象后如果改变原对象,剩下的更新都由`diffadapter`来处理。如果符合条件的数据有很多个,`applyChange(@NonNull I input,@NonNull R originalData)`会被回调多次。如下时:
230+
`UpdatePayloadFunction`用来提供异步数据获取到后数据用来和列表中的数据匹配的规则和根据规则找到需要更改的对象后如果改变原对象,剩下的更新都由`diffadapter`来处理。如果符合条件的数据有很多个,`applyChange(@NonNull I input, @NonNull R originalData, @NonNull Set<String> payloadKeys)`会被回调多次。
231+
如下时:
226232

227233
```java
228234
Object providerMatchFeature(@NonNull I input) {
@@ -233,9 +239,15 @@ Object providerMatchFeature(@NonNull I input) {
233239

234240
如果同一种匹配规则`providerMatchFeature`对应多种Holder类型,`UpdateFunction<I,R>`的返回数据类型R就可以直接设为基类的`BaseMutableData`,然后再applyChange里在具体根据类型来处理不同的UI。
235241

242+
`UpdateFunction`已废弃,`payloadKeys`可以用来解决payload方式更新item时每次需要new对象的问题。
243+
236244
### 最高效的Item局部更新方式 —— payload
237245

238-
DiffUtil 能让一个列表中只更新部分变化的Item,payload能让同一个Item只更新需要变化的View,这种方式非常适合同一个Item有多个异步数据源的,同时又对性能有更高要求的列表。
246+
DiffUtil 能让一个列表中只更新部分数据变化的Item,payload能让同一个Item只更新需要变化的View,这种方式非常适合同一个Item有多个异步数据源的,同时又对性能有更高要求的列表。看具体更新需求来判断是否有必要。
247+
248+
有两种情况的局部更新
249+
250+
**第一种是全量数据对比的情况,也就是同一个业务可能会多次调用`diffadapter.setData(List)`,可使用如下的方式**
239251

240252
**Step 1:重写BaseMutableData的appendDiffPayload**
241253

@@ -250,40 +262,81 @@ data class ItemViewData(var uid:Long, var userInfo: UserInfo?, var anyOtherData:
250262
...
251263

252264
/**
253-
* 最高效的更新方式,如果不是频繁更新的可以不实现这个方法
265+
* 最高效的更新方式,如果不是全量频繁更新的可以不实现这个方法
254266
*/
255-
override fun appendDiffPayload(newData: ItemViewData, diffPayloadBundle: Bundle) {
256-
super.appendDiffPayload(newData, diffPayloadBundle)
257-
if(this.userInfo!= newData.userInfo) {
258-
diffPayloadBundle.putString(KEY_BASE_INFO, KEY_BASE_INFO)
267+
override fun appendPayloadKeys(newData: LegendViewData, payloadKeys: MutableSet<String>) {
268+
super.appendPayloadKeys(newData, payloadKeys)
269+
if(this.userInfo!= newData.userInfo) {
270+
payloadKeys.add(KEY_BASE_INFO)
259271
}
260272
if(this.anyData != newData.anyData) {
261-
diffPayloadBundle.putString(KEY_ANY, KEY_ANY)
273+
payloadKeys.add(KEY_ANY)
274+
262275
}
263-
...
276+
...
264277
}
278+
265279
}
266280
```
267281

268282
默认用Bundle存取变化,无需存具体的数据,只需类似设置标志位,表明Item的哪部分数据发生了变化。
269283

284+
**第二种是异步动态更新一个Item的时候,比如个人资料获取,中途单个Item数据变化的情况,可使用如下的Step1**
285+
286+
```java
287+
public R applyChange(@NonNull I input, @NonNull R originalData, @NonNull Set<String> payloadKeys){
288+
...
289+
originalData.*** = input.***
290+
payloadKeys.add("自定义String类型的Key值")
291+
...
292+
}
293+
```
294+
这两种方式不是互斥的,但也没什么关联,也可以根据自己的业务场景自行选择,如果不需要payload更新,两种方式都不需要。后续的步骤两种方式相同。
295+
270296
**Step 2 :需要重写BaseDiffViewHolder里的`updatePartWithPayload`**
271297

272298
```kotlin
273299
class ItemViewHolder(itemViewRoot: View, recyclerAdapter: DiffAdapter): BaseDiffViewHolder<ItemViewData>( itemViewRoot, recyclerAdapter){
274300

275-
override fun updatePartWithPayload(data: ItemViewData, payload: Bundle, position: Int) {
301+
override fun updatePartWithPayload(data: ItemViewData, payloadKeys: MutableSet<String>, position: Int) {
276302

277-
if(payload.getString(ItemViewData.KEY_BASE_INFO)!=null) {
303+
if(payloadKeys.contains(ItemViewData.KEY_BASE_INFO)) {
278304
updateBaseInfo(data)
279305
}
280306

281-
if(payload.getString(ItemViewData.KEY_ANY)!=null) {
307+
if(payloadKeys.contains(ItemViewData.KEY_ANY)) {
282308
updateAnyView(data)
283309
}
284310
}
285311
```
286-
根据变化的标志位,更新Item中需要变化部分的View
312+
313+
**Step 3:监听数据变化,更新列表,这个只是异步数据更新Item需要也就是第二种场景,如果每次`diffadapter.setData(List)`的数据已经是是有所有的数据信息,不需要以下的动态更新方案**
314+
315+
```kotlin
316+
//用于监听请求的异步数据,userInfoData变化时与此相关的数据
317+
private val userInfoData = MutableLiveData<UserInfo>()
318+
319+
//在adapter里监听数据变化
320+
diffAdapter.addUpdateMediator(userInfoData, object : UpdateFunction<UserInfo, ItemViewData> {
321+
override fun providerMatchFeature(input: UserInfo): Any {
322+
return input.uid
323+
}
324+
325+
override fun applyChange(@NonNull I input, @NonNull R originalData, @NonNull Set<String> payloadKeys): ItemViewData {
326+
//不再需要新建对象
327+
originalData.*** = input.***
328+
payloadKeys.add("自定义String类型的Key值")
329+
return originalData
330+
331+
}
332+
})
333+
334+
// 任何通知数据获取到的通知
335+
fun asyncDataFetch(userInfo : UserInfo) {
336+
userInfoData.value = userInfo
337+
}
338+
```
339+
287340

288341
## More
289342

0 commit comments

Comments
 (0)