CursorAdapter在newView和bindView之间不一致

时间:2016-08-02 22:25:59

标签: android cursor android-view android-cursoradapter

我对CursorAdapter中的Android newView和getView如何工作感到困惑。 到目前为止,我见过的大多数实现都实现了getView,但许多在线资源表明这不是可行的方法,例如here

我的问题归结为以下代码

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

    // Decide if message was sent by Me or Other
    View chatRow;
    if(cursor.getInt(cursor.getColumnIndexOrThrow(DbChat.KEY_SENDER_ID)) == 0) {
        chatRow = LayoutInflater.from(context.getApplicationContext())
                     .inflate(R.layout.listrow_chat_me,parent,false);
    } else {
        chatRow = LayoutInflater.from(context.getApplicationContext())
                     .inflate(R.layout.listrow_chat_other,parent,false);
    }

    return chatRow;
}

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

    TextView chatText = (TextView) view.findViewById(R.id.chat_text);
    ImageView imageView = (ImageView) view.findViewById(R.id.chat_img);

    chatText.setText(cursor.getString(cursor.getColumnIndexOrThrow(DbChat.KEY_TEXT)));

    if(cursor.getInt(cursor.getColumnIndexOrThrow(DbChat.KEY_SENDER_ID)) == 0) {
        imageView.setImageDrawable(ChatActivity.sIconBlue);
    } else {
        imageView.setImageDrawable(ChatActivity.sIconRed);
    }

请注意,newView会设置布局(包括图像的左对齐或右对齐),而bindView会设置图像(在本例中为蓝色或红色)。 因此,预期的行为是左边的所有红色方块和右边的所有蓝色方块(因为颜色和位置都在光标上查询相同的ID检查)。 相反,我得到以下布局:

enter image description here

基本上,我的问题与此question中的问题相同,但我没有找到解决问题的任何建议。

感谢您对此问题的奇怪行为或解决方案的任何解释!

2 个答案:

答案 0 :(得分:1)

默认情况下,ListView(以及CursorAdapter尝试尽可能多地重复使用视图的任何其他来源。

因此,newView()仅在创建足够的视图之前被调用,之后,当您重新使用已创建的视图时向下滚动列表时,仅调用bindView()

如果您有多种视图类型(就像您所做的那样),您还应该覆盖getViewTypeCount()getItemViewType()。这些方法告诉适配器只应重用相同类型的视图,以确保使用listrow_chat_me的行仅用于将来的listrow_chat_me行,而不会用于listrow_chat_other行。

@Override
public int getViewTypeCount() {
  return 2;
}

@Override
public int getItemViewType(int position) {
  // getItem(position) returns a Cursor at the given position
  Cursor cursor = (Cursor) getItem(position);
  if (cursor.getInt(cursor.getColumnIndexOrThrow(DbChat.KEY_SENDER_ID)) == 0) {
    return 0;
  } else {
    return 1;
  }
}

答案 1 :(得分:0)

默认情况下,游标适配器只假设一行布局,并根据行类型重用视图,因此您在左侧看到子项的原因。

有两种选择:使用一个视图,只需在绑定时隐藏备注,或调查覆盖方法

 getItemViewType(int position)

 getViewTypeCount()