打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
浅谈图片加载的三级缓存(一)

之前被人问及过,图片的三级缓存是什么啊,来给我讲讲,图片三级缓存,好高大尚的名字,听着挺厉害,应该是很厉害的技术,当时不会啊,也就没什么了,没有说出来呗,前一阶端用到了BitmapUtils的图片缓存框架,索性就自己找些知识点来研究一些图片的三级缓存是什么吧。真所谓是知识你要是不知道,那就真的说不出所以然来,但是当你真正的去了解了,三级缓存也不是那么高端的技术。好了,闲话不多说了,开始图片的三级缓存原理吧。

什么是图片的三级缓存

  • 1、内存缓存 优先加载,速度最快
  • 2、本地缓存 次优先加载 速度稍快
  • 3、网络缓存 最后加载 速度由网络速度决定(浪费流量)

图片的三级缓存图形解释

好了,既然知道了什么三级缓存的字面意思了,那么我们就来处理吧。

图片缓存—内存缓存的原理

MemoryCacheUtils.Java:

package com.example.bitmaputils.bitmap;import android.graphics.Bitmap;import android.util.Log;import android.util.LruCache;/** * 内存缓存 */public class MemoryCacheUtils {    /**     * LinkedHashMap<>(10,0.75f,true);     * <p/>     * 10是最大致   0.75f是加载因子   true是访问排序   false插入排序     *     *     */    //private LinkedHashMap<String,Bitmap> mMemoryCache = new LinkedHashMap<>(5,0.75f,true);    private LruCache<String, Bitmap> mLruCache;    public MemoryCacheUtils() {        long maxMemory = Runtime.getRuntime().maxMemory();//最大内存  默认是16兆  运行时候的        mLruCache = new LruCache<String, Bitmap>((int) (maxMemory / 8)) {            @Override            protected int sizeOf(String key, Bitmap value) {                //int byteCount = value.getByteCount();                //得到图片字节数                // @return number of bytes between rows of the native bitmap pixels.                int byteCount = value.getRowBytes() * value.getWidth();                return byteCount;            }        };    }    /**     * 从内存中读取     *     * @param url     */    public Bitmap getFromMemroy(String url) {        Log.d("MyBitmapUtils", "从内存中加载图片");        return mLruCache.get(url);    }    /**     * 写入到内存中     *     * @param url     * @param bitmap     */    public void setToMemory(String url, Bitmap bitmap) {        mLruCache.put(url, bitmap);    }}
  • 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
  • 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

很简单吧,在这里我们使用了LruCache(),对图片进行了内存缓存,这里我们只是稍微进行了处理,在这里我们只是介绍原理,当然了哈,性能,OOM溢出问题我们在这里不作处理。

图片缓存—本地缓存

package com.example.bitmaputils.bitmap;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Environment;import android.util.Log;import com.example.bitmaputils.MD5Encoder;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;/** * 本地缓存 */public class SDcardCacheUtils {    /**     * 我们读取内存的绝对路径     */    public static final String CACHE_PATH = Environment            .getExternalStorageDirectory().getAbsolutePath() + "/aixuexi";    /**     * 从本地读取     * @param url     */    public Bitmap getFromSd(String url){        String fileName = null;        try {            //得到图片的url的md5的文件名            fileName = MD5Encoder.encode(url);        } catch (Exception e) {            e.printStackTrace();        }        File file = new File(CACHE_PATH,fileName);        //如果存在,就通过bitmap工厂,返回的bitmap,然后返回bitmap        if (file.exists()){            try {                Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));                Log.d("MyBitmapUtils", "从本地读取图片啊");                return bitmap;            } catch (FileNotFoundException e) {                e.printStackTrace();            }        }        return null;    }    /**     * 向本地缓存     *     * @param url   图片地址     * @param bitmap   图片     */    public void savaSd(String url,Bitmap bitmap){        String fileName = null;        try {            //我们对图片的地址进行MD5加密,作为文件名            fileName = MD5Encoder.encode(url);        } catch (Exception e) {            e.printStackTrace();        }        /**         * 以CACHE_PATH为文件夹  fileName为文件名         */        File file = new File(CACHE_PATH,fileName);        //我们首先得到他的符文剑        File parentFile = file.getParentFile();        //查看是否存在,如果不存在就创建        if (!parentFile.exists()){            parentFile.mkdirs(); //创建文件夹        }        try {            //将图片保存到本地            /**             * @param format   The format of the compressed image   图片的保存格式             * @param quality  Hint to the compressor, 0-100. 0 meaning compress for             *                 small size, 100 meaning compress for max quality. Some             *                 formats, like PNG which is lossless, will ignore the             *                 quality setting             *                 图片的保存的质量    100最好             * @param stream   The outputstream to write the compressed data.             */            bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));        } catch (FileNotFoundException e) {            e.printStackTrace();        }    }}
  • 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
  • 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

图片缓存—网络缓存

NetCacheUtils .java:

package com.example.bitmaputils.bitmap;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.AsyncTask;import android.util.Log;import android.widget.ImageView;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;/** * 网络缓存工具类 */public class NetCacheUtils {    /**     * 图片     */    private ImageView mImageView;    /**     * 图片地址     */    private String mUrl;    /**     * 本地缓存     */    private SDcardCacheUtils mDcardCacheUtils;    /**     * 内存缓存     */    private MemoryCacheUtils mMemoryCacheUtils;    public NetCacheUtils(SDcardCacheUtils dcardCacheUtils, MemoryCacheUtils memoryCacheUtils) {        mDcardCacheUtils = dcardCacheUtils;        mMemoryCacheUtils = memoryCacheUtils;    }    /**     * 从网络中下载图片     *     * @param image     * @param url     */    public void getDataFromNet(ImageView image, String url) {        new MyAsyncTask().execute(image, url);  //启动Asynctask,传入的参数到对应doInBackground()    }    /**     * 异步下载     * <p/>     * 第一个泛型 : 参数类型  对应doInBackground()     * 第二个泛型 : 更新进度   对应onProgressUpdate()     * 第三个泛型 : 返回结果result   对应onPostExecute     */    class MyAsyncTask extends AsyncTask<Object, Void, Bitmap> {        /**         * 后台下载  子线程         *         * @param params         * @return         */        @Override        protected Bitmap doInBackground(Object... params) {            //拿到传入的image            mImageView = (ImageView) params[0];            //得到图片的地址            mUrl = (String) params[1];            //将imageview和url绑定,防止错乱            mImageView.setTag(mUrl);            Bitmap bitmap = downLoadBitmap(mUrl);            return bitmap;        }        /**         * 进度更新   UI线程         *         * @param values         */        @Override        protected void onProgressUpdate(Void... values) {            super.onProgressUpdate(values);        }        /**         * 回调结果,耗时方法结束后,主线程         *         * @param bitmap         */        @Override        protected void onPostExecute(Bitmap bitmap) {            if (bitmap != null) {                //得到图片的tag值                String url = (String) mImageView.getTag();                //确保图片设置给了正确的image                if (url.equals(mUrl)) {                    mImageView.setImageBitmap(bitmap);                    /**                     * 当从网络上下载好之后保存到sdcard中                     */                    mDcardCacheUtils.savaSd(mUrl, bitmap);                    /**                     *  写入到内存中                     */                    mMemoryCacheUtils.setToMemory(mUrl, bitmap);                    Log.d("MyBitmapUtils", "我是从网络缓存中读取的图片啊");                }            }        }    }    /**     * 下载图片     *     * @param url 下载图片地址     * @return     */    private Bitmap downLoadBitmap(String url) {        //连接        HttpURLConnection conn = null;        try {            conn = (HttpURLConnection) new URL(url)                    .openConnection();            //设置读取超时            conn.setReadTimeout(5000);            //设置请求方法            conn.setRequestMethod("GET");            //设置连接超时连接            conn.setConnectTimeout(5000);            //连接            conn.connect();            //响应码            int code = conn.getResponseCode();            if (code == 200) {  //请求正确的响应码是200                //得到响应流                InputStream inputStream = conn.getInputStream();                //得到bitmap对象                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);                return bitmap;            }        } catch (IOException e) { #          e.printStackTrace();        } finally {            conn.disconnect();        }        return null;    }}
  • 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
  • 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

好了,至此,一个简单的图片的三级缓存完成了,接下来看看使用吧。

图片加载工具类

MyBitmapUtils .java:

package com.example.bitmaputils.bitmap;/** * Created by 若兰 on 2016/1/29. * 一个懂得了编程乐趣的小白,希望自己 * 能够在这个道路上走的很远,也希望自己学习到的 * 知识可以帮助更多的人,分享就是学习的一种乐趣 * QQ:1069584784 * csdn:http://blog.csdn.net/wuyinlei */import android.graphics.Bitmap;import android.widget.ImageView;/** * 自定义的bitmap工具类 */public class MyBitmapUtils {    /**     * 网络缓存     */    public NetCacheUtils mNetCacheUtils;    /**     * 本地缓存     */    public SDcardCacheUtils mSdCacheUtils;    /**     * 内存缓存     */    public MemoryCacheUtils mMemoryCacheUtils;    public MyBitmapUtils() {        mSdCacheUtils = new SDcardCacheUtils();        mMemoryCacheUtils = new MemoryCacheUtils();        mNetCacheUtils = new NetCacheUtils(mSdCacheUtils, mMemoryCacheUtils);    }    /**     * 展示图片的方法     *     * @param image     * @param url     */    public void display(ImageView image, String url) {        //从内存中读取        Bitmap fromMemroy = mMemoryCacheUtils.getFromMemroy(url);        //如果内存中有的h话就直接返回,从内存中读取        if (fromMemroy != null) {            image.setImageBitmap(fromMemroy);            return;        }        //从本地SD卡读取        Bitmap fromSd = mSdCacheUtils.getFromSd(url);        if (fromSd != null) {            image.setImageBitmap(fromSd);            mMemoryCacheUtils.setToMemory(url, fromSd);            return;        }        //从网络中读取        mNetCacheUtils.getDataFromNet(image, url);    }}
  • 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
  • 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

使用这个工具类就很简单了
只需在加载数据的适配器中

//声明图片加载工具类private MyBitmapUtils utils;        public PhotoAdapter() {            //mBitmapUtils = new BitmapUtils(MainActivity.this);           // mBitmapUtils.configDefaultLoadingImage(R.mipmap.defaut);            utils = new MyBitmapUtils();        }然后在getView()方法中,使用工具类中的display()方法就可以了。简单吧utils.display(holder.tvImage,mImageViews[position]);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在这里我们看下图片加载效果:

来看下LOGCAT日志:

01-29 11:19:48.127 5556-5556/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊01-29 11:19:48.395 5556-5556/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊01-29 11:19:48.687 5556-5556/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊01-29 11:19:49.282 5556-5556/com.example.bitmaputils D/MyBitmapUtils: 从内存中加载图片01-29 11:19:49.628 5556-5556/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊01-29 11:19:50.173 5556-5556/com.example.bitmaputils D/MyBitmapUtils: 我是从网络缓存中读取的图片啊01-29 11:19:58.630 5556-5556/com.example.bitmaputils D/MyBitmapUtils: 从内存中加载图片01-29 11:19:58.762 5556-5556/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊01-29 11:19:59.325 5556-5556/com.example.bitmaputils D/MyBitmapUtils: 我是从网络缓存中读取的图片啊01-29 11:19:59.624 5556-5556/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊01-29 11:56:40.897 15045-15045/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊01-29 11:56:40.923 15045-15045/com.example.bitmaputils D/MyBitmapUtils: 从内存中加载图片01-29 11:56:41.105 15045-15045/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊01-29 11:56:41.118 15045-15045/com.example.bitmaputils D/MyBitmapUtils: 从内存中加载图片01-29 11:56:41.268 15045-15045/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊01-29 11:56:41.283 15045-15045/com.example.bitmaputils D/MyBitmapUtils: 从内存中加载图片01-29 11:56:41.431 15045-15045/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊01-29 11:56:43.837 15045-15045/com.example.bitmaputils D/MyBitmapUtils: 从内存中加载图片01-29 11:56:44.013 15045-15045/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊01-29 11:56:46.047 15045-15045/com.example.bitmaputils D/MyBitmapUtils: 从内存中加载图片01-29 11:56:46.222 15045-15045/com.example.bitmaputils D/MyBitmapUtils: 从本地读取图片啊
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

好了,一个简单的图片三级缓存原理就这样的诞生了,当然正如开始所说,这里只是简单的原理介绍,像里面用到的AsyncTask异步加载,和LruCache在这里只是使用,在以后的篇章中会对这两个进行介绍的,好了,由于代码展示的代码量太多,这里我就不在上传怎么显示图片的源码了,下面我会提供github源码地址,可以找到我的这个demo的源码。如果有问题,或者独特的见解,咱们可以讨论哦,QQ:1069584784

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
xUtils类库的使用
android加载大量图片内存溢出的三种解决办法
Android利用Volley异步加载数据(JSON和图片)完整示例
使用ImageLoader实现图片异步加载
Android 使用开源库StickyGridHeaders来实现带sections和headers的GridView显示本地图片效果
Android 高清加载巨图方案, 拒绝压缩图片
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服