所以我试图使用 Picasso Library进行图像下载和缓存.为了让contactUri传递给Picasso,我需要向Contacts Content Provider提出查询.因为我不想阻止主UI线程获取contactId,所以我把它放在AsyncTask中.一旦我
但是,我注意到当我快速滚动ListView时出现的闪烁.在我看来,ViewHolder存在问题,因为回收视图在设置适当的图像之前显示上一个图像.反正有没有避免这个?
public class ConversationThreadsCursorAdapter extends SimpleCursorAdapter { // region Constants private static final int RECIPIENT_IDS_COLUMN_INDEX = 3; private static final int ID2_COLUMN_INDEX = 0; private static final int ADDRESS_COLUMN_INDEX = 1; // endregion // region Variables private final String DEBUG_TAG = getClass().getSimpleName().toString(); private Context mContext; protected Drawable mDefaultPicDrawable; protected ContentResolver mContentResolver; protected LinearLayout.LayoutParams mContactPicLayoutParams; // endregion // region Constructors public ConversationThreadsCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { super(context, layout, c, from, to, flags); mContext = context; mDefaultPicDrawable = mContext.getResources().getDrawable( R.drawable.ic_contact_picture); mContactPicLayoutParams = new LinearLayout.LayoutParams( mDefaultPicDrawable.getIntrinsicWidth(), mDefaultPicDrawable.getIntrinsicHeight()); } // endregion public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if (convertView == null) { convertView = mLayoutInflater.inflate(R.layout.simple_message, null); // Creates a ViewHolder and store references to the children // views we want to bind data to. viewHolder = setupViewHolder(convertView); convertView.setTag(viewHolder); } else { // Get the ViewHolder back to get fast access to the TextView // and the ImageView. viewHolder = (ViewHolder) convertView.getTag(); viewHolder.task.cancel(true); } mCursor = getCursor(); mCursor.moveToPosition(position); viewHolder.position = position; String recipient_ids = mCursor.getString(RECIPIENT_IDS_COLUMN_INDEX); String[] recipients = recipient_ids.split(" "); viewHolder.task = new AddressFetcherTask(viewHolder, position); viewHolder.task.execute(recipients); return convertView; } // region Helper Methods private ViewHolder bindUIElements(View convertView) { ViewHolder viewHolder = new ViewHolder(); viewHolder.contactBadge = (QuickContactBadge) convertView.findViewById(R.id.contact_pic); return viewHolder; } private ViewHolder setupViewHolder(View convertView) { ViewHolder viewHolder = bindUIElements(convertView); viewHolder.contactBadge.setLayoutParams(mContactPicLayoutParams); return viewHolder; } // endregion // region Inner Classes private class ViewHolder { QuickContactBadge contactBadge; int position; } private class AddressFetcherTask extends AsyncTask < String[], Void, Integer > { private ViewHolder mViewHolder; private int mPosition; public AddressFetcherTask(ViewHolder viewHolder, int position) { mViewHolder = viewHolder; mPosition = position; } @Override protected Integer doInBackground(String[]...recipients) { String recipient = recipients[0][0]; Log.d(DEBUG_TAG, "recipient is " + recipient); Cursor c = mContentResolver.query( Uri.parse("content://mms-sms/canonical-addresses"), null, "_id = " + recipient, null, null); String _id = ""; String address = ""; while (c.moveToNext()) { _id = c.getString(ID2_COLUMN_INDEX); address = c.getString(ADDRESS_COLUMN_INDEX); } c.close(); int contactId; if (address != null) { contactId = ContactsUtils.getContactId(mContext, address, "address"); } else { contactId = Integer.valueOf(address); } return contactId; } @Override protected void onPostExecute(Integer contactId) { if (mViewHolder.position == mPosition) { Picasso.with(mContext) .load(getContactUri(contactId)) .placeholder(R.drawable.ic_contact_picture) .into(mViewHolder.contactBadge); } } } // endregion }只需在getView中将imageview设置为null,它就应该删除你正在经历的大部分内容.
另一个微小的小角落情况是,当你的asynctask到达postExecute时,视图可能仍然存在,但它可能已被分配了一个不同的联系人来加载(它已被回收).
您需要在视图中放置某种标记,然后在postexecute中设置它时检查它是否仍然相同.
要删除淡入,您需要从getview中删除asynctask.您需要能够在getview中调用picasso,这意味着在到达getview之前准备好数据.
下面,不太确定它是否会编译,我已经在文本编辑器中完成了.
但是低音我正在缓存mCachedContactIds中的结果,如果需要一个新表,只需重新加载整个表.我通常发现这很强大.但你也可以调用我已经注释掉的毕加索代码
public class ConversationThreadsCursorAdapter extends SimpleCursorAdapter { // region Constants private static final int RECIPIENT_IDS_COLUMN_INDEX = 3; private static final int ID2_COLUMN_INDEX = 0; private static final int ADDRESS_COLUMN_INDEX = 1; private HashMap<String, Integer> mCachedContactIds = new HashMap<String, Integer>(); // endregion // region Variables private final String DEBUG_TAG = getClass().getSimpleName().toString(); private Context mContext; protected Drawable mDefaultPicDrawable; protected ContentResolver mContentResolver; protected LinearLayout.LayoutParams mContactPicLayoutParams; // endregion // region Constructors public ConversationThreadsCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { super(context, layout, c, from, to, flags); mContext = context; mDefaultPicDrawable = mContext.getResources().getDrawable( R.drawable.ic_contact_picture); mContactPicLayoutParams = new LinearLayout.LayoutParams( mDefaultPicDrawable.getIntrinsicWidth(), mDefaultPicDrawable.getIntrinsicHeight()); } // endregion public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if (convertView == null) { convertView = mLayoutInflater.inflate(R.layout.simple_message, null); // Creates a ViewHolder and store references to the children // views we want to bind data to. viewHolder = setupViewHolder(convertView); convertView.setTag(viewHolder); } else { // Get the ViewHolder back to get fast access to the TextView // and the ImageView. viewHolder = (ViewHolder) convertView.getTag(); viewHolder.task.cancel(true); viewHolder.contactBadge.setImageDrawable(mDefaultPicDrawable); } mCursor = getCursor(); mCursor.moveToPosition(position); viewHolder.position = position; String recipient_ids = mCursor.getString(RECIPIENT_IDS_COLUMN_INDEX); String[] recipients = recipient_ids.split(" "); String recipient = recipients[0]; if(mCachedContactIds.get(recipient) != null){ Picasso.with(mContext) .load(getContactUri(mCachedContactIds.get(recipient))) .placeholder(R.drawable.ic_contact_picture) .into(mViewHolder.contactBadge); } else { viewHolder.task = new AddressFetcherTask(viewHolder, position); viewHolder.task.execute(recipients); } return convertView; } // region Helper Methods private ViewHolder bindUIElements(View convertView) { ViewHolder viewHolder = new ViewHolder(); viewHolder.contactBadge = (QuickContactBadge) convertView.findViewById(R.id.contact_pic); return viewHolder; } private ViewHolder setupViewHolder(View convertView) { ViewHolder viewHolder = bindUIElements(convertView); viewHolder.contactBadge.setLayoutParams(mContactPicLayoutParams); return viewHolder; } // endregion // region Inner Classes private class ViewHolder { QuickContactBadge contactBadge; int position; AddressFetcherTask task; } private class AddressFetcherTask extends AsyncTask < String[], Void, Integer > { private ViewHolder mViewHolder; private int mPosition; private String mRecipient; public AddressFetcherTask(ViewHolder viewHolder, int position) { mViewHolder = viewHolder; mPosition = position; } @Override protected Integer doInBackground(String[]...recipients) { mRecipient = recipients[0][0]; Log.d(DEBUG_TAG, "recipient is " + recipient); Cursor c = mContentResolver.query( Uri.parse("content://mms-sms/canonical-addresses"), null, "_id = " + mRecipient, null, null); String _id = ""; String address = ""; while (c.moveToNext()) { _id = c.getString(ID2_COLUMN_INDEX); address = c.getString(ADDRESS_COLUMN_INDEX); } c.close(); int contactId; if (address != null) { contactId = ContactsUtils.getContactId(mContext, address, "address"); } else { contactId = Integer.valueOf(address); } return contactId; } @Override protected void onPostExecute(Integer contactId) { if (mViewHolder.position == mPosition) { mCachedContactIds.put(mRecipient, contactId); Picasso.with(mContext) .load(getContactUri(mCachedContactIds.get(recipient))) .placeholder(R.drawable.ic_contact_picture) .into(mViewHolder.contactBadge); } } } // endregion }
或者,如果所有这些让你感到困扰的是毕加索的淡出,那么在请求中添加noFade().