1

目標:アプリケーションは、ユーザーが表示されたアイテムの数量を追加できるようにする必要があります。すべての可能な製品のリストから製品の順序を作成することを考えてください。製品のコード リストは非常に長くなる可能性があります (数万またはそれ以上のアイテムなど)。一方で、オーダーの選択数は非常に少ない(最大で数~数十)。

実装済み: これまでのところ、データベースから情報にアクセスするための とコンテンツ プロバイダーをOrderOverviewActivity実装しました。LoaderManager私はそれを使用して、そのメソッドとメソッドMyCursorAdapterを拡張CursorAdapterおよびオーバーライドします。newView()bindView()

次のように、子ビューへの参照と、カーソル位置から抽出された値のバッファをnewView()含むインスタンスも作成します。ViewHolder

private static class ViewHolder {
    public TextView code;
    public CharArrayBuffer codeBuffer = new CharArrayBuffer(20);

    public TextView name;
    public CharArrayBuffer nameBuffer = new CharArrayBuffer(100);

    public TextView quantity;
    public CharArrayBuffer quantityBuffer = new CharArrayBuffer(10);
}

そのnewView()ように見えます:

    public View newView(Context context, Cursor cursor, ViewGroup parent) {

        View v = mInflater.inflate(mLayout, parent, false);

        ViewHolder holder = new ViewHolder();

        holder.code = (TextView) v.findViewById(R.id.code);
        holder.name = (TextView) v.findViewById(R.id.name);
        holder.quantity = (TextView) v.findViewById(R.id.quantity);

        v.setTag(holder);

        return v;
    }

bindView()ホルダー バッファを使用して、多くのStringオブジェクトの作成を回避します。

    public void bindView(View view, Context context, Cursor cursor) {

        ViewHolder holder = (ViewHolder) view.getTag();

        cursor.copyStringToBuffer(1, holder.codeBuffer);  // ProductTable.COLUMN_CODE
        cursor.copyStringToBuffer(2, holder.nameBuffer);  // ProductTable.COLUMN_NAME

        holder.code.setText(holder.codeBuffer.data, 0, holder.codeBuffer.sizeCopied);
        holder.name.setText(holder.nameBuffer.data, 0, holder.nameBuffer.sizeCopied);

        // The quantity (v for value) from the HashMap<String, String>.
        String v = mQuantity.get(String.valueOf(holder.codeBuffer.data, 0,
                                 holder.codeBuffer.sizeCopied));
        if (v != null) {
            holder.quantity.setText(v);
            holder.quantity.setBackgroundColor(Color.DKGRAY);
        }
        else {
            holder.quantity.setText(null);
            holder.quantity.setBackgroundColor(Color.TRANSPARENT);
        }
    }

質問の核心:HashMap<String, String>を介してオブジェクトから数量が抽出されることに注意してくださいString.valueOf(data, 0, data.size)。後でガベージコレクションを行う必要がある文字列オブジェクトを作成するため、パフォーマンスが損なわれるのではないかと心配しています。マップから数量 TextView 値を設定するより良い方法はありますか?

4

4 に答える 4

1

については yanchenko に同意しませんCharArrayBuffer。これは、ベースのアダプターで使用するのに最適な改善ですCursor(特に、使用する列Cursorが多い場合)。Stringその余分なものを取り除くためStringの最初のオプションは、mQuantity HashMapそれを機能しないキーにすることです(そしてクラスはfinalそうであるため、まったく機能させることはできません)。

行を識別する逆の方法は、とにかく_id必要な列です。ListView

これに関連して、次のことができます。

  • 2 つHashMapの s の両方がキーとしてLong値 (_id) を持ち、1 つは を保持し、もう 1 つは実際の数量を保持します (またはとコードのCOLUMN_CODE間の 1 つのマップ マッピングと、もう 1 つは現在のマップです)。_idこの 2 つのマップは同期されます (長い ID の一方の値を削除すると、もう一方の値も削除されます。値を追加する場合も同様です)。メソッドでは、getView()から _id を使用して名前を取得しますがCursor、これにはオートボクシング操作 (longLong) が必要です。

    class DataWrapper {
     private HashMap<Long, String> mCodeMapping = new HashMap<Long, String>();
     private HashMap<Long, String> mQuantityMapping = new HashMap<String, String>();
    
     public String getCode(long id) {
          return mCodeMapping.get(id);
     }
    
     public String getQuantity(long id) {
          return mQuantityMapping.get(getCode());
     }
    
     public String getQuantity(String code) {
          return mQuantityMapping.get(code);
     }
    
     public void put(long id, String code, String quantity) {
         mCodeMapping.put(id, code);
         mQuantityMapping .put(code, quantity); 
     } 
    }  
    
  • _idlongあり、適切な量の値を持っていますが、それを として脅かすことができintます (最大int値の境界にいるため)。これを行うと、カスタムクラスで a を簡単に使用できるようになります( と の間でSparseArrayキャスト):longint

    class WrapperData {
     String code; //or use the CharArraybuffer?
     String quantity;
    }
    
    SparseArray<WrapperData> data = new SparseArray<WrapperData>();
    // in the getView() method 
    WrapperData wd = data.get((int) _id_value); // further use wd.code or wd.quantity
    
  • 最後のオプションは、単純なキー (オートボクシングなし) とコードおよび数量値のSparseArray間のマッピングを可能にするような独自のクラスを実装することです。long

于 2013-08-10T06:48:39.977 に答える
0

s を台無しにして、 でs + sCharArrayBufferを使用したくありません。StringTextViewHolder

このようにして、コードを読みやすくし、プラットフォームで String プールをキャッシュに使用できるようにします。これは、最適なパフォーマンスも意味します。

いえ

private static class ViewHolder {

    public TextView code;
    public TextView name;
    public TextView quantity;

}

public void bindView(View view, Context context, Cursor cursor) {

    ViewHolder holder = (ViewHolder) view.getTag();

    String code = cursor.getString(1);
    String name = cursor.getString(2);

    String quantity = mQuantity.get(code);

    holder.code.setText(code);
    holder.name.setText(name);

    if (quantity != null) {
        holder.quantity.setText(quantity);
        holder.quantity.setBackgroundColor(Color.DKGRAY);
    } else {
        holder.quantity.setText("");
        holder.quantity.setBackgroundColor(Color.TRANSPARENT);
    }

}

最初に、一連の 3 つのプロファイリング テストを実行することをお勧めします。

  1. String v = mQuantity.get(String.valueOf(holder.codeBuffer.data, 0, holder.codeBuffer.sizeCopied));まったく電話なし。
  2. 初期バージョン。
  3. このバージョン。

その結果に基づいて、最後の 2 つの中から最も読みやすいものを選択します。(:

于 2013-08-08T11:44:58.090 に答える
0

ホルダー クラスに割り当てられ、位置にマップされた複製されたメモリ インスタンスとして、文字列変数を ViewHolder クラスに追加します。値の割り当てだけでなく、NEW キーワードを使用して、HASHMAP でマップされていない新しい STRING オブジェクトを取得します。

プライベート静的クラス ViewHolder {

public String quantityStr;

public TextView code;
public CharArrayBuffer codeBuffer = new CharArrayBuffer(20);

public TextView name;
public CharArrayBuffer nameBuffer = new CharArrayBuffer(100);

public TextView quantity;
public CharArrayBuffer quantityBuffer = new CharArrayBuffer(10);

}

パブリック ビュー newView

{ ... holder.quantityStr =新しい文字列( mQuantity.get(String.valueOf(holder.codeBuffer.data, 0, holder.codeBuffer.sizeCopied)) );

}

于 2013-08-07T20:41:35.353 に答える