Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load asynchronous images in listView

I want to load images from a server, AFTER loading the data in a list view. I know that a lot of topics existing for this problem but I haven't found the solution...

So this is my code :

//asyncTackClass for loadingpictures
public class LoadImagesThread extends AsyncTask<Bundle, Void, Bitmap> {
    private ImageView view;
    private Bitmap bm;
    private Context context;
    private final WeakReference<ImageView> imageViewReference;

    private final String BUNDLE_URL = "url";
    private final String BUNDLE_NAME = "name";
    private final String BUNDLE_BM = "bm";

    public LoadImagesThread(Context context, ImageView view) {
        this.context=context;
        imageViewReference = new WeakReference<ImageView>(view);
    }

    @Override
    protected Bitmap doInBackground(Bundle... b) {

        Bitmap bm =null;
        if (StorageHelper.getBitmap(b[0].getString(BUNDLE_NAME)) != null) { // Check the sdcard
            bm = StorageHelper.getBitmap(b[0].getString(BUNDLE_NAME));
            Log.w("LoadImagesThread", "Get image from sdcard : "+b[0].getString(BUNDLE_NAME));
        } else { // Check the server
            bm = ServiceHelper.getBitmapFromURL(b[0].getString(BUNDLE_URL));
            StorageHelper.saveBitmap(bm, b[0].getString(BUNDLE_NAME)); // Save image on sdcard   
            Log.w("LoadImagesThread", "Get image from server : "+b[0].getString(BUNDLE_NAME));
        }

        return bm;
    }

    @Override
    protected void onPostExecute(final Bitmap bm) {
        super.onPostExecute(bm);        
        if (bm != null){ //if bitmap exists...
            view = imageViewReference.get();
            // Fade out
            Animation fadeOutAnimation = AnimationUtils.loadAnimation(context, R.anim.fadeoutimage);
            fadeOutAnimation.setAnimationListener(new AnimationListener() {

            public void onAnimationStart(Animation animation) {

            }

            public void onAnimationRepeat(Animation animation) {

            }

            public void onAnimationEnd(Animation animation) {
                // Fade in
                view.setImageBitmap(bm);
                Animation fadeInAnimation = AnimationUtils.loadAnimation(context, R.anim.fadeinimage);
                view.startAnimation(fadeInAnimation);
            }
        });

            // Launch the fadeout
            view.startAnimation(fadeOutAnimation);


        }else{ //if not picture, display the default ressource
            view.setImageResource(R.drawable.productcarre);
        }

    }

}

The code is used to display a Bitmap in a ImageView

And this is the adapter:

public class ListViewShoplistStoresAdapter extends BaseAdapter {

private ArrayList<Shop> shopList;
private Activity activity;

private HashMap<Integer, ImageView> views;
private final String BUNDLE_URL = "url";
private final String BUNDLE_NAME = "name";
private final String BUNDLE_POS = "pos";
private final String BUNDLE_ID = "id";


public ListViewShoplistStoresAdapter(Activity activity, ArrayList<Shop> shopList) {
    super();
    this.activity = activity;
    this.shopList = shopList;
    this.views = new HashMap<Integer, ImageView>();
}

public int getCount() {
    return shopList.size();
}

public Object getItem(int position) {
    return shopList.get(position);
}

public long getItemId(int position) {
    return shopList.get(position).getId();
}

private class ViewHolder {
    public TextView store;
    public TextView name;
    public ImageView ImageStore;
}

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder view;
    LayoutInflater inflator = activity.getLayoutInflater();

    if(convertView == null) {
        view = new ViewHolder();
        convertView = inflator.inflate(R.layout.listviewshops, null);

        view.store = (TextView) convertView.findViewById(R.id.store);
        view.name = (TextView) convertView.findViewById(R.id.name);
        view.ImageStore = (ImageView) convertView.findViewById(R.id.imgstore);

        convertView.setTag(view);
    }else {
        view = (ViewHolder) convertView.getTag();
    }

    Typeface regular=Typeface.createFromAsset(activity.getAssets(), "fonts/RobotoRegular.ttf");
    view.store.setTypeface(regular);

    Typeface light=Typeface.createFromAsset(activity.getAssets(), "fonts/RobotoLight.ttf");
    view.store.setTypeface(light);
    Brand brand = StorageHelper.getBrand(activity, shopList.get(position).getBrandId());
    if (brand == null) {
        Log.e("SetShopInAdapter","Brand null");
        Toast.makeText(activity, "Impossible d'afficher la liste de magasins", Toast.LENGTH_LONG).show();
    } else {
        view.store.setText(brand.getName());
        view.name.setText(shopList.get(position).getName());
        view.ImageStore.setImageResource(R.drawable.productcarre);
    }

    Bundle b = new Bundle();

    //url of the pict
    b.putString(BUNDLE_URL, ServiceHelper.getImageUrl("brand", brand.getName()));

    // name of image
    b.putString(BUNDLE_NAME, ServiceHelper.getCleanImageName(brand.getName()));

    //position in the listView
    b.putInt(BUNDLE_POS, position);

    //id of the current object
    b.putInt(BUNDLE_ID, brand.getId());

    //put info in the map in order to display in the onPostExecute
    if(views.get(position)==null){
        views.put(position, view.ImageStore);
        // launch thread
        new LoadImagesThread(activity.getApplicationContext(), view.ImageStore).execute(b);
    }

    return convertView;

}

}

So, when I used a GridView, there were no problems, but when I use a ListView the image is changed only in the first item !

Example: I want to display product images for "car", "house" and "apple" items. The code will launch the thread and all images (car then house and finally apple) will be displayed in the first item (the car item)... And the house and the apple while not have images !!

Do you know what I should do ?

Thanks

like image 810
Florian Mac Langlade Avatar asked Oct 17 '12 11:10

Florian Mac Langlade


1 Answers

There is a lot about this here on SO.. asynchrnous loading like that is called "Lazy Loading"

https://github.com/thest1/LazyList

for full implementation of such a process with list

For loading images in general i recomend this :

https://github.com/nostra13/Android-Universal-Image-Loader

like image 169
AndroidGecko Avatar answered Oct 05 '22 23:10

AndroidGecko