【发布时间】:2017-12-02 02:44:06
【问题描述】:
我有一个 recyclerview 加载一组主要显示图像的项目。我在后台检索这些项目,每批 100 个。我使用 Picasso 加载图像。图片很大,但我使用 fit() 调整它们的大小。
每当使用 SwipeRefreshLayout 加载或刷新屏幕时,UI 都会阻塞不到一秒,但足以引起注意。如果我不加载图像而只放置文本,则不会发生 UI 块。
我在 Picasso 上放置了日志行,每次刷新都会检索 100 张图像,但我猜 Picasso 是在后台线程中工作?
适配器:
@ActivityScope
class LimitableListAdapter @Inject constructor() : RecyclerView.Adapter<LimitableListAdapter.ViewHolder>() {
private var events: MutableList<Event> = mutableListOf()
private var itemClick: ((Event, View) -> Unit)? = null
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val binding : ItemVideoGridScoreBinding = holder.binding
var viewModel = binding.viewModel
val event = events[position]
//Unbind old viewModel if we have one
viewModel?.unbind()
// Create new ViewModel, set it, and bind it
viewModel = EventViewModel(event)
binding.viewModel = viewModel
viewModel.bind()
holder.setClickListener(itemClick)
}
override fun getItemCount(): Int = events.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = DataBindingUtil.inflate<ItemVideoGridScoreBinding>(
LayoutInflater.from(parent.context),
R.layout.item_video_grid_score,
parent,
false
)
return ViewHolder(binding)
}
fun updateEvents(events: List<Event>, stride: Int) {
var size = this.events.size
Timber.w("Updating with: " + events.joinToString(",", transform = { e -> e.id.toString() }))
this.events = events.toMutableList()
notifyDataSetChanged()
/*if (size == 0) {
Timber.w("branch 1")
var mutableList = events.toMutableList()
if(mutableList.size == 0)
return
mutableList.add(Event.mockEvent(stride))
this.events.addAll(mutableList)
notifyDataSetChanged()
} else {
if (size > 2) {
Timber.w("branch 2.1")
this.events.addAll(size - 1, events.toMutableList())
notifyItemRangeChanged(size-1, events.size)
}
else {
Timber.w("branch 2.2")
this.events.addAll(size, events.toMutableList())
notifyItemRangeChanged(size, events.size)
}
}*/
Timber.i("New list is: " + this.events.joinToString(",", transform = { e -> e.id.toString() }))
}
fun clearList(){
this.events.clear()
notifyDataSetChanged()
}
fun setClickListener(itemClick: ((Event, View) -> Unit)?) {
this.itemClick = itemClick
}
class ViewHolder(val binding: ItemVideoGridScoreBinding) : RecyclerView.ViewHolder(binding.root) {
fun setClickListener(callback: ((Event, View) -> Unit)?) {
binding.viewModel.clicks().subscribe() {
callback?.invoke(binding.viewModel.event, itemView)
}
}
}
}
BindingUtils:
@BindingAdapter({"app:coverUrl"})
public static void loadCover(ImageView view, String imageUrl) {
Picasso p = Picasso.with(view
.getContext());
p.setIndicatorsEnabled(true);
p.load(imageUrl)
.fit()
.centerInside()
.error(R.drawable.ic_broken_image)
.into(view);
}
}
xml:
(...)
<ImageView
android:id="@+id/event_cover"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
app:coverUrl="@{videoItem.cover}"
tools:src="@drawable/img"
/>
(...)
【问题讨论】:
-
输入你的适配器代码
-
@diegoveloper 发布
-
同时检索100张图片并通知ui是一项繁重的工作。我也不认为您同时显示所有这些图像。所以可以考虑实现分页。
-
即使每页有 20 个,也会发生 UI 阻塞...
-
用 Glide 代替 Picasso Glide 比 Picasso 更快更高效。 Glide 性能比较在这里。 medium.com/@multidots/glide-vs-picasso-930eed42b81d看看性能有没有提升。
标签: android android-recyclerview picasso