Android:自定义 SimpleCursorAdapter 中的 newView 和 bindView 问题

标签 android simplecursoradapter

我从 the only example I found 之一创建了一个自定义 SimpleCursorAdapter .

当我的 ListActivity 被调用时,我的每个 DB 条目都会调用 newView 和 bindView,并且会为每个条目再次调用。我有几个问题:

-这个例子对吗(如果不对,我在哪里可以找到)?

-如果 bindView 调用总是在 newView 调用之前,为什么在两个函数中都做同样的事情?

-为什么序列 newView-bindView 为每个项目调用两次?

-为什么有些 CursorAdapter 示例使用 getView 而不是 newView 和 bindView?

基本上SimpleCursorAdapter应该怎么用,我的代码有什么问题?

谢谢


列表 Activity

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

}

最佳答案

重写 getView() 函数可以让您“重新使用”已经膨胀的列表项(当您滚动列表时从当前视口(viewport)“滚动出”的列表项)来回)。

这样做可以节省大量内存资源和处理器运行时间,因为膨胀是一项非常耗时的操作。对于您重复使用的每个 convertView,您还可以节省 GC 运行时间(因为垃圾收集器不必收集该特定列表项)。

您还可以创建一个“ View 集合”类(以下示例中的 ViewHolder 类),它将保存膨胀列表项中每个 View 的引用。这样,您不必每次使用新值更新列表项时(通常在滚动列表时)都找到它们。 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;
}

关于Android:自定义 SimpleCursorAdapter 中的 newView 和 bindView 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5183813/

相关文章:

android - 如何在手机上为 NoSQL 数据库存储数据

android - 我的 View Pager Adapter 中的 instantiateItem() 如何工作?

android - 无法恢复 Activity

android - 使用 SimpleCursorAdapter 和 SQLite 在 ListView 中反转顺序

android微调器自定义行

android - CursorLoader/适配器未显示正确的值

android - 是否可以使用 SimpleCursorAdapter 格式化 double 型?

java - SAX解析器,解析后新行被删除,我可以保留它们吗? ( )

android - 为什么 view.bringToFront() 不起作用?

android - 动态获取android锁屏包名