Question

as in title, on some devices images flicker while notifydatasetchanged is being called.

Here is my getView method from my subclass of BaseAdapter:

@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;
}

The holder.flag image flickers for a vary short period every time I click the toggleButton. This appear to happen only on some devices like Sony Xperia U or HTC Desire Z.

Here is my row layout:

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

and my AsyncIMageLoader class:

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);
        }
    }
}}

It seems to me, that convertView does not correspond to position in getView method. Is there any way to get convertView which corresponds to listview's row position? Or maybe there is another solution?

Was it helpful?

Solution

You should cancel AsyncImageLoader from a view that has been recycled.

What you are trying to achieve is really difficult to do. You can find a very detailed example here : http://developer.android.com/training/displaying-bitmaps/display-bitmap.html.

A good option, except if you really want to have achieved this in your life, is to use a library.

Here are some options :

I believe common's ware as a lib like this as well. And for sure there are even other options.

PS : I must say I prefer the second option, but as a contributor to RoboSpice I may not be that fair ;)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top