16

見つけた唯一の例の1つからカスタムSimpleCursorAdapterを作成しました。

ListActivityが呼び出されると、すべてのDBエントリに対してnewViewとbindViewが呼び出され、すべてのエントリに対して再度呼び出されます。いくつか質問があります。

-例は正しいですか(そうでない場合は、どこで見つけることができますか)?

-bindView呼び出しの前に常にnewView呼び出しがある場合、なぜ両方の関数で同じことを行うのですか?

-シーケンスnewView-bindViewがアイテムごとに2回呼び出されるのはなぜですか?

-一部のCursorAdapterの例でnewViewとbindViewの代わりにgetViewを使用するのはなぜですか?

基本的に、SimpleCursorAdapterはどのように使用する必要がありますか?また、私のコードの何が問題になっていますか?

ありがとう


ListActivity

public class ContactSelection extends ListActivity {

    private WhipemDBAdapter mDbHelper;
    private FriendAdapter friendAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mDbHelper = new WhipemDBAdapter(this);
        mDbHelper.open();     

        setContentView(R.layout.contact_list);   

        Cursor c = mDbHelper.fetchAllFriends();
        startManagingCursor(c);     
        String[] from = new String[] {};
        int[] to = new int[] {};

        this.friendAdapter = new FriendAdapter(this, R.layout.contact_row, c, from, to);
        setListAdapter(this.friendAdapter);

        getListView().setItemsCanFocus(false);
        getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mDbHelper.open();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mDbHelper.close();
    }
}

カスタムSimpleCursorAdapter

public class FriendAdapter extends SimpleCursorAdapter implements OnClickListener {

    private Context mContext;
    private int mLayout;

    public FriendAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
        super(context, layout, c, from, to);

        this.mContext = context;
        this.mLayout = layout;
    }

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

        Cursor c = getCursor();

        final LayoutInflater inflater = LayoutInflater.from(context);
        View v = inflater.inflate(mLayout, parent, false);     

        String name = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_NAME));
        String fb_id = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_FB_ID));

        TextView name_text = (TextView) v.findViewById(R.id.contact_name);
        if (name_text != null) {
            name_text.setText(name);
        }

        ImageView im = (ImageView) v.findViewById(R.id.contact_pic);            
        Drawable drawable = LoadImageFromWebOperations("http://graph.facebook.com/"+fb_id+"/picture");
        if (im != null) {
            im.setImageDrawable(drawable);
        }

        CheckBox bCheck = (CheckBox) v.findViewById(R.id.checkbox);
        if (im != null) {
            bCheck.setTag(fb_id);
        }            

        if (((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
            bCheck.setChecked(true);

        bCheck.setOnClickListener(this);

        return v;
    }

    @Override
    public void bindView(View v, Context context, Cursor c) {

         String name = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_NAME));
         String fb_id = c.getString(c.getColumnIndex(WhipemDBAdapter.KEY_FB_ID));


         TextView name_text = (TextView) v.findViewById(R.id.contact_name);
         if (name_text != null) {
             name_text.setText(name);
         }

        ImageView im = (ImageView) v.findViewById(R.id.contact_pic);            
        Drawable drawable = LoadImageFromWebOperations("http://graph.facebook.com/"+fb_id+"/picture");
        if (im != null) {
            im.setImageDrawable(drawable);
        }

        CheckBox bCheck = (CheckBox) v.findViewById(R.id.checkbox);
        if (im != null) {
            bCheck.setTag(fb_id);
        }

        ArrayList<String> dude = ((GlobalVars) mContext.getApplicationContext()).getSelectedFriendList();

        if (((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
            bCheck.setChecked(true);

        bCheck.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        CheckBox cBox = (CheckBox) v;
        String fb_id = (String) cBox.getTag();

        if (cBox.isChecked()) {
            if (!((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
                ((GlobalVars) mContext.getApplicationContext()).addSelectedFriend(fb_id);
        } else {
            if (((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
                ((GlobalVars) mContext.getApplicationContext()).removeSelectedFriend(fb_id);
        }

    }

    private Drawable LoadImageFromWebOperations(String url)
    {
        try
        {
            InputStream is = (InputStream) new URL(url).getContent();
            Drawable d = Drawable.createFromStream(is, "src name");
            return d;
        }catch (Exception e) {
            System.out.println("Exc="+e);
            return null;
        }
    }

}
4

2 に答える 2

21

関数をオーバーライドするgetView()と、すでに膨らんだリストアイテム(リストを前後にスクロールしたときに現在のビューポートから「スクロールアウト」されたリストアイテム)を「再利用」できるようになります。

そうすることで、膨張は非常に時間のかかる操作であるため、多くのメモリリソースとプロセッサの実行時間を節約できます。再利用するたびconvertViewに、GCの実行時間も節約できます(ガベージコレクターがその特定のリストアイテムを収集する必要がないため)。

ViewHolder膨らんだリストアイテムの各ビ​​ューの参照を保持する「ビューコレクション」クラス(以下の例のクラス)を作成することもできます。このようにして、リストアイテムを新しい値で更新するたびに(通常はリストをスクロールするときに)それらを見つける必要はありません。findViewById()また、かなり時間のかかる操作です。

また、レイアウトインフレータや列インデックスなど、より多くの変数をキャッシュできると思います。時間を節約するためのすべて:-)

private final Context mContext;
private final int mLayout;
private final Cursor mCursor;
private final int mNameIndex;
private final int mIdIndex;
private final LayoutInflater mLayoutInflater;

private final class ViewHolder {
    public TextView name;
    public ImageView image;
    public CheckBox checkBox;
}

public FriendAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
    super(context, layout, c, from, to);

    this.mContext = context;
    this.mLayout = layout;
    this.mCursor = c;
    this.mNameIndex = mCursor.getColumnIndex(WhipemDBAdapter.KEY_NAME);
    this.mIdIndex = mCursor.getColumnIndex(WhipemDBAdapter.KEY_FB_ID);
    this.mLayoutInflater = LayoutInflater.from(mContext);
}

public View getView(int position, View convertView, ViewGroup parent) {
    if (mCursor.moveToPosition(position)) {
        ViewHolder viewHolder;

        if (convertView == null) {
            convertView = mLayoutInflater.inflate(mLayout, null);

            viewHolder = new ViewHolder();
            viewHolder.name = (TextView) convertView.findViewById(R.id.contact_name);
            viewHolder.image = (ImageView) convertView.findViewById(R.id.contact_pic);
            viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox);

            convertView.setTag(viewHolder);
        }
        else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        String name = mCursor.getString(mNameIndex);
        String fb_id = mCursor.getString(mIdIndex);
        Drawable drawable = LoadImageFromWebOperations("http://graph.facebook.com/"+fb_id+"/picture");
        boolean isChecked = ((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id);

        viewHolder.name.setText(name);
        viewHolder.image.setImageDrawable(drawable);
        viewHolder.checkBox.setTag(fb_id);
        viewHolder.checkBox.setChecked(isChecked);
    }

    return convertView;
}
于 2011-03-03T17:48:10.983 に答える
13

例はほぼ正しいです。でバインディングを行う必要はありません。newView()前述のように、bindView()が呼び出されるためです。newView / bindViewのシーケンスがアイテムごとに2回呼び出されている場合はListView、高さをに設定して使用している可能性がありますがwrap_content、これは常に悪い考えです。最後に、newView()およびbindView()に固有CursorAdapterです:それは実装し、またはあなたのためgetView()に呼び出します。ただし、オーバーライドも完全に有効です。これは、他のアダプターの動作方法です。newView()bindView()getView()

getView()(したがって、bindView / newView)は、画面に表示される各アイテムに対してのみ呼び出されることに注意してください。

于 2011-03-03T17:13:07.390 に答える