/** * Get a view and have it show the data associated with the specified * position. This is called when we have already discovered that the view is * not available for reuse in the recycle bin. The only choices left are * converting an old view or making a new one. * * @param position The position to display * @param isScrap Array of at least 1 boolean, the first entry will become true if * the returned view was taken from the scrap heap, false if otherwise. * * @return A view displaying the data associated with the specified position */ View obtainView(int position, boolean[] isScrap) { isScrap[0] = false; // Check whether we have a transient state view. Attempt to re-bind the // data and discard the view if we fail. finalViewtransientView= mRecycler.getTransientStateView(position); if (transientView != null) { finalLayoutParamsparams= (LayoutParams) transientView.getLayoutParams(); // If the view type hasn't changed, attempt to re-bind the data. if (params.viewType == mAdapter.getItemViewType(position)) { finalViewupdatedView= mAdapter.getView(position, transientView, this); // If we failed to re-bind the data, scrap the obtained view. if (updatedView != transientView) { setItemViewLayoutParams(updatedView, position); mRecycler.addScrapView(updatedView, position); } } isScrap[0] = true; // Finish the temporary detach started in addScrapView(). transientView.dispatchFinishTemporaryDetach(); return transientView; } finalViewscrapView= mRecycler.getScrapView(position); finalViewchild= mAdapter.getView(position, scrapView, this); if (scrapView != null) { if (child != scrapView) { // Failed to re-bind the data, return scrap to the heap. mRecycler.addScrapView(scrapView, position); } else { isScrap[0] = true; // Finish the temporary detach started in addScrapView(). child.dispatchFinishTemporaryDetach(); } } ...... // 省略部分代码 return child; }
private RecyclerListener mRecyclerListener; /** * The position of the first view stored in mActiveViews. */ // 第一个活动view的position,即第一个可视view的position privateint mFirstActivePosition; /** * Views that were on screen at the start of layout. This array is populated at the start of * layout, and at the end of layout all view in mActiveViews are moved to mScrapViews. * Views in mActiveViews represent a contiguous range of Views, with position of the first * view store in mFirstActivePosition. */ // 活动view的集合 private View[] mActiveViews = newView[0]; /** * Unsorted views that can be used by the adapter as a convert view. */ /**废弃的可修复view集合,复用时传递到Adapter#getView方法的convertView参数。 * 因为item type可能大于1,只有view type相同的view之间才能复用,所以是个二维数组 */ private ArrayList<View>[] mScrapViews; // ListView item type数量 privateint mViewTypeCount; // 当前的废弃view数组,定义这个成员是为了在mViewTypeCount为1时使用方便,不需要去取mScrapViews的第一个元素 private ArrayList<View> mCurrentScrap; // 被跳过的,不能复用的view集合。view type小于0或者处理transient状态的view不能被复用。 private ArrayList<View> mSkippedScrap; // 处于 transient状态的view集合,处于transient状态的view不能被复用,如view的动画正在播放, // transient是瞬时、过渡的意思,关于transient状态详见android.view.View#PFLAG2_HAS_TRANSIENT_STATE private SparseArray<View> mTransientStateViews; // 如果adapter的hasStableIds方法返回true,处于过度状态的view保存到这里。因为需要保存view的position,而且处于过度状态的view一般很少, // 这2个成员用了稀疏数组。具体不需要case,知道是保存转换状态view的集合就行。 private LongSparseArray<View> mTransientStateViewsById;
A class that describes a view hierarchy that can be displayed in
another process. The hierarchy is inflated from a layout resource
file, and this class provides some basic operations for modifying the
content of the inflated hierarchy.