안 드 로 이 드 비동기 다운로드 사진 벽

12900 단어
안 드 로 이 드 비동기 다운로드 사진 벽
저작권 성명: 본 고 는 ShengFQ 의 블 로그 에서 나 왔 습 니 다. 전재 출처 를 밝 혀 주 십시오.http://www.jianshu.com/p/1709ea24ebbb
나의 문제
서버 에서 그림 주소 목록 을 다운로드 하고 이미지 뷰 에 그림 을 다운로드 하여 캐 시 와 압축 을 실현 하려 고 합 니 다.압축 된 그림 을 다운로드 하려 면 서버 에서 먼저 압축 한 후에 저장 해 야 합 니 다. 여 기 는 클 라 이언 트 범위 만 말 하고 토론 하지 않 습 니 다.
예비 지식 필요: 1. AsyncTask 비동기 호출 방법 json 데이터 2. listview, viewaadapter 의 고성능 쓰기 3. HandlerThread, Hander, Message 비동기 메시지 체제 4. LurCache 캐 시 5. BitmapFactory 의 압축 그림 다운로드
1. AsyncTask 비동기 호출 방법 은 json 데 이 터 를 다운로드 합 니 다. AsyncTask 와 Adapter 조합 은 서버 에서 그림 주 소 를 포함 한 json 형식 데 이 터 를 끌 어 옵 니 다.2. listview, view adapter 의 고성능 쓰기

viewadapter.java     
Object mlock;//    list ,   list      
Context mContext;//     
List datalist;//list   
int itemLayoutId;//adapterview        id
getDataList();
reload(List models);
add(model model);
addAll(List models);
render(Model model,View view,int position);//    ViewHolder  getView     
getCount();
getItem(int position);
getItemId(int position);
class ViewHolder{}
getView(int position,View convertView,ViewGroup parent);

//            view 
protected void render(LinkModel linkmodel,View view,int position){
     final LinkModel item=linkmodel;
     ViewHolder viewHolder=(ViewHolder)view.getTag();
     //        ,             
     if(viewHolder==null){
         viewHolder=new ViewHolder();
        viewHolder.app_layout= (FrameLayout)view.findViewById(R.id.iv_app_layout);
        viewHolder.app_icon_layout=(LinearLayout)view.findViewById(R.id.app_icon_layout);
        viewHolder.app_log_iv=(ImageView)view.findViewById(R.id.ic_app_ico);
        viewHolder.app_name_tv=(TextView)view.findViewById(R.id.ic_app_name);
        view.setTag(viewHolder);
     }else{
         viewHolder=(ViewHolder)view.getTag();
     }
     if(item!=null){
         viewHolder.app_log_iv.setImageResource(R.drawable.app_img_app_normal);
         viewHolder.app_name_tv.setText(item.name);
         if (ImageCache.getInstance(mCacheSize).isCache(item.photoUrl)) {
             viewHolder.app_log_iv.setImageBitmap(ImageCache.getInstance(mCacheSize).getBitmapFromMemCache(item.photoUrl));
            }else{
        //          ,Token      imageview   
         mThumbnailThread.queueThumbnail(viewHolder.app_log_iv, item.photoUrl);
            }
    }
}


AsyncTask 에서 배경 에 있 는 json 데 이 터 를 실체 대상 에 밀봉 하고 상기 adapter. addAll (List models) 을 통 해 adapter 에 주입 합 니 다.
3. HandlerThread, Hander, Message 비동기 메시지 체 제 는 Thunbnail Downloader 류 를 정의 합 니 다. 다운로드 요청 메 시 지 를 보 내 고 다른 스 레 드 에서 배경 으로 다운로드 하고 프론트 UI 스 레 드 와 의 상호작용 을 통 해 불 러 옵 니 다.
public class ThumbnailDownLoader extends HandlerThread {
    private static final String TAG="ThumbnailDownLoader";
    private static final int MESSAGE_DOWNLOAD=0;
    private Handler mHandler;
    private String requestToken;
    private int mCacheSize;
    Map requestMap= Collections.synchronizedMap(new HashMap());
    /**
     *      Handler  
     * */
    Handler mRespoonseHandler;
    //      
    Listener mListener;
    
    /**
     *           
     *           :      UI   ImageView
     * */
    public interface Listener{
        /**
         *        ,            ImageView
         * @param token        
         * @param thumbnail     
         * */
        void onThumbnailDownloaded(Token token,Bitmap thumbnail);
    }

    public void setListener(Listener listener){
        mListener=listener;
    }

    public ThumbnailDownLoader(String requesttoken){
        super(TAG);
        this.requestToken=requesttoken;
    }

    /**
     *       Handler
     * @param responseHandler   UI  handler
     * @param requesttoken        token
     * @param cacheSize     
     * */
    public ThumbnailDownLoader(Handler responseHandler,String requesttoken,int cacheSize){
        super(TAG);
        mRespoonseHandler=responseHandler;
        this.requestToken=requesttoken;
        this.mCacheSize=cacheSize;
    }
/**
 *          Looper           
 * */

 @SuppressLint("handlerLeak")
 @Override
 protected void onLooperPrepared(){
    mHandler=new Handler(){
    //looper            ,        what      
      public void handleMessage(Message msg){
        if(msg.what==MESSAGE_DOWNLOAD){
            @SuppressWarnings("unchecked")
            Token token=(Token)msg.obj;//Handler.obtainMessage(msg,obj);  Handler  Message   message.obj,       ,    obj,      。
            Log.i(TAG,"Got a request for url:"+requestMap.get(token));
            handleRequest(token,requestToken);
        }
      }
    };
 }
 /**
  *   message      , URL Token     hashMap 
  *    getView()       
  * @param token      UI  
  * @param url          
  * */
    public void queueThumbnail(Token token,String url){
        Log.i(TAG,"Got to URL:"+url);
        requestMap.put(token,url);//  getview()     
        Message message=mHandler.obtainMessage(MESSAGE_DOWNLOAD,token);//           ,      handler   
        message.sendToTarget();//         
    }

    /**
     *       ,             UI ImageView 
     * @param token     ,      ImageView
     * */
    private void handleRequest(final Token token,final String requestToken){
        try{
            final String url=requestMap.get(token);
            if(url==null)
            return;
            byte[] bitmapBytes=new ImageLoaderUtils().getUrlBytes(url,requestToken);
           // final Bitmap bitmap= BitmapFactory.decodeByteArray(bitmapBytes,0,bitmapBytes.length);
            final Bitmap bitmap=  ImageCompress.decodeSampleBitmapFromBytes(bitmapBytes, 54, 54);//    
            ImageCache.getInstance(mCacheSize).addBitmapToMemoryCache(url, bitmap);
            Log.i(TAG,"Bitmap created");
            //                  UI  
            mRespoonseHandler.post(new Runnable(){
                public void run(){
                    if(requestMap.get(token)!=url) return;
                    requestMap.remove(token);//
                    Bitmap cachebitmap =ImageCache.getInstance(mCacheSize).getBitmapFromMemCache(url);
                    if(cachebitmap!=null)
                        mListener.onThumbnailDownloaded(token,cachebitmap);
                    else{
                          mListener.onThumbnailDownloaded(token,bitmap);
                    }
                }
            });
            
        }catch(IOException ioe){
            Log.e(TAG,"Error downloading image",ioe);
        }
    }

    public void clearQueue(){
        mHandler.removeMessages(MESSAGE_DOWNLOAD);
        requestMap.clear();
    }
}


설명: HandlerThread 는 메시지 알림 처리 스 레 드 클래스 onLooperPrepared (); /Handler 를 초기 화 하 는 곳 입 니 다. Handler Thread 가 초기 화 되면 Loop () 에 들 어가 기 전에 호출 되 는 방법 이기 때 문 입 니 다. Handler 를 초기 화 하 는 것 은 메시지 가 전송 되 기 전에 handler 를 초기 화 하 는 데 도움 이 됩 니 다.
Handler handlleMessage(Message msg);//메시지 의 분류 와 메시지 에 첨부 된 매개 변수 에 따라 handler. obtainMessage (String msg, object) / / Message 대상 message. sendToTarget () 을 비동기 로 다운로드 합 니 다. /메시지 큐 handler. removeMessages (String msg) 에 메 시 지 를 보 냅 니 다. /이 메 시 지 를 지우 고 자원 을 방출 합 니 다.
프론트 UI 스 레 드 와 어떻게 대화 합 니까?
이미 image 를 다운 로드 했 습 니 다. UI 스 레 드 의 Imageview 에 채 우려 면 프론트 데스크 와 상호작용 을 해 야 합 니 다. 맞습니다. 프론트 UI 스 레 드 에 도 Handler 가 있 고 하나 밖 에 없습니다. 프론트 데스크 의 handler 를 백 스테이지 에 전달 하여 공유 합 니 다.
/**
 *      Handler  
 * 
Handler mRespoonseHandler;
/**
     *       Handler
     * @param responseHandler   UI  handler
     * @param requesttoken        token
     * @param cacheSize     
     * */
public ThumbnailDownLoader(Handler responseHandler,String requesttoken,int cacheSize){
    super(TAG);
    mRespoonseHandler=responseHandler;
    this.requestToken=requesttoken;
    this.mCacheSize=cacheSize;
}


그림 을 다운로드 한 후 handler. post () 를 통 해방법 과 프론트 UI 상호작용

//                  UI  
    mRespoonseHandler.post(new Runnable(){
        public void run(){
            if(requestMap.get(token)!=url) return;
            requestMap.remove(token);//
            Bitmap cachebitmap =ImageCache.getInstance(mCacheSize).getBitmapFromMemCache(url);
            if(cachebitmap!=null)
                mListener.onThumbnailDownloaded(token,cachebitmap);//      
            else{
                  mListener.onThumbnailDownloaded(token,bitmap);
            }
        }
    });
    

Listener mListener;//인터페이스 대상 을 되 돌려 그림 을 다운로드 한 후 그림 을 imageview 에 설정 합 니 다.
/**
 *           
 *           :      UI   ImageView
 * */
public interface Listener{
    /**
     *        ,            ImageView
     * @param token        
     * @param thumbnail     
     * */
    void onThumbnailDownloaded(Token token,Bitmap thumbnail);
}

public void setListener(Listener listener){
    mListener=listener;
}


메 인 스 레 드 UI 로 돌아 가기
따라서 UI 스 레 드 에서 두 가지 일 을 하고 HandlerThread 를 초기 화하 여 리 셋 인 터 페 이 스 를 실현 합 니 다.
  //           
mThumbnailThread = new ThumbnailDownLoader(new Handler(),token,mCacheSize);//    Looper   Handler
mThumbnailThread.setListener(new ThumbnailDownLoader.Listener() {
    public void onThumbnailDownloaded(ImageView imageView, Bitmap thumbnail) {
        if (true) {
            // ImageView    Bitmap
            imageView.setImageBitmap(thumbnail);
        }
    }
});
mThumbnailThread.start();
mThumbnailThread.getLooper();


어떻게 비동기 다운 로드 를 촉발 합 니까
우리 가 실현 하고 자 하 는 효 과 는 gridview 를 끌 어 내 릴 때 그림 을 자동 으로 다운로드 하여 gridview 에 있 는 imageview 보기 로 불 러 오 는 것 입 니 다. 따라서 adapter. getView () 방법 에 초점 을 맞 추 려 면 HandlerThread 의 현재 Imageview 인 스 턴 스 와 다운로드 해 야 할 그림 URL 에 두 개의 중요 한 매개 변수 가 전달 되 어야 합 니 다.
mThumbnailThread.queueThumbnail(viewHolder.app_log_iv, item.photoUrl);

4. LurCache 캐 시 는 주로 LruCache 클래스 를 사 용 했 습 니 다. 이 클래스 의 사용 방법 은 다음 과 같 습 니 다. 일반 캐 시 크기 는 다음 과 같 습 니 다.
UI     
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);  
        //           1/8       。  
        mCacheSize = maxMemory / 8;  
/**
 *     
 * */
public class ImageCache {
    private static ImageCache instance;
    
    /**
     *    ,    
     */
    public static ImageCache getInstance(int cacheSize) {
        if (instance == null) {
            synchronized (ImageCache.class) {
                if (instance == null) {
                    instance = new ImageCache(cacheSize);
                }
            }
        }
        return instance;
    }
    private LruCache mMemoryCache;
    private ImageCache(int cacheSize){
        mMemoryCache=new LruCache(cacheSize){
            protected int sizeOf(String key,Bitmap bitmap){
                return bitmap.getByteCount()/1024;
            }
        };
    }
    
    /**
     *      
     * */
    public void addBitmapToMemoryCache(String key,Bitmap bitmap){
        if(getBitmapFromMemCache(key) ==null){
            mMemoryCache.put(key, bitmap);
        }
    }
    /**
     *       
     * */
    public Bitmap getBitmapFromMemCache(String key){
        return mMemoryCache.get(key);
    }
    /**
     *       
     * */
    public boolean isCache(String key){
        Bitmap map=mMemoryCache.get(key);
        return map!=null;
    }
}


5. BitmapFactory 의 압축 그림
ImageCompress.java
/**
     * 
     *           */
public static Bitmap decodeSampleBitmapFromBytes(byte[] data,int reqWidth,int reqHeight){
    final BitmapFactory.Options options=new BitmapFactory.Options();
    options.inJustDecodeBounds=true;
    //BitmapFactory.decodeResource(resource, resId, options);
    BitmapFactory.decodeByteArray(data, 0, data.length, options);
    options.inSampleSize=calculateInSampleSize(options, reqWidth, reqHeight);
    options.inJustDecodeBounds=false;
    return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}

//     ,      inSamplesize,           
public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){
    //
    final int height=options.outHeight;
    final int width=options.outWidth;
    int inSampleSize=1;
    if(height>reqHeight || width>reqWidth){
        final int heightRatio=Math.round((float)height/(float)reqHeight);
        final int widthRatio=Math.round((float)width/(float)reqWidth);
        inSampleSize=heightRatio

참고 자료
1.http://blog.csdn.net/guolin_blog / article / details / 9526203 안 드 로 이 드 사진 벽 응용 이 실현 되 었 습 니 다. 아무리 많은 사진 이라도 붕 괴 를 두려워 하지 않 습 니 다.
2 http://blog.csdn.net/guolin_blog / article / details / 9316683 안 드 로 이 드 고 효율 로드 큰 그림, 다 중 그림 솔 루 션, 프로그램 OOM 을 효과적으로 피 할 수 있 습 니 다.
3. android 개발 프로 그래 밍 권위 가이드

좋은 웹페이지 즐겨찾기