滚动视图时,Recyclerview 在contactsContract 中更改我的phoneNumber 的值
Posted
技术标签:
【中文标题】滚动视图时,Recyclerview 在contactsContract 中更改我的phoneNumber 的值【英文标题】:Recyclerview change the value of my phoneNumber in contactsContract when scroll the view 【发布时间】:2016-12-23 01:35:15 【问题描述】:我正在使用 recyclerview 实施一项活动。我加载了手机中的所有联系人(姓名和电话号码)。一切看起来都很好,问题是当我在视图中滚动时,当我回到同一个联系人时,这个联系人没有正确的电话号码。是唯一一个改变的。姓名和联系电话显示正确。
例如,一个联系人只设置了手机。初始化时看起来没问题,但如果我滚动并返回,家庭和工作设置了另一个数字,并且这个用户只设置了手机
一些帮助将不胜感激!
这是我在 recyclerAdapter 中的 onBind 方法:
@Override
public void onBindViewHolder(ViewHolder holder, int position)
dataCursor.moveToPosition(position);
holder.mTextView.setText((dataCursor.getString(1)));
ContentResolver cr = context.getContentResolver();
String contactId = dataCursor.getString(dataCursor.getColumnIndex(ContactsContract.Contacts._ID));
Long photoTest = dataCursor.getLong(dataCursor.getColumnIndex(ContactsContract.Contacts.PHOTO_ID));
if (dataCursor.moveToFirst())
Cursor phones = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);
if (phones == null)
phones.close();
else
while (phones.moveToNext())
try
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[]contactId, null);
while (pCur.moveToNext())
int phoneType = pCur.getInt(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
String phoneNumber = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
if(phoneType == TYPE_MOBILE)
holder.mNumberMoBilePhone.setText(phoneNumber);
holder.mNumberMoBilePhone.setVisibility(View.VISIBLE);
holder.textMobilePhone.setVisibility(View.VISIBLE);
else if(phoneType == TYPE_HOME)
holder.mNumberHomePhone.setText(phoneNumber);
holder.mNumberHomePhone.setVisibility(View.VISIBLE);
holder.textHomePhone.setVisibility(View.VISIBLE);
else if(phoneType == TYPE_WORK)
holder.mNumberWorkPhone.setText(phoneNumber);
holder.mNumberWorkPhone.setVisibility(View.VISIBLE);
holder.textWorkPhone.setVisibility(View.VISIBLE);
else
catch (NullPointerException n)
phones.close();
if (photoTest != null)
ContactPhotoLoaderSdk5.instance().loadPhoto(holder.mContactPhoto, photoTest);
不确定是否必须与此相关,但这是我的选择:
String select = "((" + ContactsContract.Contacts.DISPLAY_NAME + " NOTNULL) AND (" + ContactsContract.Contacts.HAS_PHONE_NUMBER + " != 0 ))";
【问题讨论】:
我建议在设置适配器时从数据库中获取所有数据。将此数据放入列表并在适配器中使用该列表。这将提高性能,使您的代码更加简洁,并且更容易发现错误。 【参考方案1】:这是因为RecyclerView
的工作方式,与您访问联系人数据的方式无关。 RecyclerView
只会为一次适合屏幕的每个视图创建一个 ViewHolder
,然后当它们滚动到屏幕外时回收这些视图。然后该视图的新内容将应用到onBindViewHolder()
。
由于您之前可能已为 ViewHolder.textHomePhone
和 ViewHolder.textWorkPhone
文本视图分配了文本,因此当这些视图持有者被回收时,该文本仍然存在。因此,如果新联系人只有手机号码,则家庭号码和工作号码的文本仍将由占用该ViewHolder
的先前联系人填写。
要解决此问题,您需要检查联系人没有是否具有每种类型(移动、家庭和工作)的编号,如果有,请将相应 TextView
的可见性设置为View.GONE
.
一个简单的方法是在循环之前创建三个布尔值,然后检查它们:
boolean hasMobile = false;
boolean hasHome = false;
boolean hasWork = false;
while (pCur.moveToNext())
int phoneType = pCur.getInt(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
String phoneNumber = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
if(phoneType == TYPE_MOBILE)
holder.mNumberMoBilePhone.setText(phoneNumber);
holder.mNumberMoBilePhone.setVisibility(View.VISIBLE);
holder.textMobilePhone.setVisibility(View.VISIBLE);
hasMobile = true;
else if(phoneType == TYPE_HOME)
holder.mNumberHomePhone.setText(phoneNumber);
holder.mNumberHomePhone.setVisibility(View.VISIBLE);
holder.textHomePhone.setVisibility(View.VISIBLE);
hasHome = true;
else if(phoneType == TYPE_WORK)
holder.mNumberWorkPhone.setText(phoneNumber);
holder.mNumberWorkPhone.setVisibility(View.VISIBLE);
holder.textWorkPhone.setVisibility(View.VISIBLE);
hasWork = true;
if(!hasMobile)
holder.mNumberMobilePhone.setVisibility(View.GONE);
holder.textMobilePhone.setVisibility(View.GONE);
if(!hasHome)
holder.mNumberHomePhone.setVisibility(View.GONE);
holder.textHomePhone.setVisibility(View.GONE);
if(!hasWork)
holder.mNumberWorkPhone.setVisibility(View.GONE);
holder.textWorkPhone.setVisibility(View.GONE);
【讨论】:
【参考方案2】:我认为问题出在以下行:
if (dataCursor.moveToFirst())
您将数据光标移动到每次调用中的第一个元素,这是不必要的,这将撤消函数顶部的以下行:
dataCursor.moveToPosition(position);
如果您删除 if
语句,它应该可以正常工作
【讨论】:
嗨@pooya 你的解决方案仍然有同样的问题 @D.O.从这里进行调试非常困难,但是您的代码中也存在一些语义问题,例如,在此之前 (phones.moveToNext()) 需要有phones.moveToFirst()。请看看您是否可以先纠正这些问题以帮助获得更可靠的输出 这是我试图在我的代码中读取所有电话号码的实现。也许这可以帮助你给我一些解决方案。是@anivaler ***.com/questions/2356084/… 的答案 @D.O.在 RecyclerView 中,您应该做的只是在用户滚动并且数据失效时更新每一行的数据,因此您无法读取 onBindViewHolder 中的所有内容以上是关于滚动视图时,Recyclerview 在contactsContract 中更改我的phoneNumber 的值的主要内容,如果未能解决你的问题,请参考以下文章
RecyclerView的行项目视图隐藏/显示在Recyclerview的滚动上搞砸了