毕加索加载图像内的AsyncTask催生毕加索、图像、加载、AsyncTask

2023-09-12 01:21:18 作者:结局时你哭了 我心疼了°

所以,我想使用毕加索库的图像下载和缓存。为了让contactUri传递给毕加索我需要做一个查询联系人内容提供商。因为我不希望阻止的主UI线程得到的ContactID,我已经在的AsyncTask 把这个。一旦我得到的ContactID,我做出的的AsyncTask 。

不过,我注意到一个闪烁显示,当我通过我的的ListView 快速滚动。在我看来,有一个问题, ViewHolder 因为回收视图设置相应的图像之前显示previous图像。反正是有避免这种情况?

 公共类ConversationThreadsCursorAdapter扩展SimpleCursorAdapter {

    //区域常量
    私有静态最终诠释RECIPIENT_IDS_COLUMN_INDEX = 3;
    私有静态最终诠释ID2_COLUMN_INDEX = 0;
    私有静态最终诠释ADDRESS_COLUMN_INDEX = 1;
    // endregion

    //区域变量
    私人最终字符串DEBUG_TAG =的getClass()getSimpleName()的toString()。

    私人语境mContext;
    保护绘制对象mDefaultPicDrawable;
    保护ContentResolver的mContentResolver;
    保护LinearLayout.LayoutParams mContactPicLayoutParams;
    // endregion

    //区域构造
    公共ConversationThreadsCursorAdapter(上下文的背景下,INT布局,
    光标C,的String []从,INT []键,诠释标志){
        超(背景下,布局,C,从到,旗);
        mContext =背景;
        mDefaultPicDrawable = mContext.getResources()。getDrawable(
        R.drawable.ic_contact_picture);
        mContactPicLayoutParams =新LinearLayout.LayoutParams(
        mDefaultPicDrawable.getIntrinsicWidth(),
        mDefaultPicDrawable.getIntrinsicHeight());

    }
    // endregion

    公共查看getView(最终诠释的立场,观点convertView,ViewGroup中父){
        ViewHolder viewHolder = NULL;

        如果(convertView == NULL){
            convertView = mLayoutInflater.inflate(R.layout.simple_message,NULL);

            //创建一个ViewHolder和存储引用的孩子
            //意见,我们希望将数据绑定到。
            viewHolder = setupViewHolder(convertView);

            convertView.setTag(viewHolder);

        } 其他 {
            //获取ViewHolder回得到快速访问的TextView
            //和ImageView的。
            viewHolder =(ViewHolder)convertView.getTag();
            viewHolder.task.cancel(真正的);


        }

        mCursor = getCursor();

        mCursor.moveToPosition(位置);

        viewHolder.position =位置;

        字符串recipient_ids = mCursor.getString(RECIPIENT_IDS_COLUMN_INDEX);

        的String []收件人= recipient_ids.split();

        viewHolder.task =新AddressFetcherTask(viewHolder,位置);
        viewHolder.task.execute(收件人);

        返回convertView;

    }

    //区域的辅助方法
    私人ViewHolder bindUIElements(查看convertView){
        ViewHolder viewHolder =新ViewHolder();

        viewHolder.contactBadge =(QuickContactBadge)convertView.findViewById(R.id.contact_pic);
        返回viewHolder;
    }

    私人ViewHolder setupViewHolder(查看convertView){
        ViewHolder viewHolder = bindUIElements(convertView);

        viewHolder.contactBadge.setLayoutParams(mContactPicLayoutParams);
        返回viewHolder;
    }
    // endregion

    //区域内部类

    私有类ViewHolder {
        QuickContactBadge contactBadge;
        INT位置;
    }

    私有类AddressFetcherTask扩展的AsyncTask<的String [],太虚,整数GT; {
        私人ViewHolder mViewHolder;
        私人诠释mPosition;

        公共AddressFetcherTask(ViewHolder viewHolder,INT位置){
            mViewHolder = viewHolder;
            mPosition =位置;
        }

        @覆盖
        保护整数doInBackground(字符串[] ...收件人){
            串收件人的收件人= [0] [0];
            Log.d(DEBUG_TAG,收件人是+接受者);
            光标C = mContentResolver.query(
            Uri.parse(内容:// MMS,SMS /规范-地址),NULL,_id =+收件人,NULL,NULL);

            字符串_id =;
            字符串的地址=;
            而(c.moveToNext()){
                _id = c.getString(ID2_COLUMN_INDEX);
                地址= c.getString(ADDRESS_COLUMN_INDEX);
            }
            c.close();

            INT的ContactID;
            如果(地址!= NULL){
                使用ContactID = ContactsUtils.getContactId(mContext,地址,地址);
            } 其他 {
                使用ContactID = Integer.valueOf(地址);
            }
            返回的ContactID;
        }

        @覆盖
        保护无效onPostExecute(整型的ContactID){

            如果(mViewHolder.position == mPosition){
                Picasso.with(mContext)
                    .load(getContactUri(的ContactID))
                    .placeholder(R.drawable.ic_contact_picture)
                    。走进(mViewHolder.contactBadge);

            }
        }
    }
    // endregion

}
 

解决方案

刚刚设置的ImageView内getView空的,它应该删除您遇到什么样的大部分,你会是正确的。

其他微小的小角落案件的方面是,当你的AsyncTask到达postExecute,视图可能仍然存在,但它可能已被分配一个不同的接触加载了(它被回收)。

您需要把某种标签的viewholder,然后检查,当你去设置它在postexecute它仍然是相同的。

VB载入图片的程序怎么把图片合并在程序文件里

要删除淡入,你需要从getview删除AsyncTask的。你需要能够调用毕加索在getview,这意味着有数据准备好到达getview之前。

下面,不太清楚是否会编,我已经在文本编辑器做到了。

但bassically我缓存结果mCachedContactIds,只是重新加载整个表,如果我需要一个新的。我通常发现这是稳健的。但你也可以拨打毕加索code我已经注释掉

 公共类ConversationThreadsCursorAdapter扩展SimpleCursorAdapter {

//区域常量
私有静态最终诠释RECIPIENT_IDS_COLUMN_INDEX = 3;
私有静态最终诠释ID2_COLUMN_INDEX = 0;
私有静态最终诠释ADDRESS_COLUMN_INDEX = 1;
私人的HashMap<字符串,整数> mCachedContactIds =新的HashMap<字符串,整数>();
// endregion

//区域变量
私人最终字符串DEBUG_TAG =的getClass()getSimpleName()的toString()。
私人语境mContext;
保护绘制对象mDefaultPicDrawable;
保护ContentResolver的mContentResolver;
保护LinearLayout.LayoutParams mContactPicLayoutParams;
// endregion

//区域构造
公共ConversationThreadsCursorAdapter(上下文的背景下,INT布局,
光标C,的String []从,INT []键,诠释标志){
    超(背景下,布局,C,从到,旗);
    mContext =背景;
    mDefaultPicDrawable = mContext.getResources()。getDrawable(
    R.drawable.ic_contact_picture);
    mContactPicLayoutParams =新LinearLayout.LayoutParams(
    mDefaultPicDrawable.getIntrinsicWidth(),
    mDefaultPicDrawable.getIntrinsicHeight());

}
// endregion

公共查看getView(最终诠释的立场,观点convertView,ViewGroup中父){
    ViewHolder viewHolder = NULL;

    如果(convertView == NULL){
        convertView = mLayoutInflater.inflate(R.layout.simple_message,NULL);
        //创建一个ViewHolder和存储引用的孩子
        //意见,我们希望将数据绑定到。
        viewHolder = setupViewHolder(convertView);
        convertView.setTag(viewHolder);

    } 其他 {
        //获取ViewHolder回得到快速访问的TextView
        //和ImageView的。
        viewHolder =(ViewHolder)convertView.getTag();
        viewHolder.task.cancel(真正的);
        viewHolder.contactBadge.setImageDrawable(mDefaultPicDrawable);
    }

    mCursor = getCursor();

    mCursor.moveToPosition(位置);

    viewHolder.position =位置;

    字符串recipient_ids = mCursor.getString(RECIPIENT_IDS_COLUMN_INDEX);

    的String []收件人= recipient_ids.split();
    串收件人的收件人= [0];

    如果(mCachedContactIds.get(收件人)!= NULL){
        Picasso.with(mContext)
            .load(getContactUri(mCachedContactIds.get(收件人)))
            .placeholder(R.drawable.ic_contact_picture)
            。走进(mViewHolder.contactBadge);
    } 其他 {
        viewHolder.task =新AddressFetcherTask(viewHolder,位置);
        viewHolder.task.execute(收件人);
    }

    返回convertView;
}

//区域的辅助方法
私人ViewHolder bindUIElements(查看convertView){
    ViewHolder viewHolder =新ViewHolder();
    viewHolder.contactBadge =(QuickContactBadge)convertView.findViewById(R.id.contact_pic);
    返回viewHolder;
}

私人ViewHolder setupViewHolder(查看convertView){
    ViewHolder viewHolder = bindUIElements(convertView);
    viewHolder.contactBadge.setLayoutParams(mContactPicLayoutParams);
    返回viewHolder;
}
// endregion

//区域内部类

私有类ViewHolder {
    QuickContactBadge contactBadge;
    INT位置;
    AddressFetcherTask任务;
}

私有类AddressFetcherTask扩展的AsyncTask<的String [],太虚,整数GT; {
    私人ViewHolder mViewHolder;
    私人诠释mPosition;
    私人字符串mRecipient;

    公共AddressFetcherTask(ViewHolder viewHolder,INT位置){
        mViewHolder = viewHolder;
        mPosition =位置;
    }

    @覆盖
    保护整数doInBackground(字符串[] ...收件人){
        mRecipient =收件人[0] [0];
        Log.d(DEBUG_TAG,收件人是+接受者);
        光标C = mContentResolver.query(
        Uri.parse(内容:// MMS,SMS /规范-地址),NULL,_id =+ mRecipient,NULL,NULL);

        字符串_id =;
        字符串的地址=;
        而(c.moveToNext()){
            _id = c.getString(ID2_COLUMN_INDEX);
            地址= c.getString(ADDRESS_COLUMN_INDEX);
        }
        c.close();

        INT的ContactID;
        如果(地址!= NULL){
            使用ContactID = ContactsUtils.getContactId(mContext,地址,地址);
        } 其他 {
            使用ContactID = Integer.valueOf(地址);
        }
        返回的ContactID;
    }

    @覆盖
    保护无效onPostExecute(整型的ContactID){
        如果(mViewHolder.position == mPosition){
            mCachedContactIds.put(mRecipient,使用ContactID);

            Picasso.with(mContext)
                .load(getContactUri(mCachedContactIds.get(收件人)))
                .placeholder(R.drawable.ic_contact_picture)
                。走进(mViewHolder.contactBadge);
        }
    }
}
// endregion

}
 

或者,如果剩下的窃听,你是从毕加索褪色,再加入noFade()请求。

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 < 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

}

解决方案

Just set the imageview to null in within getView and it should remove what you are experiencing for the most part you'll be right.

The other tiny tiny corner case aspect is that when your asynctask arrives at postExecute, the view might still exist, but it might have already been assigned a different contact to load up (it's been recycled).

You need to put some kind of tag in the viewholder, and then check that it is still the same when you go to set it in postexecute.

To remove the fade in, you need to remove the asynctask from the getview. You need to be able to call picasso within getview, which means having your data ready before arriving at getview.

The below, not quite sure if it will compile, I've done it in a text editor.

But bassically I'm caching results in mCachedContactIds and just reloading the whole table if I need a new one. I've typically found this to be robust. But you can also call the picasso code which I've commented out

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 that's bugging you left is the fade from picasso, then add noFade() to the request.