chip
chip

Reputation: 1789

Palette in ListView Android with Picasso

I have a ListView and I'm playing with Palette from the support library. When on using BitmapFactory.decodeStream to generate a bitmap from a url, this throws an exception (Network on UI thread) or possibly very expensive. How do I make this asynchronous? I couldn't think of any efficient way to do this. What's the best approach?

    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {
        final ViewHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.item_grid, null);
            holder = new ViewHolder();
            holder.image = (ImageView) convertView.findViewById(R.id.img_photo);
            holder.bg = (LinearLayout) convertView.findViewById(R.id.bg_title);
            holder.text = (TextView) convertView.findViewById(R.id.txt_title);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Picasso.with(mContext)
                .load(mShows.get(position).poster)
                .into(holder.image);

        try {
            URL url = new URL(mShows.get(position).poster);
            Bitmap bitmap = BitmapFactory.decodeStream(
                    url.openConnection().getInputStream()); // Too expensive!!!
            Palette palette = Palette.generate(bitmap);

            holder.text.setText(mShows.get(position).title);
            holder.text.setTextColor(palette.getVibrantColor().getRgb());

            holder.bg.setAlpha(0.4f);
            holder.bg.setBackgroundColor(palette.getDarkMutedColor().getRgb());

        } catch (IOException e) {
            e.printStackTrace();
        }

        return convertView;
    }

Upvotes: 1

Views: 1277

Answers (2)

sddamico
sddamico

Reputation: 2130

You could use Picasso's into(...) with a Callback parameter for when the image has successfully loaded:

Picasso.with(mContext)
            .load(mShows.get(position).poster)
            .into(holder.image, new Callback() {

    @Override public void onSuccess() {
        Bitmap bitmap = ((BitmapDrawable)holder.image.getDrawable()).getBitmap();
        // do your processing here....
    }

    @Override public void onError() {
        // reset your views to default colors, etc.
    }

});

Upvotes: 5

jobcrazy
jobcrazy

Reputation: 1073

Try to do the network and bitmap decoding stuff in a work thread, and asynchronous notify back when you get the bitmap, and you also need a bitmap cache to avoid duplicate decoding work. A simple implementation is like this:

Interface IBitmapCache {
    Bitmap get(String key);
    put(String key, Bitmap map);
}

Class YourAdapter {

    Class ViewHolder {
        //your other views
        //use url as key.
        String url;
    }

    IBitmapCache mCache;

    //you need to hold an instance of your listview here.
    WeakReference<ListView> mAttachedListView;

    View getView() {
        //... handle other things
        Bitmap bitmap = mCache.get(url);
        if (bitmap == null) {
            //retrieve bitmap asynchronous
        }
    }

    //callback when bitmap is retrieved
    void onBitmapRetrived(String url, Bitmap bitmap) {
        if (mAttachedListView.get() != null) {
            final ListView list = mAttachedListView.get();
            final int count = list.getLastVisiblePosition() - list.getFirstVisiblePosition + 1;
            for (int i = 0; i < count; i++) {
                View v = lv.getChildAt(i);
                if (v == null) {
                    continue;
                }
                ViewHolder holder = (ViewHolder) v.getTag();
                if (url.equals(holder.url)) {
                    //do your Palette related things here.
                    break;
                }
            }
        }
    }
}

there are 2 more things you should do, put your decoded Bitmap to your bitmap cache, set a callback to your work thread and ensure that it is called on UI thread which can be easily implemented by Handler.

Upvotes: 0

Related Questions