So I am trying to use the Picasso Library for image downloading and caching. In order to get the contactUri to pass to Picasso
I need to make a query to the Contacts Content Provider
. Since I don't want to block the main UI thread to get the contactId, I have put this in an AsyncTask
. And once I get that contactId, I make the call to Picasso
in the onPostExecute()
method of the AsyncTask
.
However, I am noticing a flickering that shows up when I scroll through my ListView
quickly. It seems to me that there is an issue with the ViewHolder
since the recycled views are displaying the previous image before setting the appropriate image. Is there anyway to avoid this?
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 { 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 }