【发布时间】:2020-03-18 23:41:33
【问题描述】:
我有一个 RecyclerView,它使用 Glide 从 URL 加载图像。现在使用分页从 Firebase 检索 URL,如下所示。问题是,当 MainActivity(包含下面的代码和 recyclerview)第一次初始化时,UI 有很大的延迟(滚动非常缓慢和不连贯,选项菜单需要 3 秒才能打开等)并且图像需要同时加载。在我向下滚动并到达第一页数据的 RecyclerView 末尾后,触发 OnScrollListener 并开始从新查询中加载新数据。我已经尽力根据用户在我发布的另一篇帖子中的建议优化 Glide 所做的事情,并且我也将 adapter.setHasFixedSize 设置为 true,但没有运气。知道这里发生了什么吗?尽管查询是异步的,但我是否以某种方式挂起了 UI 线程?
编辑 : Glide 是否会导致主线程延迟,因为它必须将多个图像加载到回收器视图的 imageViews 中?如果是这样,我该如何应对?
以下是我如何处理从 Firebase 获得的数据的分页并通知适配器:
class MainActivity : AppCompatActivity() {
private val TAG: String = MainActivity::class.java.simpleName // Tag used for debugging
private var queryLimit : Long = 50 // how many documents should the query request from firebase
private lateinit var iconsRCV : RecyclerView // card icons recycler view
private lateinit var lastVisible:DocumentSnapshot
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rootRef: FirebaseFirestore = FirebaseFirestore.getInstance()
val urlsRef : CollectionReference = rootRef.collection("CardIconUrls")
val query : Query = urlsRef.orderBy("resID",Query.Direction.ASCENDING).limit(queryLimit) // create a query for the first queryLimit documents in the urlsRef collection
// Setting Toolbar default settings
val toolbar : Toolbar = findViewById(R.id.mainToolbar)
setSupportActionBar(toolbar) // set the custom toolbar as the support action bar
supportActionBar?.setDisplayShowTitleEnabled(false) // remove the default action bar title
// RecyclerView initializations
iconsRCV = findViewById(R.id.cardIconsRCV)
iconsRCV.layoutManager = GridLayoutManager(this,5) // set the layout manager for the rcv
val iconUrls : ArrayList<String> = ArrayList() // initialize the data with an empty array list
val adapter = CardIconAdapter(this,iconUrls) // initialize the adapter for the recyclerview
iconsRCV.adapter = adapter // set the adapter
iconsRCV.setHasFixedSize(true)
iconsRCV.addOnScrollListener(object:OnScrollListener(){
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if(!iconsRCV.canScrollVertically(1) && (newState == RecyclerView.SCROLL_STATE_IDLE) && ((iconsRCV.layoutManager as GridLayoutManager).findLastVisibleItemPosition() == (iconsRCV.layoutManager as GridLayoutManager).itemCount-1)) {
Log.d(TAG,"End of rcv-Starting query")
val nextQuery = urlsRef.orderBy("resID",Query.Direction.ASCENDING).startAfter(lastVisible).limit(queryLimit).get().addOnCompleteListener { task ->
if(task.isSuccessful) {
Log.d(TAG,"Next query called")
for(document:DocumentSnapshot in task.result!!) {
iconUrls.add(document.get("url").toString())
}
lastVisible = task.result!!.documents[task.result!!.size()-1]
adapter.notifyDataSetChanged()
}
}
}
}
})
query.get().addOnCompleteListener {task: Task<QuerySnapshot> ->
if(task.isSuccessful) {
Log.d(TAG,"Success")
for(document:DocumentSnapshot in task.result!!) {
Log.d(TAG,"Task size = " + task.result!!.size())
iconUrls.add(document.get("url").toString()) // add the url to the list
}
lastVisible = task.result!!.documents[task.result!!.size()-1]
adapter.notifyDataSetChanged() // notify the adapter about the new data
}
}
}
这是 recyclerview 适配器:
public class CardIconAdapter extends RecyclerView.Adapter<CardIconAdapter.ViewHolder> {
private List<String> urlsList;
private Context context;
class ViewHolder extends RecyclerView.ViewHolder {
ImageView iconImg;
ViewHolder(@NonNull View view) {
super(view);
iconImg = view.findViewById(R.id.cardIcon);
}
}
public CardIconAdapter(Context cntxt, List<String> data) {
context = cntxt;
urlsList = data;
}
@NonNull
@Override
public CardIconAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_icons_rcv_item,parent,false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull CardIconAdapter.ViewHolder holder, int position) {
RequestOptions requestOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL);
GlideApp.with(context).load(urlsList.get(position)).thumbnail(0.25f).centerCrop().dontTransform().apply(requestOptions).into(holder.iconImg);
}
@Override
public int getItemCount() {
return urlsList.size();
}
}
【问题讨论】:
-
@MartinZeitler 为什么它是重复的?在您链接的帖子中,我在 RecyclerView 中通过 Glide 更快地加载图像时遇到了问题,但问题已解决(尽管用户仍然没有添加答案),而在这篇文章中,我的 Recycler 视图存在性能问题(滞后, UI 滞后、删除以前的数据等)。
-
对我来说,这似乎是同一个问题;尝试缓存这些缩略图而不是即时缩小它们(这可能会浪费电池,因为它需要 CPU)。已经以预期的大小为它们提供服务将完全消除操纵它们的需要(并且 Glide 不需要这样做)。我的意思是,缩小一个图像是没有问题的 - 但缩小一大堆图像是。
-
@MartinZeitler 不会自动缓存它们吗?即使我没有即时对它们进行下采样,我仍然会遇到长时间加载问题,但现在回收器视图也滞后,并且之前的数据加载很奇怪(如果它们完全加载的话)
-
您的回收站视图实现有点不同。请发布您的firebase db节点结构数据将如何存储。
标签: android android-recyclerview google-cloud-firestore android-glide