मैं एसडीके डेमो नमूने से EfficientAdapter example के आधार पर बेसएडाप्टर का विस्तारित संस्करण उपयोग कर रहा हूं।एंड्रॉइड: दो अलग-अलग दृश्यों के साथ कुशल एडाप्टर
मेरा डेटा मूल रूप से एक ऑब्जेक्ट (ListPlaces
) है जिसमें listPlaces.getValues()
के माध्यम से सुलभ स्थानों की वास्तविक सूची के साथ ArrayList
है। इस ArrayList डेटा को श्रेणी द्वारा क्रमबद्ध किया गया है और ArrayList
में कुछ विशेष आइटम (विभाजक) शामिल हैं, बिना डेटा के, लेकिन separator
ध्वज true
पर सेट है।
अब जब भी मेरी EfficientAdapter
एक डेटा वस्तु है जो एक विभाजक यह public boolean isEnabled(int position)
के लिए false
वापस आती है और public View getView(int position, View convertView, ViewGroup parent)
पर मौजूदा डेटा वस्तु वास्तविक डेटा के होते हैं या सिर्फ एक विभाजक डमी है अगर आधार पर दो अलग-अलग लेआउट अनावश्यक रूप से बढ़ा है हो जाता है।
यह बहुत अच्छा काम करता है, अगर मैं हर बार लेआउट फुलाता हूं। हालांकि, हर बार लेआउट को फुलाकर और findViewById
पर कॉल करने से ListView
लगभग असामान्य रूप से धीमा हो जाता है।
इसलिए मैंने ViewHolder
दृष्टिकोण के साथ कुशल एडाप्टर का उपयोग करने की कोशिश की। लेकिन यह उन दो अलग-अलग विचारों के कारण बॉक्स से बाहर काम नहीं करता था, जिन्हें मैं एक्सेस करने का प्रयास करता हूं। इसलिए जब भी मेरा convertView != null
(अन्य मामला) हमारे ViewHolder
के माध्यम से लेआउट पर आइटम तक पहुंचता है और जब पिछला दृश्य एक विभाजक था, तो निश्चित रूप से यह टेक्स्टव्यू तक पहुंचने के लिए काम नहीं करता है जो केवल "वास्तविक" आइटम लेआउट पर उपलब्ध है ।
तो मैं भी मेरी getView()
लेआउट न केवल जब convertView == null
को बढ़ाने के लिए मजबूर, लेकिन यह भी जब पिछले listRow मौजूदा से अलग है: if (convertView == null || (listRow != listRow_previous)) { [....] }
यह लगता है लगभग अब काम करने के लिए। या कम से कम यह शुरुआत से ही दुर्घटनाग्रस्त नहीं होता है। लेकिन यह अभी भी दुर्घटनाग्रस्त है और मुझे नहीं पता कि मुझे क्या करना है। मैंने convertView.getID()
और convertView.getResources()
में देखने का प्रयास किया है, लेकिन यह अब तक वास्तव में सहायक नहीं था। हो सकता है कि किसी और के पास कोई विचार हो कि मैं कैसे जांच सकता हूं कि मेरे वर्तमान convertView
सूची आइटम लेआउट या सूची विभाजक लेआउट के साथ मेल खाता है या नहीं। धन्यवाद।
यहां कोड है। यह आसान को पढ़ने के लिए कहाँ कभी वहाँ एक [...] मैं बाहर कुछ कम महत्वपूर्ण कोड लिया है बनाने के लिए और समझने:
private class EfficientAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ListPlaces listPlaces;
private ListRow listRow;
private ListRow listRow_previous;
public EfficientAdapter(Context context, ListPlaces listPlaces) {
// Cache the LayoutInflate to avoid asking for a new one each time.
mInflater = LayoutInflater.from(context);
// Data
this.listPlaces = listPlaces;
}
/**
* The number of items in the list is determined by the number of items
* in our ArrayList
*
* @see android.widget.ListAdapter#getCount()
*/
public int getCount() {
return listPlaces.getValues().size();
}
/**
* Since the data comes from an array, just returning the index is
* sufficent to get at the data. If we were using a more complex data
* structure, we would return whatever object represents one row in the
* list.
*
* @see android.widget.ListAdapter#getItem(int)
*/
public Object getItem(int position) {
return position;
}
/**
* Use the array index as a unique id.
*
* @see android.widget.ListAdapter#getItemId(int)
*/
public long getItemId(int position) {
return position;
}
@Override
public boolean isEnabled(int position) {
// return false if item is a separator:
if(listPlaces.getValues().get(position).separator >= 0)
return false;
else
return true;
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
/**
* Make a view to hold each row.
*
* @see android.widget.ListAdapter#getView(int, android.view.View,
* android.view.ViewGroup)
*/
public View getView(int position, View convertView, ViewGroup parent) {
// Get the values for the current list element
ListPlacesValues curValues = listPlaces.getValues().get(position);
if (curValues.separator >= 0)
listRow = ListRow.SEPARATOR;
else
listRow = ListRow.ITEM;
Log.i(TAG,"Adapter: getView("+position+") " + listRow + " (" + listRow_previous + ") -> START");
// A ViewHolder keeps references to children views to avoid unneccessary calls
// to findViewById() on each row.
ViewHolder holder;
// When convertView is not null, we can reuse it directly, there is no need
// to reinflate it. We only inflate a new View when the convertView supplied
// by ListView is null.
if (convertView == null || (listRow != listRow_previous)) {
Log.i(TAG, "--> (convertView == null) at position: " + position);
// Creates a ViewHolder and store references to the two children views
// we want to bind data to.
holder = new ViewHolder();
if (listRow == ListRow.SEPARATOR) {
convertView = mInflater.inflate(R.layout.taxonomy_list_separator, null);
holder.separatorText = (TextView) convertView.findViewById(R.id.separatorText);
convertView.setTag(holder);
Log.i(TAG,"\tCREATE SEPARATOR: convertView ID: " + convertView.getId() + " Resource: " + convertView.getResources());
}
else {
convertView = mInflater.inflate(R.layout.taxonomy_listitem, null);
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.category = (TextView) convertView.findViewById(R.id.category);
// [...]
convertView.setTag(holder);
Log.i(TAG,"\tCREATE ITEM: convertView ID: " + convertView.getId() + " Resource: " + convertView.getResources());
}
} else {
// Get the ViewHolder back to get fast access to the TextView
// and the ImageView.
Log.i(TAG,"\tconvertView ID: " + convertView.getId() + " Resource: " + convertView.getResources());
holder = (ViewHolder) convertView.getTag();
convertView.setAnimation(null);
}
/* Bind the data efficiently with the holder */
if (listRow == ListRow.SEPARATOR) {
String separatorText;
switch (curValues.separator) {
case 0: separatorText="case 0"; break;
case 1: separatorText="case 1"; break;
case 2: separatorText="case 2"; break;
// [...]
default: separatorText="[ERROR]"; break;
}
holder.separatorText.setText(separatorText);
}
else {
// Set the name:
holder.name.setText(curValues.name);
// Set category
String cat = curValues.classification.toString();
cat = cat.substring(1,cat.length()-1); // removing "[" and "]"
if (cat.length() > 35) {
cat = cat.substring(0, 35);
cat = cat + "...";
}
holder.category.setText(cat);
// [...] (and many more TextViews and ImageViews to be set)
}
listRow_previous = listRow;
Log.i(TAG,"Adapter: getView("+position+") -> DONE");
return convertView;
}
private class ViewHolder {
TextView name;
TextView category;
// [...] -> many more TextViews and ImageViews
TextView separatorText;
}
}
और यहाँ मेरी Logcat उत्पादन:
755 ListPlaces_Activity I onPostExecute: notifyDataSetChanged()
755 ListPlaces_Activity I Adapter: getView(0) SEPARATOR (null) -> START
755 ListPlaces_Activity I --> (convertView == null) at position: 0
755 ListPlaces_Activity I CREATE SEPARATOR: convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(0) -> DONE
755 ListPlaces_Activity I Adapter: getView(1) ITEM (SEPARATOR) -> START
755 ListPlaces_Activity I --> (convertView == null) at position: 1
755 ListPlaces_Activity I CREATE ITEM: convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(1) -> DONE
755 ListPlaces_Activity I Adapter: getView(2) SEPARATOR (ITEM) -> START
755 ListPlaces_Activity I --> (convertView == null) at position: 2
755 ListPlaces_Activity I CREATE SEPARATOR: convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(2) -> DONE
755 ListPlaces_Activity I Adapter: getView(3) ITEM (SEPARATOR) -> START
755 ListPlaces_Activity I --> (convertView == null) at position: 3
755 ListPlaces_Activity I CREATE ITEM: convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(3) -> DONE
755 ListPlaces_Activity I Adapter: getView(4) ITEM (ITEM) -> START
755 ListPlaces_Activity I convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(4) -> DONE
755 ListPlaces_Activity I Adapter: getView(5) ITEM (ITEM) -> START
755 ListPlaces_Activity I convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(5) -> DONE
755 ListPlaces_Activity I Adapter: getView(6) ITEM (ITEM) -> START
755 ListPlaces_Activity I convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(6) -> DONE
755 ListPlaces_Activity I Adapter: getView(0) SEPARATOR (ITEM) -> START
755 ListPlaces_Activity I --> (convertView == null) at position: 0
755 ListPlaces_Activity I CREATE SEPARATOR: convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(0) -> DONE
755 ListPlaces_Activity I Adapter: getView(1) ITEM (SEPARATOR) -> START
755 ListPlaces_Activity I --> (convertView == null) at position: 1
755 ListPlaces_Activity I CREATE ITEM: convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(1) -> DONE
755 ListPlaces_Activity I Adapter: getView(2) SEPARATOR (ITEM) -> START
755 ListPlaces_Activity I --> (convertView == null) at position: 2
755 ListPlaces_Activity I CREATE SEPARATOR: convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(2) -> DONE
755 ListPlaces_Activity I Adapter: getView(3) ITEM (SEPARATOR) -> START
755 ListPlaces_Activity I --> (convertView == null) at position: 3
755 ListPlaces_Activity I CREATE ITEM: convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(3) -> DONE
755 ListPlaces_Activity I Adapter: getView(4) ITEM (ITEM) -> START
755 ListPlaces_Activity I convertView ID: 2131296317 Resource: [email protected]
755 ListPlaces_Activity I Adapter: getView(4) -> DONE
755 ListPlaces_Activity I Adapter: getView(5) ITEM (ITEM) -> START
755 ListPlaces_Activity I convertView ID: 2131296317 Resource: [email protected]
755 AndroidRuntime D Shutting down VM
755 dalvikvm W threadid=3: thread exiting with uncaught exception (group=0x4001aa28)
755 AndroidRuntime E Uncaught handler: thread main exiting due to uncaught exception
755 AndroidRuntime E java.lang.NullPointerException
755 AndroidRuntime E at com.tato.main.ListPlaces_Activity$EfficientAdapter.getView(ListPlaces_Activity.java:330)
755 AndroidRuntime E at android.widget.HeaderViewListAdapter.getView(HeaderViewListAdapter.java:191)
755 AndroidRuntime E at android.widget.AbsListView.obtainView(AbsListView.java:1255)
755 AndroidRuntime E at android.widget.ListView.makeAndAddView(ListView.java:1658)
755 AndroidRuntime E at android.widget.ListView.fillDown(ListView.java:637)
755 AndroidRuntime E at android.widget.ListView.fillFromTop(ListView.java:694)
755 AndroidRuntime E at android.widget.ListView.layoutChildren(ListView.java:1502)
755 AndroidRuntime E at android.widget.AbsListView.onLayout(AbsListView.java:1112)
755 AndroidRuntime E at android.view.View.layout(View.java:6569)
755 AndroidRuntime E at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
755 AndroidRuntime E at android.widget.LinearLayout.layoutVertical(LinearLayout.java:998)
755 AndroidRuntime E at android.widget.LinearLayout.onLayout(LinearLayout.java:918)
755 AndroidRuntime E at android.view.View.layout(View.java:6569)
755 AndroidRuntime E at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
755 AndroidRuntime E at android.view.View.layout(View.java:6569)
755 AndroidRuntime E at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
755 AndroidRuntime E at android.widget.LinearLayout.layoutVertical(LinearLayout.java:998)
755 AndroidRuntime E at android.widget.LinearLayout.onLayout(LinearLayout.java:918)
755 AndroidRuntime E at android.view.View.layout(View.java:6569)
755 AndroidRuntime E at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
755 AndroidRuntime E at android.view.View.layout(View.java:6569)
755 AndroidRuntime E at android.view.ViewRoot.performTraversals(ViewRoot.java:979)
755 AndroidRuntime E at android.view.ViewRoot.handleMessage(ViewRoot.java:1613)
755 AndroidRuntime E at android.os.Handler.dispatchMessage(Handler.java:99)
755 AndroidRuntime E at android.os.Looper.loop(Looper.java:123)
755 AndroidRuntime E at android.app.ActivityThread.main(ActivityThread.java:4203)
755 AndroidRuntime E at java.lang.reflect.Method.invokeNative(Native Method)
755 AndroidRuntime E at java.lang.reflect.Method.invoke(Method.java:521)
755 AndroidRuntime E at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
755 AndroidRuntime E at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
755 AndroidRuntime E at dalvik.system.NativeStart.main(Native Method)
क्या आप एक टिप्पणी जोड़ सकते हैं जिसमें दिखाया गया है कि लाइन 300 है जो स्टैकट्रैक में है? यदि यह 'if (curValues.separator> = 0) है, तो क्या आप सूची के अंत में 1 तक पदों को संभालने में सक्षम होना चाहिए? – rsp