RecyclerView的基本用法 (四)

来源:互联网 发布:免费x站最新域名升级 编辑:程序博客网 时间:2024/05/23 23:59


本篇承接上一篇需要回答的问题,即自定义LayoutManager为何用,何时用及怎么用的问题。那么首先引经据典,Dave Smith在其博文中有很简单易懂的回答,原文于此。


Building The Core

A LayoutManager implementation is responsible for attaching, measuring, and laying out all the child views it needs in real-time. As the user scrolls the view, it will be up to the layout manager to determine when new child views need to be added, and old views can be detached and scrapped.


从上可以知道,LayoutManager是负责实时在需要时对子view进行attaching,measuring和layout,比如当用户滑动列表时,将由LayoutManager来决定何时需要添加新的item即列表的子view,以及何时将它们detach并放入废品站。那么久引申出recyclerview做何事情,二者的关系是如何。


The Recycler

First, a bit of insight into how the API is structured. Your LayoutManager is given access to a Recyclerinstance at key points in the process when you might need to recycle old views, or obtain new views from a potentially recycled previous child.

The Recycler also removes the need to directly access the view’s current adapter implementation. When your LayoutManager requires a new child view, simply call getViewForPosition() and the Recycler will return the view with the appropriate data already bound. The Recycler takes care of determining whether a new view must be created, or if an existing scrapped view gets reused. Your responsibility, inside your LayoutManager, is to ensure that views which are no longer visible get passed to the Recycler in a timely manner; this will keep the Recycler from creating more view objects than is necessary.


通过看源码可以知道LayoutManager是RecyclerView的一个内部类,那么不难解释上面所说,当需要回收旧View或者从废品站中取回新View时LayoutManager有访问recyclerview的权限。当你的LayoutManager需要一个新的子view只需要调用recyclerview的getViewForPosition() 方法就可以得到。recyclerview的负责决定是否需要创建新view或者决定已存在于废品站的view是否需要重用。而LayoutManager就需要保证屏幕外的view能够及时传递给recyclerview,这将保证recyclerview不会创建多余的view对象。那么接下来就需要对试图的回收机制作一个简单的了解。


Detach vs. Remove

There are two ways to handle existing child views during a layout update: detach and remove. Detach is meant to be a lightweight operation for reordering views. Views that are detached are expected to be re-attached before your code returns. This can be used to modify the indices of attached child views without re-binding or re-creating those views through the Recycler.

Remove is meant for views that are no longer needed. Any view that is permanently removed should be placed in the Recycler for later re-use, but the API does not enforce this. It is up to you whether the views you remove also get recycled.

Scrap vs. Recycle

Recycler has a two-level view caching system: the scrap heap and the recycle pool. The scrap heap represents a lighter weight collection where views can be returned to the LayoutManager directly without passing through the adapter again. Views are typically placed here when they are temporarily being detached, but will be re-used within the same layout pass. The recycle pool consists of views that are assumed to have incorrect data (data from a different position), so they will always be passed through the adapter to have data re-bound before they are returned to the LayoutManager.

When attempting to supply the LayoutManager with a new view, a Recycler will first check the scrap heap for a matching position/id; if one exists, it will be returned without re-binding to the adapter data. If no matching view is found, the Recycler will instead pull a suitable view from the recycle pool and bind the necessary data to it from the adapter (i.e. RecyclerView.Adapter.bindViewHolder() is invoked) before returning it. In cases where no valid views exist in the recycle pool, a new view will be created instead (i.e. RecyclerView.Adapter.createViewHolder() is invoked) before being bound, and returned.

Rule of Thumb

The LayoutManager API lets you do pretty much all of these tasks independently if you wish, so the possible combinations can be a bit numerous. In general, use detachAndScrapView() for views you want to temporarily reorganize and expect to re-attach inside the same layout pass. Use removeAndRecycleView()for views you no longer need based on the current layout.


上面所述主要是讲大概的回收机制以及在这个机制中recyclerview和layoutmanager之间分别所作的事,非常言简意赅。而到目前为止,我们基本上解决了LayoutManager为何用的问题。那么何时用的问题也就迎刃而解了,因为上面清楚的解释到,LayoutManager是用来解决子view的attaching,measuring和layout问题的,换个角度来讲,如果官方只有一个LinearLayoutManager,那么我们需要通过修改LinearLayoutManager来实现GridLayoutManager或者StaggeredGridLayoutManager所实现的效果,也就是说当列表子view无法用现有的manager实现时,我们就应当自定义LayoutManager了。就如同后面我们会深入研究的如下效果一样:




dave在博文回答问题时这样解释了自定义LayoutManager的一种使用场景:


RecyclerView doesn't really have a good mechanism (yet) for handling these types of "extra" views (i.e. views that don't really have a data position but need to be in the layout). RecyclerView adapters do support view types, so placing headers inline with your data items is possible. However, the view types are not exposed to the layout manager (and LayoutManager is really designed not to touch the adapter directly), so it's hard to make judgements in your layout based on type. You could pack additional data in the ViewHolder indicating a header view, and reacting to any attached header views inside of onLayoutChildren(), scrollXXXBy(), etc.

Also, keep in mind that standard layout managers assume all attached views can be shifted uniformly, so they would try to move any header views for you. You would have to account for that in your extension.



下一篇我们会沿着dave的脚步来解答第三个问题,自定义LayoutManager怎么用。




0 0