Just set the image to null within the getView and it should remove what you experience for the most part, you'll be right.
Another tiny tiny aspect of the corner case is that when your asynthesis arrives in postExecute, the view may still exist, but it may be assigned a different contact for download (it has been redesigned).
You need to put some kind of tag in the viewer, and then check that it is the same when you go to set it in postexecute.
To remove the attenuation, you need to remove the asintex from getview. You should be able to call picasso within getview, which means your data is ready before arriving at getview.
Below, Iβm not quite sure that it will compile, I did it in a text editor.
But the bass player I cache the results in mCachedContactIds and just reload the whole table if I need a new one. I usually find this reliable. But you can also name the picasso code that I commented on.
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 }
Or if all you were listening for was fading out of picasso, then add noFade () to the request.