Baptiste Costa
Baptiste Costa

Reputation: 1044

Asynchronously download image from internet/database to Android ListView

I'm trying to set a drawable in a list. My list doesn't contain just an image. I'm populating it from a list_item.xml with severals TextViews and one ImageView.

I don't have any problem if my image is store in the Res android folder, but here I'm loading this image from a database.

Right now i'm using this king of method :

SimpleAdapter adapter = new SimpleAdapter(this.getBaseContext(), list,
R.layout.xml_leaderboard_item, keys, views);

Is there a way to add this drawable/bitmap in my list ? or maybe put that image in the Res folder programmatically so I can use it ?

Upvotes: 0

Views: 774

Answers (2)

Baptiste Costa
Baptiste Costa

Reputation: 1044

I was finally able to do what I wanted. Here is the result :

enter image description here

I'm downloading these pictures asynchronously from my database. I was having trouble adding it to a ListView... Here's my code for those who might be interested.

public class LeaderboardScreen extends ListActivity implements View.OnClickListener
{
    private UserAdapter             adapter;
    private ArrayList<User>         users;
    private UserPictureDownloader   user_picture_cache;
    ...

    protected void onCreate(Bundle saved_instance_state)
    {
        ...
        users = new ArrayList<User>();
        adapter = new UserAdapter(this, R.layout.xml_leaderboard_item, users);
        user_picture_cache = new UserPictureDownloader();
        setListAdapter(adapter);     
        ...
    }     


    private class UserAdapter extends ArrayAdapter<User>
    {
        private ArrayList<User>     users;

        public UserAdapter(Context context, int text_view_res_id, ArrayList<User> users)
        {
            super(context, text_view_res_id, users);
            this.users = users;
        }

        public View         getView(int position, View view, ViewGroup parent)
        {
            LayoutInflater layout = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = layout.inflate(R.layout.xml_leaderboard_item, null);


            ImageView iv_pic = (ImageView)view.findViewById(R.id.lead_pic);
            TextView et_position = (TextView)view.findViewById(R.id.lead_position);
            TextView et_user = (TextView)view.findViewById(R.id.lead_user);
            TextView et_score = (TextView)view.findViewById(R.id.lead_s_value);
            TextView et_reput = (TextView)view.findViewById(R.id.lead_r_value);
            TextView et_contrib = (TextView)view.findViewById(R.id.lead_c_value);
            TextView et_bronze = (TextView)view.findViewById(R.id.lead_bronze_value);
            TextView et_silver = (TextView)view.findViewById(R.id.lead_silver_value);
            TextView et_gold = (TextView)view.findViewById(R.id.lead_gold_value);

            User current_user = users.get(position);
            if (current_user != null)
            {               
                // Set available informations right away.
                et_position.setText(String.valueOf(position + 1));
                et_user.setText(current_user.GetLogin());
            et_score.setText(String.valueOf(current_user.GetScore()));
            et_reput.setText(String.valueOf(current_user.GetReputation()));
            et_contrib.setText(String.valueOf(current_user.GetNumberOfQuestionPost()));
            et_bronze.setText(String.valueOf(current_user.GetBadgeBronze()));
            et_silver.setText(String.valueOf(current_user.GetBadgeSilver()));
            et_gold.setText(String.valueOf(current_user.GetBadgeGold()));

            // Fetch user image asynchronously.
            final int pos = position;
            final String user_login = current_user.GetLogin();
            final ImageView _iv_pic = iv_pic;

            final Handler handler = new Handler()
                {
                @Override
                public void         handleMessage(Message message)
                {
                    _iv_pic.setImageDrawable((Drawable)message.obj);
                }
            };

            Thread thread = new Thread()
            {
                @Override
                public void         run()
                {
                    try
                    {
                        Drawable dwb = (Drawable)user_picture_cache.GetCachedObject(user_login, handler);
                        handler.sendMessage(handler.obtainMessage(0, dwb));
                    }
                    catch (Exception e) {   Log.e(TAG, e.getMessage()); }
                }
            };
            thread.start();
        }
        return view;
    }
}   

The DownloadCache class :

public class DownloadCache
{
    private final String    TAG = "DownloadCache";

    private ConcurrentHashMap<String, CountDownLatch>   queued_downloads;
    private ConcurrentHashMap<String, Object>           cache;

    public DownloadCache()
    {
        queued_downloads = new ConcurrentHashMap<String, CountDownLatch>();
        cache = new ConcurrentHashMap<String, Object>();
    }


    public Object GetCachedObject(String url, Handler handler) throws InterruptedException
    {
        // Check for a running download, if found wait for its result.
        CountDownLatch complete_event = queued_downloads.get(url);
        if (complete_event != null)
        complete_event.await();

        // Check for cached object.
        Object obj = cache.get(url);
        if (obj != null)
            return obj;

        obj = StartDownload(url, handler);
        return obj;
    }

private Object StartDownload(String url, Handler handler)
    {
        CountDownLatch complete_event = new CountDownLatch(1);
        queued_downloads.put(url, complete_event);

        Object obj = DoDownloadWork(url, handler);
        cache.put(url, obj);

        queued_downloads.remove(url);

        complete_event.countDown();
        return obj;
    }

    public Object DoDownloadWork(String url, Handler handler)
    {
        return null;
    }
}

Hope this help.

Upvotes: 0

xaviert
xaviert

Reputation: 5932

Decode the image byte data from your database using the BitmapFactory class. Then use the setImageBitmap or setImageDrawable method on your ImageView.

byte[] imageData = ...;    
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
imageView.setImageBitmap( bitmap );

Upvotes: 1

Related Questions