안드로이드의 그림 레벨 3 캐시

L3 캐시를 사용해야 하는 이유
  • 현재의 안드로이드 앱은 항상 인터넷 상호작용을 필요로 하기 때문에 인터넷을 통해 그림을 얻는 것은 더 이상 정상적인 일이 아니다
  • 만약에 시작할 때마다 인터넷에서 사진을 끌어내면 많은 데이터가 소모될 것이다.현재 상황에서 비와이파이 사용자에게 데이터는 매우 비싸다. 데이터 소모가 많은 응용은 사용자 수량급이 반드시 영향을 받을 것이다
  • 특히 우리가 몇 개의 그림을 다시 찾으려고 할 때 매번 인터넷을 통해 얻어야 한다면 데이터의 낭비는 가히 짐작할 수 있다
  • 따라서 네트워크, 로컬, 메모리의 3급 캐시 이미지를 통해 불필요한 네트워크 상호작용을 줄이고 데이터 낭비를 피한다
  • L3 캐시란?
  • 네트워크 캐시, 우선 로드 없음, 느린 속도, 데이터 낭비
  • 로컬 캐시, 보조 우선 로드, 빠른 속도
  • 메모리 캐시, 우선 로드, 최고 속도
  • 3 레벨 캐시 원리
  • 안드로이드 앱을 처음 로드할 때 반드시 인터넷 상호작용을 통해 그림을 가져와야 한다. 이후에 우리는 그림을 로컬 SD 카드와 메모리에 저장할 수 있다
  • 이후 App 실행 시 메모리에 있는 이미지 캐시에 우선 액세스하고 메모리에 없으면 로컬 SD 카드에 있는 이미지 로드
  • 한 마디로 하면 새로운 내용을 처음 방문할 때만 네트워크를 통해 이미지 자원을 얻을 수 있다
  • 구체적 실현 및 코드
    1. 사용자 정의 이미지 캐시 도구 클래스(MyBitmapUtils)
  • new MyBitmapUtils().display(ImageView ivPic, String url)를 통해 외부 방법으로 이미지 캐시를 제공하는 인터페이스
  • 매개 변수 의미: ivPic는 그림을 표시하는 ImageView에 사용되며, url에서 그림을 가져오는 네트워크 주소
  •     /**
         *     BitmapUtils,      
         */
        public class MyBitmapUtils {
    
            private NetCacheUtils mNetCacheUtils;
            private LocalCacheUtils mLocalCacheUtils;
            private MemoryCacheUtils mMemoryCacheUtils;
    
            public MyBitmapUtils(){
                mMemoryCacheUtils=new MemoryCacheUtils();
                mLocalCacheUtils=new LocalCacheUtils();
                mNetCacheUtils=new NetCacheUtils(mLocalCacheUtils,mMemoryCacheUtils);
            }
    
            public void disPlay(ImageView ivPic, String url) {
                ivPic.setImageResource(R.mipmap.pic_item_list_default);
                Bitmap bitmap;
                //    
                bitmap=mMemoryCacheUtils.getBitmapFromMemory(url);
                if (bitmap!=null){
                    ivPic.setImageBitmap(bitmap);
                    System.out.println("        .....");
                    return;
                }
    
                //    
                bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
                if(bitmap !=null){
                    ivPic.setImageBitmap(bitmap);
                    System.out.println("        .....");
                    //        ,      
                    mMemoryCacheUtils.setBitmapToMemory(url,bitmap);
                    return;
                }
                //    
                mNetCacheUtils.getBitmapFromNet(ivPic,url);
            }
        }

    2. 네트워크 캐시(NetCacheUtils)
  • 네트워크 캐시에서 주로 AsyncTask를 사용하여 비동기식 데이터 로드
  • 간단하게 말하자면 AsyncTask는handler와 스레드 탱크에 대한 봉인으로 볼 수 있다. 일반적으로 AsyncTask는 데이터가 간단할 때handler+thread는 데이터 양이 많고 복잡할 때 주로 사용된다. 물론 이것도 필수적인 것이 아니다. 인자견인지자견지
  • 동시에 메모리가 넘치는 문제를 피하기 위해 우리는 네트워크 그림을 얻은 후에이미지 압축
  •     /**
         *          
         */
        public class NetCacheUtils {
    
            private LocalCacheUtils mLocalCacheUtils;
            private MemoryCacheUtils mMemoryCacheUtils;
    
            public NetCacheUtils(LocalCacheUtils localCacheUtils, MemoryCacheUtils memoryCacheUtils) {
                mLocalCacheUtils = localCacheUtils;
                mMemoryCacheUtils = memoryCacheUtils;
            }
    
            /**
             *        
             * @param ivPic      imageview
             * @param url            
             */
            public void getBitmapFromNet(ImageView ivPic, String url) {
                new BitmapTask().execute(ivPic, url);//  AsyncTask
    
            }
    
            /**
             * AsyncTask   handler       
             *      :    
             *      :       
             *      :onPostExecute     
             */
            class BitmapTask extends AsyncTask<Object, Void, Bitmap> {
    
                private ImageView ivPic;
                private String url;
    
                /**
                 *       ,       
                 * @param params
                 * @return
                 */
                @Override
                protected Bitmap doInBackground(Object[] params) {
                    ivPic = (ImageView) params[0];
                    url = (String) params[1];
    
                    return downLoadBitmap(url);
                }
    
                /**
                 *     ,     
                 * @param values
                 */
                @Override
                protected void onProgressUpdate(Void[] values) {
                    super.onProgressUpdate(values);
                }
    
                /**
                 *             ,    
                 * @param result
                 */
                @Override
                protected void onPostExecute(Bitmap result) {
                    if (result != null) {
                        ivPic.setImageBitmap(result);
                        System.out.println("        .....");
    
                        //        ,       
                        mLocalCacheUtils.setBitmapToLocal(url, result);
                        //      
                        mMemoryCacheUtils.setBitmapToMemory(url, result);
    
                    }
                }
            }
    
            /**
             *       
             * @param url
             * @return
             */
            private Bitmap downLoadBitmap(String url) {
                HttpURLConnection conn = null;
                try {
                    conn = (HttpURLConnection) new URL(url).openConnection();
                    conn.setConnectTimeout(5000);
                    conn.setReadTimeout(5000);
                    conn.setRequestMethod("GET");
    
                    int responseCode = conn.getResponseCode();
                    if (responseCode == 200) {
                        //    
                        BitmapFactory.Options options = new BitmapFactory.Options();
                        options.inSampleSize=2;//        1/2
                        options.inPreferredConfig=Bitmap.Config.ARGB_4444;
                        Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream(),null,options);
                        return bitmap;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    conn.disconnect();
                }
    
                return null;
            }
        }

    3. 로컬 캐시(LocalCacheUtils)
  • 처음 네트워크를 통해 이미지를 검색한 후 로컬 SD 카드에 이미지를 저장할 수 있습니다
  • MD5 암호화 그림의 네트워크 주소를 사용하여 그림의 이름으로 저장할 수 있음
  •     /**
         *          
         */
        public class LocalCacheUtils {
    
            private static final String CACHE_PATH= Environment.getExternalStorageDirectory().getAbsolutePath()+"/WerbNews";
    
            /**
             *        
             * @param url
             */
            public Bitmap getBitmapFromLocal(String url){
                String fileName = null;//    url     ,   MD5  
                try {
                    fileName = MD5Encoder.encode(url);
                    File file=new File(CACHE_PATH,fileName);
    
                    Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
    
                    return bitmap;
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                return null;
            }
    
            /**
             *         ,       
             * @param url
             * @param bitmap
             */
            public void setBitmapToLocal(String url,Bitmap bitmap){
                try {
                    String fileName = MD5Encoder.encode(url);//    url     ,   MD5  
                    File file=new File(CACHE_PATH,fileName);
    
                    //          ,         
                    File parentFile = file.getParentFile();
                    if (!parentFile.exists()){
                        parentFile.mkdirs();
                    }
    
                    //        
                    bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
            }
        }

    4. 메모리 캐시(Memory CacheUtils)
  • 이것은 본문에서 가장 중요하고 중점적으로 소개해야 할 부분
  • 메모리 캐시를 진행할 때 반드시 주의해야 할 문제는 메모리 넘침(OutOfMemory)
  • 이다.
  • 왜 메모리 넘침을 초래합니까?
  • Android 가상 머신은 기본적으로 모든 App 16M의 메모리 공간에 분배되며 실제 머신은 16M보다 크지만 메모리가 넘치는 경우
  • 안드로이드 시스템은 그림을 불러올 때 모든 픽셀의 정보를 분석하고 모든 픽셀을 메모리에 저장한다
  • 이미지 크기 = 이미지의 전체 픽셀* 픽셀당 크기
    단색도: 픽셀당 1/8바이트, 16색도: 픽셀당 1/2바이트, 256색도: 픽셀당 1바이트, 24비트맵: 픽셀당 3바이트(흔한 rgb로 구성된 그림)
  • 예를 들어 1920x1080의 JPG 사진은 안드로이드 시스템에서 ARGB 형식으로 해석된다. 즉, 하나의 픽셀은 4바이트를 차지하고 그림의 크기는 1920x1080x4=7M
  • 이다.
  • 구현 방법:
  • 키 값이 맞는 방식으로 그림을 저장합니다. 키는 주소이고value는 그림 대상이지만 강한 인용 대상이기 때문에 메모리가 넘치기 쉽습니다.SoftReference 소프트 인용 대상
  • 을 시도해 보십시오.
  • HashMapSoftReference를 통해 소프트 인용 대상(GC 쓰레기 회수는 자동으로 소프트 인용 대상)을 회수하지만 안드로이드2.3+ 이후 시스템은 약한 인용 대상을 회수하는 것을 우선적으로 고려하고 공식적으로 LruCache
  • 사용을 제안한다.
  • 통과HashMap>least recentlly use 최소 최근 사용 알고리즘은 메모리를 일정한 크기로 제어하고 최대치를 초과할 때 자동으로 회수한다. 이 최대치는 개발자가 스스로 정한다
  •     /**
         *          
         */
        public class MemoryCacheUtils {
    
            // private HashMap mMemoryCache=new HashMap<>();//1.     ,        ,              
            // private HashMap> mMemoryCache = new HashMap<>();//2.   Android2.3+ ,              ,      LruCache
            private LruCache mMemoryCache;
    
            public MemoryCacheUtils(){
                long maxMemory = Runtime.getRuntime().maxMemory()/8;//           1/8,       ,     
                //            ,       16M,       
                mMemoryCache=new LruCache((int) maxMemory){
                    //           
                    @Override
                    protected int sizeOf(String key, Bitmap value) {
                        int byteCount = value.getByteCount();
                        return byteCount;
                    }
                };
    
            }
    
            /**
             *        
             * @param url
             */
            public Bitmap getBitmapFromMemory(String url) {
                //Bitmap bitmap = mMemoryCache.get(url);//1.     
                /*2.     
                SoftReference bitmapSoftReference = mMemoryCache.get(url);
                if (bitmapSoftReference != null) {
                    Bitmap bitmap = bitmapSoftReference.get();
                    return bitmap;
                }
                */
                Bitmap bitmap = mMemoryCache.get(url);
                return bitmap;
    
            }
    
            /**
             *        
             * @param url
             * @param bitmap
             */
            public void setBitmapToMemory(String url, Bitmap bitmap) {
                //mMemoryCache.put(url, bitmap);//1.     
                /*2.     
                mMemoryCache.put(url, new SoftReference<>(bitmap));
                */
                mMemoryCache.put(url,bitmap);
            }
        }

    좋은 웹페이지 즐겨찾기