Android:在某些设备上调用notifyDataSetChanged时,ListView中的图像闪烁

4

如标题所述,在某些设备上,当调用notifydatasetchanged时,图像会闪烁。

这是我在BaseAdapter子类中的getView方法:

@Override
public View getView(int position, View convertView, ViewGroup arg2) {
    String infService = Context.LAYOUT_INFLATER_SERVICE;
    LayoutInflater li = (LayoutInflater)context.getSystemService(infService);
    View v = arg1;
    final ViewHolder holder;

    if(v == null)
    {
        v = li.inflate(R.layout.row_history_settings, arg2, false);
        holder = new ViewHolder();

        holder.flag = (ImageView) v.findViewById(R.id.row_history_settings_image_flag);
        holder.currency = (TextView) v.findViewById(R.id.row_history_settings_text_currency);
        holder.tb = (ToggleButton) v.findViewById(R.id.row_history_settings_tb);
        v.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) v.getTag();
    }

    Account account = accounts.get(arg0);

    int resID = enabled == true ? Utils.getFlagResIdForCurrency(account.currency()) : Utils.getFlagInactiveResIdForCurrency(account.currency());

    if(resID != holder.resId)
    {   
        holder.resId = resID;
        holder.flag.setTag(resID);
        new AsyncImageLoader(holder.flag, context).execute();
    }

    holder.currency.setText(account.currency());
    if(currency!=null)
    {
        holder.tb.setChecked(currency.equals(account.currency()));
        holder.tb.setEnabled(true);
    }
    else
    {
        holder.tb.setChecked(false);
        holder.tb.setEnabled(false);
    }

    holder.tb.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            currency = holder.currency.getText().toString();
            notifyDataSetChanged();
        }
    });

    Utils.enableDisableView(v, enabled);

    return v;
}

每次我点击toggleButton时,holder.flag 图像会在极短的时间内闪烁。这似乎只会发生在某些设备上,例如Sony Xperia U或HTC Desire Z。
这是我的行布局:
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/row_list_standard_height"
    android:background="@drawable/list_item_background"
    android:gravity="center_vertical"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/row_history_settings_image_flag"
        android:layout_width="@dimen/row_list_flag_width"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="10dp"
        android:adjustViewBounds="true"
        android:contentDescription="@string/none"
        android:src="@drawable/flag_pln" />

    <com.aliorbank.components.customfont.CustomFontTextView
        android:id="@+id/row_history_settings_text_currency"
        style="@style/textViewUniversalRobotoLightBlack"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_gravity="left|center_vertical"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/row_history_settings_image_flag"
        android:text="@string/universal_currency_pln"
        android:textSize="@dimen/font_size_big" />

    <ToggleButton
        android:id="@+id/row_history_settings_tb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="10dp"
        android:background="@drawable/btn_radio_standard"
        android:checked="true"
        android:text="@string/none"
        android:textOff="@string/none"
        android:textOn="@string/none" />
</RelativeLayout>

以及我的AsyncIMageLoader类:

public class AsyncImageLoader extends AsyncTask<Object, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private Context context;
private int resId;

public AsyncImageLoader(ImageView imv, Context context)
{
    imageViewReference = new WeakReference<ImageView>(imv);
    this.context = context;
    this.resId = (Integer)imv.getTag();
}

@Override
protected Bitmap doInBackground(Object... arg0) {
    return BitmapFactory.decodeResource(context.getResources(), resId);
}

@Override
protected void onPostExecute(Bitmap result) {

    if (imageViewReference != null && result != null) {
        final ImageView imageView = imageViewReference.get();
        if (imageView != null) {
            imageView.setImageBitmap(result);
        }
    }
}}

在getView方法中,convertView好像并不对应于位置。有没有办法获取与listview行位置对应的convertView?或者也许有其他解决方案吗?

1个回答

3
您应该从已经被回收的视图中取消AsyncImageLoader。
您试图实现的目标真的很难做到。您可以在此处找到一个非常详细的示例:http://developer.android.com/training/displaying-bitmaps/display-bitmap.html
一个好的选择,除非您真的想在生活中实现这一点,否则就是使用库。
以下是一些选项: 我相信Common's Ware也有类似的库,当然还有其他选项。
PS: 我必须说我更喜欢第二个选项,但作为RoboSpice的贡献者,我可能不那么公正;)

谢谢您的回答!我试着按照 http://developer.android.com/training/displaying-bitmaps/display-bitmap.html 的步骤处理,并简单地将所需的所有方法复制到我的适配器中,但是在 final AsyncDrawable asyncDrawable = new AsyncDrawable(getResources(), mPlaceHolderBitmap, task); 中出现了一个问题。好像必须放置一些图像占位符。 - Marcin Szulc
无论如何,它指引了我正确的方向,现在似乎已经可以工作了!谢谢! - Marcin Szulc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接