2010-12-31 11 views
27

यहाँ मेरी कस्टम CursorAdapter है: ViewHolder पैटर्न की कमी में इस गिरावटकस्टमहोसर एडाप्टर में सहीहोल्डर पैटर्न सही ढंग से कार्यान्वित किया गया है?

public class TasksAdapter extends CursorAdapter implements Filterable { 

    private final Context context; 

    public TasksAdapter(Context context, Cursor c) { 
     super(context, c); 
     this.context = context; 
    } 

    /** 
    * @see android.widget.CursorAdapter#newView(android.content.Context, android.database.Cursor, android.view.ViewGroup) 
    */ 
    @Override 
    public View newView(Context context, Cursor cursor, ViewGroup parent) { 
     LayoutInflater inflater = LayoutInflater.from(context); 
     View v = inflater.inflate(android.R.layout.simple_list_item_checked, parent, false);   

     ViewHolder holder = new ViewHolder(); 
     holder.textview = (CheckedTextView)v.findViewById(android.R.id.text1); 
     v.setTag(holder); 

     return v; 
    } 

    /** 
    * @see android.widget.CursorAdapter#bindView(android.view.View, android.content.Context, android.database.Cursor) 
    */ 
    @Override 
    public void bindView(View view, Context context, Cursor cursor) { 

     ViewHolder holder = (ViewHolder)view.getTag(); 
     int titleCol = cursor.getColumnIndexOrThrow(Tasks.TITLE); 
     int completedCol = cursor.getColumnIndexOrThrow(Tasks.COMPLETED); 

     String title = cursor.getString(titleCol); 
     boolean completed = Util.intToBool(cursor.getInt(completedCol)); 

     holder.textview.setText(title); 
     holder.textview.setChecked(completed); 
    } 

    /** 
    * @see android.widget.CursorAdapter#runQueryOnBackgroundThread(java.lang.CharSequence) 
    */ 
    @Override 
    public Cursor runQueryOnBackgroundThread(CharSequence constraint) { 

     StringBuffer buffer = null; 
     String[] args = null; 

     if (constraint != null) { 
      buffer = new StringBuffer(); 
      buffer.append("UPPER ("); 
      buffer.append(Tasks.TITLE); 
      buffer.append(") GLOB ?"); 
      args = new String[] { "*" + constraint.toString().toUpperCase() + "*" }; 
     } 

     Cursor c = context.getContentResolver().query(Tasks.CONTENT_URI, 
      null, (buffer == null ? null : buffer.toString()), args, 
      Tasks.DEFAULT_SORT_ORDER); 

     c.moveToFirst(); 
     return c; 
    } 

    /** 
    * @see android.widget.CursorAdapter#convertToString(android.database.Cursor) 
    */ 
    @Override 
    public CharSequence convertToString(Cursor cursor) { 
     final int titleCol = cursor.getColumnIndexOrThrow(Tasks.TITLE); 
     String title = cursor.getString(titleCol); 
     return title; 
    } 

    static class ViewHolder { 
     CheckedTextView textview; 
    } 

} 

करता है? मुझे यकीन नहीं था क्योंकि यह एक कर्सर एडाप्टर था, जहां getView नहीं था। अगर कोई समस्या या सुझाव हैं, तो क्या आप उन्हें इंगित कर सकते हैं।

उत्तर

45

CursorAdapter प्रत्येक बार इसे एक नई पंक्ति की आवश्यकता होने पर newView पर कॉल नहीं करेगा; यदि यह पहले से ही View है, तो यह bindView पर कॉल करेगा, इसलिए निर्मित दृश्य वास्तव में पुन: उपयोग किया जाता है।

कहा गया है कि टिप्पणियों में जोसेफ द्वारा इंगित किया गया है, आप अभी भी findViewById पर कॉल करने से बचने के लिए व्यूहोल्डर का उपयोग कर सकते हैं।

आप अभी भी क्षमता के बारे में चिंतित हैं, तो उसके बाद SimpleCursorAdapter कार्यान्वयन पर एक नज़र है, जो एक WeakHashMap (एक WeakReferences के नक्शे) का उपयोग करता ले:

WeakHashMap<View, View[]> mHolders = new WeakHashMap<View, View[]>(); 
+2

तो मैं View.findViewById (int) की तरह महंगा कॉल कर सकते हैं और अपने आवेदन अंतराल नहीं होगा? –

+16

'findViewById (int)' उतना महंगा नहीं है जितना आप सोचते हैं। यह केवल एक संदर्भ लौटाएगा (यदि कोई मौजूद है)। व्यूहोल्डर तकनीक अन्य प्रकार की समस्याओं को हल करने के लिए मौजूद है: आपको वास्तव में जो चाहिए उससे अधिक दृश्य न बनाएं (इस प्रकार, यह अत्यधिक दृश्य inflations से बचाता है, जो महंगा है)। – Cristian

+1

@ क्रिस्टियन, धन्यवाद। मैंने कक्षा को 'SimpleCursorAdapter' तक विस्तारित करने के लिए 'newView' और 'bindView' का उपयोग किया। नीचे दिया गया कोड देखें। –

1

एक वर्ग की मेरी कार्यान्वयन newView और bindView साथ फैली SimpleCursorAdapter लेकिन ViewHolder पैटर्न के बिना

private class CountriesAdapter extends SimpleCursorAdapter { 

      private LayoutInflater mInflater; 

      public CountriesAdapter(Context context, int layout, Cursor cursor, String[] from, 
        int[] to, LayoutInflater inflater) { 
       super(getActivity(), layout, cursor, from, to, CURSOR_ADAPTER_FLAGS); 
       mInflater = inflater; 
      } 

      @Override 
      public View newView(Context context, Cursor cursor, ViewGroup parent) { 
       return mInflater.inflate(R.layout.countries_list_row, parent, false); 
      } 

      @Override 
      public void bindView(View rowView, Context context, Cursor cursor) { 

       TextView tvCountry = (TextView) rowView.findViewById(R.id.countriesList_tv_countryName); 
       TextView tvOrgs = (TextView) rowView.findViewById(R.id.countriesList_tv_orgNames); 
       ImageView ivContinent = 
         (ImageView) rowView.findViewById(R.id.countriesList_iv_continentName); 

       // TODO: set texts of TextViews and an icon here 
       } 

      } 
    } 
7

आप newView() औरअधिभावी रहे हैं, आपको getView() में कुछ भी अतिरिक्त करने की आवश्यकता नहीं है। CursorAdapter में getView() का कार्यान्वयन है जो पंक्ति रीसाइक्लिंग को लागू करने के लिए newView() और bindView() पर प्रतिनिधि करता है।

findViewById() शायद ListView की स्क्रॉलिंग के दौरान अक्सर बुलाया जाता है, जो प्रदर्शन को धीमा कर सकता है। यहां तक ​​कि जब Adapter रीसाइक्लिंग के लिए एक फुलाया दृश्य देता है, तब भी आपको तत्वों को देखने और उन्हें अपडेट करने की आवश्यकता होती है। इससे बचने के लिए, ViewHolder पैटर्न उपयोगी है।

यहाँ ViewHolder पैटर्न का एक उदाहरण एक मौसम अनुप्रयोग के लिए लागू किया गया है:

public class ForecastAdapter extends CursorAdapter { 

    public ForecastAdapter(Context context, Cursor cursor, int flags) { 
     super(context, cursor, flags); 
    } 

    @Override 
    public View newView(Context context, Cursor cursor, ViewGroup parent) { 
     View view = LayoutInflater.from(context).inflate(
       R.layout.list_item_forecast, parent, false); 
     ViewHolder viewHolder = new ViewHolder(view); 
     view.setTag(viewHolder); 
     return view; 
    } 

    @Override 
    public void bindView(View view, Context context, Cursor cursor) { 
     ViewHolder viewHolder = (ViewHolder) view.getTag(); 

     long date = cursor.getLong(ForecastFragment.COL_WEATHER_DATE); 
     viewHolder.dateView.setText("Today"); 

     String weatherForecast = 
       cursor.getString(ForecastFragment.COL_WEATHER_DESC); 
     viewHolder.descriptionView.setText(weatherForecast); 

     double high = cursor.getFloat(ForecastFragment.COL_WEATHER_MAX_TEMP); 
     viewHolder.highTempView.setText("30"); 

     double low = cursor.getFloat(ForecastFragment.COL_WEATHER_MIN_TEMP); 
     viewHolder.lowTempView.setText("24"); 

     int weatherConditionId = 
       cursor.getInt(ForecastFragment.COL_WEATHER_CONDITION_ID); 
     viewHolder.iconView.setImageResource(R.drawable.ic_snow); 
    } 

    /** Cache of the children views for a list item. */ 
    public static class ViewHolder { 
     public final ImageView iconView; 
     public final TextView dateView; 
     public final TextView descriptionView; 
     public final TextView highTempView; 
     public final TextView lowTempView; 

     public ViewHolder(View view) { 
      iconView = 
        (ImageView) view.findViewById(R.id.item_icon); 
      dateView = 
        (TextView) view.findViewById(R.id.item_date_textview); 
      descriptionView = 
        (TextView) view.findViewById(R.id.item_forecast_textview); 
      highTempView = 
        (TextView) view.findViewById(R.id.item_high_textview); 
      lowTempView = 
        (TextView) view.findViewById(R.id.item_low_textview); 
     } 
    } 
} 
संबंधित मुद्दे