-
Notifications
You must be signed in to change notification settings - Fork 0
/
base-quick-adapter-tips.html
320 lines (239 loc) · 14.1 KB
/
base-quick-adapter-tips.html
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
<!DOCTYPE html>
<html>
<head>
<!-- [[! Document Settings ]] -->
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!-- [[! Page Meta ]] -->
<title>BaseQuickAdapter使用tips</title>
<meta name="description" content="与机器,人,神共舞 - 编程,读书,思考,旅行,与机器对话,与人交谈,对神发问,探索,体验人生美丽的风景" />
<meta name="HandheldFriendly" content="True" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="shortcut icon" href="/assets/images/favicon.ico" >
<!-- [[! Styles'n'Scripts ]] -->
<link rel="stylesheet" type="text/css" href="/assets/css/screen.css" />
<link rel="stylesheet" type="text/css"
href="//fonts.googleapis.com/css?family=Merriweather:300,700,700italic,300italic|Open+Sans:700,400" />
<link rel="stylesheet" type="text/css" href="/assets/css/syntax.css" />
<!-- [[! Ghost outputs important style and meta data with this tag ]] -->
<link rel="canonical" href="/" />
<meta name="referrer" content="origin" />
<link rel="next" href="/page2/" />
<meta property="og:site_name" content="与机器,人,神共舞" />
<meta property="og:type" content="website" />
<meta property="og:title" content="与机器,人,神共舞" />
<meta property="og:description" content="编程,读书,思考,旅行,与机器对话,与人交谈,对神发问,探索,体验人生美丽的风景" />
<meta property="og:url" content="/" />
<meta property="og:image" content="/assets/images/cover1.jpg" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="与机器,人,神共舞" />
<meta name="twitter:description" content="编程,读书,思考,旅行,与机器对话,与人交谈,对神发问,探索,体验人生美丽的风景" />
<meta name="twitter:url" content="/" />
<meta name="twitter:image:src" content="/assets/images/cover1.jpg" />
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "Website",
"publisher": "Tao's Page",
"url": "/",
"image": "/assets/images/cover1.jpg",
"description": "编程,读书,思考,旅行,与机器对话,与人交谈,对神发问,探索,体验人生美丽的风景"
}
</script>
<meta name="generator" content="Jekyll 3.0.0" />
<link rel="alternate" type="application/rss+xml" title="与机器,人,神共舞" href="/rss.xml" />
</head>
<body class="home-template nav-closed">
<div class="nav">
<h3 class="nav-title">Menu</h3>
<a href="#" class="nav-close">
<span class="hidden">Close</span>
</a>
<ul>
<li class="nav-home " role="presentation"><a href="/">Home</a></li>
<li class="nav-about " role="presentation"><a href="/about.html">About</a></li>
<li class="nav-fables " role="presentation"><a href="/tag/machine/">Machine</a></li>
<li class="nav-speeches " role="presentation"><a href="/tag/human/">Human</a></li>
<li class="nav-fiction " role="presentation"><a href="/tag/god/">God</a></li>
<li class="nav-author " role="presentation"><a href="/author/hetao/">Author</a></li>
</ul>
<a class="subscribe-button icon-feed" href="/vocab.html">Apps</a>
</div>
<span class="nav-cover"></span>
<div class="site-wrapper">
<!-- [[! Everything else gets inserted here ]] -->
<!-- default -->
<!-- The comment above "< default" means - insert everything in this file into -->
<!-- the [body] of the default.hbs template, which contains our header/footer. -->
<!-- Everything inside the #post tags pulls data from the post -->
<!-- #post -->
<header class="main-header post-head no-cover">
<nav class="main-nav clearfix">
</nav>
</header>
<main class="content" role="main">
<article class="post tag-machine">
<header class="post-header">
<h1 class="post-title">BaseQuickAdapter使用tips</h1>
<section class="post-meta">
<!-- <a href='/'>Tao He</a> -->
<time class="post-date" datetime="2021-11-10">10 Nov 2021</time>
<!-- [[tags prefix=" on "]] -->
on
<a href='/tag/machine'>Machine</a>
</section>
</header>
<section class="post-content">
<p>此文记录在实际工作中使用BaseQuickAdapter的一些经验和心得,以期新同学在第一次使用时免去踩坑的风险。</p>
<p>Tips:</p>
<ul>
<li>如果adapter只有一种类型的item,则直接继承自BaseQuickAdapter,提供布局文件即可,例如:</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
class SelectedContactAdapter : BaseQuickAdapter<ContactUIItemData, BaseViewHolder>(layoutResId = R.layout.s_item_select_user_normal){
override fun convert(holder: BaseViewHolder, item: ContactUIItemData) {
holder.getView<UserFaceView>(R.id.ufv_avatar).bindUid(item.bean.account)
addChildClickViewIds(R.id.ll_item)
}
}
</code></pre></div></div>
<ul>
<li>如果adapter需要多种类型的item,则需要继承自BaseMultiItemQuickAdapter,例如:</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
class ContactAdapter : BaseMultiItemQuickAdapter<ContactUIItemData, BaseViewHolder>() {
var actionType = AppConstants.User.TYPE_CONTACT_NEW_MESSAGE
init {
addItemType(ITEM_TYPE_HEAD, R.layout.s_item_contact_head)
addItemType(ITEM_TYPE_TITLE, R.layout.s_item_contact_title)
addItemType(ITEM_TYPE_CONTACT, R.layout.s_item_single_contact)
setDiffCallback(object : DiffUtil.ItemCallback<ContactUIItemData>() {
override fun areItemsTheSame(
oldItem: ContactUIItemData,
newItem: ContactUIItemData
): Boolean {
return oldItem.viewType == newItem.viewType
}
override fun areContentsTheSame(
oldItem: ContactUIItemData,
newItem: ContactUIItemData
): Boolean {
if (newItem.viewType == ITEM_TYPE_CONTACT) {
return TextUtils.equals(newItem.bean.account, oldItem.bean.account) && TextUtils.equals(newItem.bean.name, oldItem.bean.name)
&& TextUtils.equals(newItem.searchText, oldItem.searchText)
}
return true;
}
})
}
....
}
</code></pre></div></div>
<p>这里需要注意的是数据item必须实现MultiItemEntity接口:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
public class ContactUIItemData implements MultiItemEntity {
...
@Override
public int getItemType() {
return viewType;
}
}
</code></pre></div></div>
<p>并且需要实现DiffCallback,DiffCallback有两个方法需要实现,第一个用来判断两个item是否同一类型,如果判断是,则调用第二个方法判断两个item内容是否相等,这两个方法需要根据实际业务场景谨慎实现。</p>
<ul>
<li>
<p>刷新数据统一调用setDiffNewData,无论是第一次加载数据还是后续数据变更刷新,这里要注意的是,刷新时调用setDiffNewData需要传入新的数据列表才能实现刷新。</p>
</li>
<li>
<p>如只需刷新某个item,则可以通过notifyItemChanged来实现,当然添加和删除数据都有对应的方法,但是添加和删除还是统一走setDiffNewData比较好。</p>
</li>
<li>
<p>如只需刷新某个item中的某个元素,而不是刷新整个item,则可以通过payload的方式来实现局部刷新,例如:</p>
</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
override fun convert(holder: BaseViewHolder, item: GroupUIItemData, payloads: List<Any>) {
super.convert(holder, item, payloads)
when(holder.itemViewType) {
GroupContactItemConstants.ITEM_TYPE_CONTACT -> {
if (payloads.isEmpty()) {
return
}
val payload = payloads[0];
if (payload == EDIT_MODE_PAYLOAD) {
val cbSelect = holder.getView<CheckBox>(R.id.cb_select)
cbSelect.isChecked = item.checked
cbSelect.isEnabled = item.enabled
if (item.canSelect) {
cbSelect.visibility = View.VISIBLE
} else {
cbSelect.visibility = View.GONE
}
}
}
}
}
</code></pre></div></div>
<p>对需要局部刷新的item调用contactsAdapter.notifyItemChanged(position, GroupContactAdapter.EDIT_MODE_PAYLOAD).</p>
<ul>
<li>
<p>如遇到列表不刷新的问题,则需要检查调用setDiffNewData时传入的是否时新的列表,数据源对象是不是新对象,从多个方面来排查,理论上更新列表就统一使用这个方法,避免调用notifyDataSetChanged.</p>
</li>
<li>
<p>要注意DiffCallback的实现,如果遇到问题,可调试此接口两个方法实现的返回值。</p>
</li>
<li>
<p>Item的点击事件响应都是通过setOnItemClickListener和setOnItemChildClickListener分别实现,前者是注册整个item,后者是注册item上的子view,子view的响应需要调用addChildClickViewIds来分别注册。</p>
</li>
<li>
<p>Item的长按与点击相同,分别对应setOnItemLongClickListener和setOnItemChildLongClickListener两个方法。</p>
</li>
</ul>
</section>
<footer class="post-footer">
<!-- Everything inside the #author tags pulls data from the author -->
<!-- #author-->
<!-- Add Disqus Comments -->
</footer>
</article>
</main>
<aside class="read-next">
<!-- [[! next_post ]] -->
<a class="read-next-story no-cover" href="/live-in-the-vim">
<section class="post">
<h2>生活在Vim中</h2>
<p>从第一天接触Vim编辑器到现在已经过去10年了,从最开始的不知所措到现在的运用自如,Vim已经融入到了我工作生活的很多场景, 它对于我已经不仅仅是一个高效强大的编辑器,更是变成了一种做事的方式和编辑,操作的哲学。关于这种哲学我最喜欢一个类比: 使用Vim的过程就像是一个画家画画的过程,当一个画家需要挥毫泼墨时,他就进入了insert模式,可以对画布进行任意的修改,当一个画家需要思考和审视时,他需要防止笔误和操作失当,这个时候他就需要进入normal模式,这个时候不能修改画布,只能在画布上移动,无论是移动你的手指和思绪,这个时候都不能对画布进行修改。这种特有的多模式也许是Vim和Emacs与其他大部分编辑器最显著的不同。 当你初窥Vim的与众不同后,如果你还不熟悉它的使用,你可能会不知所措,甚至无法编辑,无法退出,你和它会僵死在那里。你遇到的这种困境也正是Vim特有的操作方式引起的。这篇文章不打算如流水账般罗列Vim的诸多命令,我只挑选几种在日常代码编辑中最常用的命令来呈现Vim的神奇与强大。Vim之强大主要体现在无论是移动查询还是修改替换都能将一个动作做到非常小的粒度和精确控制,并且可以以极少的击键次数优雅地实现你精细的操作。我来举一个最常见的例子: ``` int i = 3 * (4 + 2); ``` 如上,假如我们想将括号中的内容改掉,一般的编辑器的做法都是移动到数字4,然后完全选中括号中的内容后修改。但是如果使用Vim,动作将会非常简单和快捷,只需移动到左括号后键入`ci(`即可,然后就可以直接进入insert模式修改了。敏感的读者可能已经感知到Vim的这条命令其实就是change...</p>
</section>
</a>
<!-- [[! /next_post ]] -->
<!-- [[! prev_post ]] -->
<a class="read-next-story prev no-cover" href="/kotlin-overview">
<section class="post">
<h2>Kotlin使用小计</h2>
<p>此文记录一次对Kotlin的技术分享,显然无法对Kotlin的方方面面都涉及到,只将一些在实际工作中频繁涉及到的要点做一个梳理,以期对Kotlin这们JVM语言有一个整体的认识。 为什么使用Kotlin 静态类型语言 同时支持面向对象和函数式编程范式 更强大语言表达能力 解决Java NPE问题,更安全 支持扩展函数 与Java的高互操作性 类和函数 我们只能继承声明为open 或 obstract的类 Unit 类似Java中的void...</p>
</section>
</a>
<!-- [[! /prev_post ]] -->
</aside>
<!-- /post -->
<footer class="site-footer clearfix">
<section class="copyright"><a href="/">与机器,人,神共舞</a> © 2024</section>
</footer>
</div>
<!-- [[! Ghost outputs important scripts and data with this tag ]] -->
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<!-- [[! The main JavaScript file for Casper ]] -->
<script type="text/javascript" src="/assets/js/jquery.fitvids.js"></script>
<script type="text/javascript" src="/assets/js/index.js"></script>
<!-- Add Google Analytics -->
<!-- Google Analytics Tracking code -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-78960009-1', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>