[置顶] 【Android性能优化】Android图片加载方案--Bitmap的内存管理和优化方案

 

[置顶] 【Android性能优化】Android图片加载方案--Bitmap的内存管理和优化方案

标签: Bitmap优化OOM缓存图片加载
  9811人阅读  评论(0)  收藏  举报
  分类:

目录(?)[+]

转载请注明原文地址:http://blog.csdn.net/mxm691292118/article/details/51028953

我把Android重难点和读书笔记都整理在github上:https://github.com/miomin/AndroidDifficulty

如果你觉得对你有帮助的话,希望可以star/follow一下哟,我会持续保持更新。


写在前面:笔者的上一篇博文有提到过,如果不恰当的使用Bitmap,很容易造成OOM。这篇博文就来谈谈应该如何正确的管理Bitmap的内存,以及优化策略。

参考: Google官方教程 – 《Android Training Ccourse》


一、加载按显示需要的比例缩小的图片

1、先来说说屏幕密度

  • android中,Imageview控件的长宽单位一般设置为dp/dip,而不用px。这样做的原因,是因为dp/dip与屏幕像素密度无关,px与屏幕密度有关。在Android中,规定以160dpi为基准,1dip=1px,如果密度是320dpi,则1dip=2px。(所以,同一个imageview,在不同的设备上所显示的长宽的像素是不同的,我们需要根据像素不同,来按比例压缩大图)

  • 如果把一个大小为1024x1024像素的图片显示到大小为512x512像素的ImageView上吗,就没有必要加载整张原图到Bitmap中。

  • 为了告诉解码器去加载一个缩小比例是多少的图片到内存中,需要在BitmapFactory.Options 中设置 inSampleSize 的值。例如, 一个分辨率为2048x2048的图片,如果设置 inSampleSize 为4,那么会产出一个大约512x512大小的Bitmap。

  • 下面的代码是动态获取一个ImageView的长宽像素: 
    注意:返回的是像素值(px),而不是dp/dip

    int reqHeight = iv.getLayoutParams().height;
    int reqWidth = iv.getLayoutParams().width;
   
   
  • 1
  • 2
  • 1
  • 2

2、压缩图片

  • 一般来说,加载本地资源图片才需要压缩,加载网络图片,应该让服务器按需压缩,一方面节省流量,另一方面提高加载流畅度
  • 可以通过下面的代码计算inSampleSize的值,就是需要压缩的倍数:
//reqWidth和reqHeight是需要显示的Imageview的width和height
public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // height和width图片长宽的像素
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 通过下面的方法可以获得压缩后的Bitmap: 
    注意:可以通过设置 inJustDecodeBounds 属性为true可以在解码的时候避免内存的分配,它会返回一个null的Bitmap,但是可以获取到 outWidth, outHeight 与 outMimeType。确定好压缩比例后,再将inJustDecodeBounds设置为false。
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // 计算inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // 根据inSampleSize压缩图片
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

二、Bitmap缓存

1、缓存类LruCache介绍

  • 在Android3.0之后,一般使用LruCache来缓存Bitmap,它使用一个强引用的LinkedHashMap保存最近引用的对象,并且在缓存超出设置大小的时候剔除(evict)最少使用到的对象。
  • LinkedHashMap会根据LRU算法来排列对象的顺序,新加入的对象添加到头部,刚被使用过的对象也被移动到头部,所以在链表尾部的对象是最久没有被使用过的,一旦链表满了,有新对象加入,就会删除链表尾部的对象。

2、如何给LruCache设置一个合适的大小?

  • LruCache太大的话,容易造成OOM或者分配给应用的剩余内存不够用,LruCache大小的设置,应该考虑下面的因素: 
    • (1)应用允许的最大内存是多少?剩下了多少可用的内存?
    • (2)多少张图片会同时显示在屏幕上?
    • (3)设备的屏幕密度是多少?显示图片的像素是多少?
    • (4)可以根据访问频率给Bitmap分组,为不同的Bitmap组设置不同大小的LruCache对象。

3、一个LruCache使用的完整例子

  • 代码参考了一个大神的代码,并修真了一些写的不对和不好的地方。
public class PhotoAdapter extends BaseAdapter implements AbsListView.OnScrollListener {

    // 从network下载图片的线程集合
    private List<ImageDownloadTask> mDownloadTaskList;
    private LruCache<String, Bitmap> mLruCache;

    // 引用外部的变量
    private WeakReference<GridView> mGridView;
    private WeakReference<List<String>> urls;
    private WeakReference<Context> mContext;


    // 可见项的第一项的index
    private int mFirstVisibleIndex;

    // 可见项的个数
    private int mVisibleItemCount;

    // 是不是第一次打开Activity
    private boolean isFirstOpen = true;

    public PhotoAdapter(Context context, GridView mGridView, List<String> urls) {
        this.mContext = new WeakReference<Context>(context);
        this.urls = new WeakReference<List<String>>(urls);
        this.mGridView = new WeakReference<GridView>(mGridView);
        this.mGridView.get().setOnScrollListener(this);
        mDownloadTaskList = new ArrayList<>();
        // 初始化图片缓存池
        initCache();
    }

    private void initCache() {

        // 获取应用的max heap size
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

        // Android官方教学文档推荐LruCache的size为heap size的1/8
        int cacheSize = maxMemory / 8;

        mLruCache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                if (bitmap != null) {
                    return bitmap.getByteCount() / 1024;
                }
                return 0;
            }
        };
    }

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

    @Override
    public Object getItem(int position) {
        return urls.get().get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        viewHolder holder = null;

        if (convertView == null) {
            convertView = LayoutInflater.from(mContext.get()).inflate(R.layout.layout_item, parent, false);
            holder = new viewHolder();
            holder.mImageView = (ImageView) convertView.findViewById(R.id.imageView);
            holder.mTextView = (TextView) convertView.findViewById(R.id.textView);
            convertView.setTag(holder);
        } else {
            holder = (viewHolder) convertView.getTag();
        }

        String url = urls.get().get(position);
        //imageview与url绑定,防止错乱显示
        holder.mImageView.setTag(MD5Tools.decodeString(url));
        holder.mTextView.setText("第" + position + "项");

        if (!holder.mImageView.getTag().equals(url)) {
            showImageView(holder.mImageView, url);
        }

        return convertView;
    }

    /**
     * convertView复用
     */
    private class viewHolder {
        ImageView mImageView;
        TextView mTextView;
    }

    /**
     * 给ImageView设置Bitmap
     */
    private void showImageView(ImageView imageView, String url) {

        // 对url进行md5编码
        String key = MD5Tools.decodeString(url);
        // 先从cache中找bitmap缓存
        Bitmap bitmap = get(key);

        if (bitmap != null) {
            // 如果缓存命中
            imageView.setImageBitmap(bitmap);
        } else {
            // 如果cache miss
            imageView.setBackgroundResource(R.color.color_five);
        }
    }

    /**
     * 将Bitmap put 到 cache中
     */
    private void put(String key, Bitmap bitmap) {

        if (get(key) == null) {
            mLruCache.put(key, bitmap);
        }
    }

    /**
     * 在Cache中查找bitmap,如果miss则返回null
     */
    private Bitmap get(String key) {
        return mLruCache.get(key);
    }

    /**
     * 从网络下载图片
     */
    private Bitmap loadBitmap(String urlStr) {

        HttpURLConnection connection = null;
        Bitmap bitmap = null;
        try {
            URL url = new URL(urlStr);
            connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.setDoInput(true);
            connection.connect();
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream mInputStream = connection.getInputStream();
                bitmap = BitmapFactory.decodeStream(mInputStream);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
        return bitmap;
    }

    /**
     * 取消所有的下载任务
     */
    public void cancelAllTask() {

        if (mDownloadTaskList != null) {
            for (int i = 0; i < mDownloadTaskList.size(); i++) {
                mDownloadTaskList.get(i).cancel(true);
            }
        }
    }

    /**
     * 加载可见项的图片
     */
    private void loadVisibleBitmap(int mFirstVisibleItem, int mVisibleItemCount) {

        for (int i = mFirstVisibleItem; i < mFirstVisibleItem + mVisibleItemCount; i++) {
            final String url = urls.get().get(i);
            String key = MD5Tools.decodeString(url);
            Bitmap bitmap = get(key);
            ImageView mImageView;
            if (bitmap != null) {
                //缓存中存在该图片的话就设置给ImageView
                mImageView = (ImageView) mGridView.get().findViewWithTag(MD5Tools.decodeString(url));
                if (mImageView != null) {
                    mImageView.setImageBitmap(bitmap);
                }
            } else {
                //不存在的话就开启一个异步线程去下载
                ImageDownloadTask task = new ImageDownloadTask(this);
                mDownloadTaskList.add(task);
                task.execute(url);
            }
        }
    }

    /**
     * 从网络下载图片的异步task
     */
    static class ImageDownloadTask extends AsyncTask<String, Void, Bitmap> {

        private String url;
        private WeakReference<PhotoAdapter> photoAdapter;

        public ImageDownloadTask(PhotoAdapter photoAdapter) {
            this.photoAdapter = new WeakReference<PhotoAdapter>(photoAdapter);
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            //在后台开始下载图片
            url = params[0];
            Bitmap bitmap = photoAdapter.get().loadBitmap(url);
            if (bitmap != null) {
                //把下载好的图片放入LruCache中
                String key = MD5Tools.decodeString(url);
                photoAdapter.get().put(key, bitmap);
            }
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            //把下载好的图片显示出来
            ImageView mImageView = (ImageView) photoAdapter.get().mGridView.get().findViewWithTag(MD5Tools.decodeString(url));
            if (mImageView != null && bitmap != null) {
                mImageView.setImageBitmap(bitmap);
                photoAdapter.get().mDownloadTaskList.remove(this);//把下载好的任务移除
            }
        }
    }

    /**
     * 监听GridView的滑动状态
     */
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

        //GridView停止滑动时,去加载可见项的图片
        if (scrollState == SCROLL_STATE_IDLE) {
            loadVisibleBitmap(mFirstVisibleIndex, mVisibleItemCount);
        } else {
            //GridView开始滑动时,取消所有加载任务
            cancelAllTask();
        }
    }

    /**
     * 监听并更新GridView滑动过程中的可见项
     */
    @Override
    public void onScroll(AbsListView view, int firstVisibleIndex, int visibleItemCount, int totalItemCount) {

        mFirstVisibleIndex = firstVisibleIndex;
        mVisibleItemCount = visibleItemCount;

        // 第一次打开,加载可见项
        if (isFirstOpen && visibleItemCount > 0) {
            loadVisibleBitmap(mFirstVisibleIndex, mVisibleItemCount);
            isFirstOpen = false;
        }
    }
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271

4、Andorid3.0之前的Bitmap管理方法(参考自xiaanming的博客)

  • 在Android3.0之前,Bitmap对象与数据是分开存储的,Bitmap对象存储在Java heap中,而像素数据存储在Native Memory中,Java虚拟机的垃圾回收机制不会主动回收Native Memory中的对象,需要在Bitmap不需要使用的时候,主动调用recycle()方法来释放,而在Android3.0之后,Bitmap的像素数据和Bitmap对象都存放在Java Heap中,所以不需要手动调用recycle()来释放,垃圾收集器会处理。
  • 应该在什么时候去调用recycle()方法呢?可以用引用计数算法,用一个变量来记录Bitmap显示情况,如果Bitmap绘制在View上面displayRefCount加一, 否则就减一, 只有在displayResCount为0且Bitmap不为空且Bitmap没有调用过recycle()的时候,才调用recycle(),下面用BitmapDrawable类来包装下Bitmap对象,代码如下:
public class RecycleBitmapDrawable extends BitmapDrawable {
    private int displayResCount = 0;
    private boolean mHasBeenDisplayed;

    public RecycleBitmapDrawable(Resources res, Bitmap bitmap) {
        super(res, bitmap);
    }


    /**
     * @param isDisplay
     */
    public void setIsDisplayed(boolean isDisplay){
        synchronized (this) {
            if(isDisplay){
                mHasBeenDisplayed = true;
                displayResCount ++;
            }else{
                displayResCount --;
            }
        }

        checkState();
    }

    /**
     * 检查图片的一些状态,判断是否需要调用recycle
     */
    private synchronized void checkState() {
        if (displayResCount <= 0 && mHasBeenDisplayed
                && hasValidBitmap()) {
            getBitmap().recycle();
        }
    }


    /**
     * 判断Bitmap是否为空且是否调用过recycle()
     * @return
     */
    private synchronized boolean hasValidBitmap() {
        Bitmap bitmap = getBitmap();
        return bitmap != null && !bitmap.isRecycled();
    }

}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 还需要一个自定义的ImageView,重写了setImageDrawable()方法,在这个方法中我们先获取ImageView上面的图片,然后通知之前显示在ImageView的Drawable不在显示了,Drawable会判断是否需要调用recycle(),代码如下:
public class RecycleImageView extends ImageView {

    public RecycleImageView(Context context) {  
        super(context);  
    }  

    public RecycleImageView(Context context, AttributeSet attrs) {  
        super(context, attrs);  
    }  

    public RecycleImageView(Context context, AttributeSet attrs, int defStyle) {  
        super(context, attrs, defStyle);  
    }  

    @Override  
    public void setImageDrawable(Drawable drawable) {  
        Drawable previousDrawable = getDrawable();  
        super.setImageDrawable(drawable);  

        //显示新的drawable  
        notifyDrawable(drawable, true);  

        //回收之前的图片  
        notifyDrawable(previousDrawable, false);  
    }  

    @Override  
    protected void onDetachedFromWindow() {  
        //当View从窗口脱离的时候,清除drawable  
        setImageDrawable(null);  
        super.onDetachedFromWindow();  
    }  

    /** 
     * 通知该drawable显示或者隐藏 
     *  
     * @param drawable 
     * @param isDisplayed 
     */  
    public static void notifyDrawable(Drawable drawable, boolean isDisplayed) {  
        if (drawable instanceof RecycleBitmapDrawable) {  
            ((RecycleBitmapDrawable) drawable).setIsDisplayed(isDisplayed);  
        } else if (drawable instanceof LayerDrawable) {  
            LayerDrawable layerDrawable = (LayerDrawable) drawable;  
            for (int i = 0, z = layerDrawable.getNumberOfLayers(); i < z; i++) {  
                notifyDrawable(layerDrawable.getDrawable(i), isDisplayed);  
            }  
        }  
    }  

}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 具体的使用方法如下
ImageView imageView = new ImageView(context);  
        imageView.setImageDrawable(new RecycleBitmapDrawable(context.getResource(), bitmap));
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值