2010-12-31 14 views
27

は私のカスタムCursorAdapterです:ViewHolderパターンがカスタムCursorAdapterに正しく実装されていますか?ここ

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; 
    } 

} 

はViewHolderパターンの制約には、この秋にしていますか?これはCursorAdapterなので、わからなかった。そこにはgetViewがなかった。問題や提案がある場合は、それらを指摘してください。

答えて

45

CursorAdapterは、新しい行が必要になるたびにnewViewを呼び出しません。既にViewがある場合は、bindViewを呼び出します。そのため、作成されたビューは実際に再利用されます。

コメントにJosephが指摘したように、findViewByIdを繰り返し呼び出すのを避けるために、ViewHolderを使用することができます。

あなたはまだ、効率を懸念している場合は、WeakHashMapを使用していますSimpleCursorAdapter実装、(WeakReferencesのマップ)を見てみましょうは:クラスの

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

は、だから私はView.findViewById(int型)のような高価な電話をかけることができて、私のアプリケーションが遅れないのだろうか? –

+16

'findViewById(int)'は思ったほど高価ではありません。参照を返します(存在する場合)。 ViewHolder技術は、他の種類の問題を解決するために存在します。本当に必要なビュー以上のビューを作成しない(したがって、高価なビューインプレッションを避ける)。 – Cristian

+1

@クリスチャン、ありがとう。私は 'newView'と' bindView'を使って、クラスを 'SimpleCursorAdapter'に拡張させました。以下のコードを参照してください。 –

1

私の実装では、newViewbindViewで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は、newView()bindView()に委譲して行リサイクルを実施するgetView()の実装を持っています。

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); 
     } 
    } 
} 
関連する問題