Loading Picasso Image Created Inside AsyncTask

So, I'm trying to use the Picasso Library to upload and cache images. To contact us in order to upgrade to Picasso , I need to make a request to the Content Provider contacts. Since I don't want to block the main UI thread to get contactId, I put it in AsyncTask . And as soon as I get this contact, I make a call to Picasso in the onPostExecute() AsyncTask .

However, I notice a flicker that appears when I quickly scroll through my ListView . It seems to me that there is a problem with ViewHolder , since the redesigned views display the previous image before setting the corresponding 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 < 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 } 
+1
android image android-asynctask picasso
source share
1 answer

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.

+3
source share

All Articles