Search code examples
androidlistviewandroid-asynctaskimage-loading

Android Custom Listview Image loading without libraries


I want to load images from sd card into a custom listview. My listview contains image view and a text view. I know there are many libraries which can help me achieve this, but I want to do without using such libraries.

Problem :-

I am loading the images from async task. I am calling the async task from inside my getView(). I get the images only in the last row. That is, if there are 3 images in my folder, then only the image is shown in the 3rd item of the listview.

Below is my code :-

public class MyPhotoAdapter extends BaseAdapter {

    private Activity callingActivity;
    private ArrayList<String> filePaths = new ArrayList<String>();//contains file path of images
    ArrayList<Bitmap> myImages = new ArrayList<Bitmap>();
    private int imageWidth;
    int position;

    ImageView iv_photo;
    TextView tv_address;


    public MyPhotoAdapter(Activity activity,ArrayList<String> paths,int width)
    {
        this.callingActivity = activity;
        this.filePaths = paths;
        this.imageWidth = width;
    }



    @Override
    public int getCount() {
        return filePaths.size();
    }

    @Override
    public Object getItem(int i) {
        return this.filePaths.get(i);
    }

    @Override
    public long getItemId(int i) {
        return 0;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {

        position = i;

        LayoutInflater inflater = (LayoutInflater) callingActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row = inflater.inflate(R.layout.single_photo,viewGroup, false);

        iv_photo = (ImageView) row.findViewById(R.id.photoView);
        tv_address = (TextView) row.findViewById(R.id.tv_address);

        AsyncImageLoader loader = new AsyncImageLoader();
        loader.execute(filePaths);
        return row;
    }

    class AsyncImageLoader extends AsyncTask<ArrayList<String>,Bitmap,Void>{


        ProgressDialog dialog;


        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dialog = ProgressDialog.show(callingActivity,"Loading Images","Please Wait ....");
        }

        @Override
        protected Void doInBackground(ArrayList<String>... arrays) {
            Log.d("Test","Total Images :- "+arrays[0].size());
            for(int i = 0; i< arrays[0].size(); i++)
            {
                Bitmap map = decodeFile(arrays[0].get(i).toString(), 150, 150);
                myImages.add(map);
                publishProgress(map);
            }

            return null;
        }

        @Override
        protected void onProgressUpdate(Bitmap... bitmap) {

            iv_photo.setImageBitmap(bitmap[0]);

        }

        @Override
        protected void onPostExecute(Void aVoid) {
            //super.onPostExecute(aVoid);
            dialog.dismiss();
            /*for(int i = 0; i < myImages.size(); i ++)
            {
                iv_photo.setImageBitmap(myImages.get(i));
            }*/
        }


        public Bitmap decodeFile(String filePath, int WIDTH, int HIGHT) {
            try {

                File f = new File(filePath);

                BitmapFactory.Options o = new BitmapFactory.Options();
                o.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(new FileInputStream(f), null, o);

                final int REQUIRED_WIDTH = WIDTH;
                final int REQUIRED_HIGHT = HIGHT;
                int scale = 1;
                while (o.outWidth / scale / 2 >= REQUIRED_WIDTH
                        && o.outHeight / scale / 2 >= REQUIRED_HIGHT)
                    scale *= 2;

                BitmapFactory.Options o2 = new BitmapFactory.Options();
                o2.inSampleSize = scale;
                return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
}

Image is shown only in the last list-item. Other image views dont show the images.


Solution

  • You can follow this to know more about handling concurrency.

    I have modified your code ..... please see if it helps

    public class MyPhotoAdapter extends BaseAdapter {
    
        private Activity callingActivity;
        private ArrayList<String> filePaths = new ArrayList<String>();
        ArrayList<Bitmap> myImages = new ArrayList<Bitmap>();
        private int imageWidth;
        int position;
    
        ImageView iv_photo;
        TextView tv_address;
    
    
        public MyPhotoAdapter(Activity activity,ArrayList<String> paths,int width)
        {
            this.callingActivity = activity;
            this.filePaths = paths;
            this.imageWidth = width;
        }
    
    
    
        @Override
        public int getCount() {
            return filePaths.size();
        }
    
        @Override
        public Object getItem(int i) {
            return this.filePaths.get(i);
        }
    
        @Override
        public long getItemId(int i) {
            return 0;
        }
    
        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
    
            position = i;
    
            LayoutInflater inflater = (LayoutInflater) callingActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View row = inflater.inflate(R.layout.single_photo,viewGroup, false);
    
            iv_photo = (ImageView) row.findViewById(R.id.photoView);
            tv_address = (TextView) row.findViewById(R.id.tv_address);
    
            AsyncImageLoader loader = new AsyncImageLoader(iv_photo);
            loader.execute(filePaths);
            return row;
        }
    
        class AsyncImageLoader extends AsyncTask<ArrayList<String>,Bitmap,Void>{
    
    
            ProgressDialog dialog;
            private final WeakReference<ImageView> imageViewReference;
    
            public AsyncImageLoader(ImageView imageView)
            {
                imageViewReference = new WeakReference<ImageView>(imageView);
            }
    
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                dialog = ProgressDialog.show(callingActivity,"Loading Images","Please Wait ....");
            }
    
            @Override
            protected Void doInBackground(ArrayList<String>... arrays) {
                Log.d("Test","Total Images :- "+arrays[0].size());
                for(int i = 0; i< arrays[0].size(); i++)
                {
                    Bitmap map = decodeFile(arrays[0].get(i).toString(), 150, 150);
                    myImages.add(map);
                    publishProgress(map);
                }
    
                return null;
            }
    
            @Override
            protected void onProgressUpdate(Bitmap... bitmap) {
    
                //iv_photo.setImageBitmap(bitmap[0]);
    
                if (imageViewReference != null) {
                    ImageView imageView = imageViewReference.get();
                    if (imageView != null) {
                        imageView.setImageBitmap(bitmap[0]);
                    }
                }
    
            }
    
            @Override
            protected void onPostExecute(Void aVoid) {
                //super.onPostExecute(aVoid);
                dialog.dismiss();
                /*for(int i = 0; i < myImages.size(); i ++)
                {
                    iv_photo.setImageBitmap(myImages.get(i));
                }*/
            }
    
    
            public Bitmap decodeFile(String filePath, int WIDTH, int HIGHT) {
                try {
    
                    File f = new File(filePath);
    
                    BitmapFactory.Options o = new BitmapFactory.Options();
                    o.inJustDecodeBounds = true;
                    BitmapFactory.decodeStream(new FileInputStream(f), null, o);
    
                    final int REQUIRED_WIDTH = WIDTH;
                    final int REQUIRED_HIGHT = HIGHT;
                    int scale = 1;
                    while (o.outWidth / scale / 2 >= REQUIRED_WIDTH
                            && o.outHeight / scale / 2 >= REQUIRED_HIGHT)
                        scale *= 2;
    
                    BitmapFactory.Options o2 = new BitmapFactory.Options();
                    o2.inSampleSize = scale;
                    return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }
    }