एंटोन के समाधान के बाद, इसके साथ आते हैं ViewHolder
जो विभिन्न प्रकार के लेआउट रखता / संभालता है। लेकिन यकीन नहीं है कि रीसाइक्लिंग लेआउट ViewHolder
के डेटा रोल का प्रकार नहीं होने पर नए लेआउट की जगह काम करेगी ।
इसलिए मूल रूप से,
onCreateViewHolder(ViewGroup parent, int viewType)
केवल तभी कहा जाता है जब नए दृश्य लेआउट की आवश्यकता होती है;
getItemViewType(int position)
के लिए बुलाया जाएगा viewType
;
onBindViewHolder(ViewHolder holder, int position)
हमेशा कहा जाता है जब दृश्य को पुनर्चक्रित किया जाता है (नया डेटा लाया जाता है और उस के साथ प्रदर्शित करने का प्रयास करें ViewHolder
)।
तो जब onBindViewHolder
यह कहा जाता है तो इसे सही दृश्य लेआउट में डालना चाहिए और अपडेट करना होगा ViewHolder
।
जिस तरह से ViewHolder
या किसी भी समस्या में लाया जा सकता है, उसके लिए व्यू लेआउट को बदलने का तरीका सही है? किसी भी टिप्पणी की सराहना!
public int getItemViewType(int position) {
TypedData data = mDataSource.get(position);
return data.type;
}
public ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
return ViewHolder.makeViewHolder(parent, viewType);
}
public void onBindViewHolder(ViewHolder holder,
int position) {
TypedData data = mDataSource.get(position);
holder.updateData(data);
}
///
public static class ViewHolder extends
RecyclerView.ViewHolder {
ViewGroup mParentViewGroup;
View mCurrentViewThisViewHolderIsFor;
int mDataType;
public TypeOneViewHolder mTypeOneViewHolder;
public TypeTwoViewHolder mTypeTwoViewHolder;
static ViewHolder makeViewHolder(ViewGroup vwGrp,
int dataType) {
View v = getLayoutView(vwGrp, dataType);
return new ViewHolder(vwGrp, v, viewType);
}
static View getLayoutView(ViewGroup vwGrp,
int dataType) {
int layoutId = getLayoutId(dataType);
return LayoutInflater.from(vwGrp.getContext())
.inflate(layoutId, null);
}
static int getLayoutId(int dataType) {
if (dataType == TYPE_ONE) {
return R.layout.type_one_layout;
} else if (dataType == TYPE_TWO) {
return R.layout.type_two_layout;
}
}
public ViewHolder(ViewGroup vwGrp, View v,
int dataType) {
super(v);
mDataType = dataType;
mParentViewGroup = vwGrp;
mCurrentViewThisViewHolderIsFor = v;
if (data.type == TYPE_ONE) {
mTypeOneViewHolder = new TypeOneViewHolder(v);
} else if (data.type == TYPE_TWO) {
mTypeTwoViewHolder = new TypeTwoViewHolder(v);
}
}
public void updateData(TypeData data) {
mDataType = data.type;
if (data.type == TYPE_ONE) {
mTypeTwoViewHolder = null;
if (mTypeOneViewHolder == null) {
View newView = getLayoutView(mParentViewGroup,
data.type);
/**
* how to replace new view with
the view in the parent
view container ???
*/
replaceView(mCurrentViewThisViewHolderIsFor,
newView);
mCurrentViewThisViewHolderIsFor = newView;
mTypeOneViewHolder =
new TypeOneViewHolder(newView);
}
mTypeOneViewHolder.updateDataTypeOne(data);
} else if (data.type == TYPE_TWO){
mTypeOneViewHolder = null;
if (mTypeTwoViewHolder == null) {
View newView = getLayoutView(mParentViewGroup,
data.type);
/**
* how to replace new view with
the view in the parent view
container ???
*/
replaceView(mCurrentViewThisViewHolderIsFor,
newView);
mCurrentViewThisViewHolderIsFor = newView;
mTypeTwoViewHolder =
new TypeTwoViewHolder(newView);
}
mTypeTwoViewHolder.updateDataTypeOne(data);
}
}
}
public static void replaceView(View currentView,
View newView) {
ViewGroup parent = (ViewGroup)currentView.getParent();
if(parent == null) {
return;
}
final int index = parent.indexOfChild(currentView);
parent.removeView(currentView);
parent.addView(newView, index);
}
संपादित करें: ViewHolder दृश्य को धारण करने के लिए सदस्य mItemViewType है
संपादित करें: onBindViewHolder (ViewHolder धारक, int स्थिति) में ऐसा दिखता है कि इसमें मिला ViewHolder उठाया गया है (या बनाया गया) getItemViewType (int स्थिति) को देखते हुए सुनिश्चित करें कि यह एक मैच है, इसलिए वहां चिंता करने की आवश्यकता नहीं है कि ViewHolder प्रकार डेटा [स्थिति] के प्रकार से मेल नहीं खाता है। क्या किसी को अधिक पता है कि ऑनबॉन्ड व्यूहॉल्डर () में ViewHolder कैसे उठाया जाता है?
संपादित करें: ऐसा लगता है कि रीसायकल ViewHolder
प्रकार द्वारा चुना गया है, इसलिए वहां कोई योद्धा नहीं है।
संपादित करें: http://wiresareobirect.com/2014/09/building-a-recyclerview-layoutmanager-part-1/ इस सवाल का जवाब देता है।
इसे रीसायकल मिलता है ViewHolder
जैसे:
holder = getRecycledViewPool().getRecycledView(mAdapter.getItemViewType(offsetPosition));
या ViewHolder
सही प्रकार का रीसायकल न मिलने पर नया बनाएं ।
public ViewHolder getRecycledView(int viewType) {
final ArrayList<ViewHolder> scrapHeap = mScrap.get(viewType);
if (scrapHeap != null && !scrapHeap.isEmpty()) {
final int index = scrapHeap.size() - 1;
final ViewHolder scrap = scrapHeap.get(index);
scrapHeap.remove(index);
return scrap;
}
return null;
}
View getViewForPosition(int position, boolean dryRun) {
......
if (holder == null) {
final int offsetPosition = mAdapterHelper.findPositionOffset(position);
if (offsetPosition < 0 || offsetPosition >= mAdapter.getItemCount()) {
throw new IndexOutOfBoundsException("Inconsistency detected. Invalid item "
+ "position " + position + "(offset:" + offsetPosition + ")."
+ "state:" + mState.getItemCount());
}
final int type = mAdapter.getItemViewType(offsetPosition);
// 2) Find from scrap via stable ids, if exists
if (mAdapter.hasStableIds()) {
holder = getScrapViewForId(mAdapter.getItemId(offsetPosition), type, dryRun);
if (holder != null) {
// update position
holder.mPosition = offsetPosition;
fromScrap = true;
}
}
if (holder == null && mViewCacheExtension != null) {
// We are NOT sending the offsetPosition because LayoutManager does not
// know it.
final View view = mViewCacheExtension
.getViewForPositionAndType(this, position, type);
if (view != null) {
holder = getChildViewHolder(view);
if (holder == null) {
throw new IllegalArgumentException("getViewForPositionAndType returned"
+ " a view which does not have a ViewHolder");
} else if (holder.shouldIgnore()) {
throw new IllegalArgumentException("getViewForPositionAndType returned"
+ " a view that is ignored. You must call stopIgnoring before"
+ " returning this view.");
}
}
}
if (holder == null) { // fallback to recycler
// try recycler.
// Head to the shared pool.
if (DEBUG) {
Log.d(TAG, "getViewForPosition(" + position + ") fetching from shared "
+ "pool");
}
holder = getRecycledViewPool()
.getRecycledView(mAdapter.getItemViewType(offsetPosition));
if (holder != null) {
holder.resetInternal();
if (FORCE_INVALIDATE_DISPLAY_LIST) {
invalidateDisplayListInt(holder);
}
}
}
if (holder == null) {
holder = mAdapter.createViewHolder(RecyclerView.this,
mAdapter.getItemViewType(offsetPosition));
if (DEBUG) {
Log.d(TAG, "getViewForPosition created new ViewHolder");
}
}
}
boolean bound = false;
if (mState.isPreLayout() && holder.isBound()) {
// do not update unless we absolutely have to.
holder.mPreLayoutPosition = position;
} else if (!holder.isBound() || holder.needsUpdate() || holder.isInvalid()) {
if (DEBUG && holder.isRemoved()) {
throw new IllegalStateException("Removed holder should be bound and it should"
+ " come here only in pre-layout. Holder: " + holder);
}
final int offsetPosition = mAdapterHelper.findPositionOffset(position);
mAdapter.bindViewHolder(holder, offsetPosition);
attachAccessibilityDelegate(holder.itemView);
bound = true;
if (mState.isPreLayout()) {
holder.mPreLayoutPosition = position;
}
}
final ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
final LayoutParams rvLayoutParams;
if (lp == null) {
rvLayoutParams = (LayoutParams) generateDefaultLayoutParams();
holder.itemView.setLayoutParams(rvLayoutParams);
} else if (!checkLayoutParams(lp)) {
rvLayoutParams = (LayoutParams) generateLayoutParams(lp);
holder.itemView.setLayoutParams(rvLayoutParams);
} else {
rvLayoutParams = (LayoutParams) lp;
}
rvLayoutParams.mViewHolder = holder;
rvLayoutParams.mPendingInvalidate = fromScrap && bound;
return holder.itemView;
}