Android画像はどのように効率的にロードとキャッシュするか--(3)機能の改善と増加


前の文章の中でまた多くの问题があります:例えばある画像の引き出しの任务を取り消して、画像のロードの过程の中の画像の効果の修正、いくつかのロジックの上の问题、今度は一つ一つ修正します!!
一、タスクを削除可能にする
最初のステップでは、FutureTaskとCallableを組み合わせて、タスクを作成します.△このFutureTaskを無視して、IONの中のものだと思っていたが、これは持参したQQQだとは思わなかった.
私たちはその1つを例に挙げて、これはネットワークがタスクを引き出したもので、他のタスクの作成もそうです.

private class Fetcher implements Callable<String>,ThreadinterFace {

    //      
    ... ...
        @Override
        public String call() throws Exception {

            if (imageView != null || onImageLoad != null){
                OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(5,TimeUnit.SECONDS).build();
                Request request = new Request.Builder().url(imageUrl).build();
                try {
                    Call call = okHttpClient.newCall(request);
                    Response response = call.execute();
                    cacheImage = BitmapFactory.decodeStream(response.body().byteStream());
                    if (cacheImage != null) imageCacher.putCache(tag,cacheImage);
                    if (onLoaded != null) cacheImage = onLoaded.reduce(cacheImage,tag);
                } catch (IOException e) {
                    Log.e("OCImageLoader", "
url:"
+ imageUrl +"
Error:"
+ e.toString()); onError(0); } runOnUIThread(new Runnable() { @Override public void run() { Log.d("OCImageLoader","Image :"+imageUrl+" downloaded"); onDownloadCompleted(cacheImage,imageView,tag,onImageLoad); } }); }else { runOnUIThread(new Runnable() { @Override public void run() { onError(1); } }); } return null; } ... ... }

ステップ2:スレッドプールをカスタマイズし、タスクの制御を実現
public class OCThreadExecutor extends ThreadPoolExecutor {

    //      HashMap          ,     
    private Map<String,FutureTask> runnableMap;

    public OCThreadExecutor(int maxRunningThread, String poolName) {
        super(maxRunningThread, maxRunningThread, 0l, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new OCThreadFactory(poolName));
        runnableMap = new HashMap<>();
    }

    public void submit(FutureTask task , String tag){

        //    
        if ( !runnableMap.containsKey(tag) ){
            //                
            runnableMap.put(tag, task);
            submit(task);
        }else {
            Log.d("OCThreadExecutor", "Same task TAG. Skipped. ");
        }
    }

    public boolean cancelTask(String tag){

        //    

        //     tag         
        if ( runnableMap.containsKey(tag) ){
            //          
            remove(runnableMap.get(tag));
            //          ,      ,      
            runnableMap.remove(tag).cancel(true);
            return true;
        }else{
            Log.d("OCThreadExecutor", "TAG dose not exist. Skipped. ");
            return false;
        }
    }

    public boolean cancelAllTask(){
        //      

        //           
        Iterator<FutureTask> taskList = runnableMap.values().iterator();
        int count = 0;
        while (taskList.hasNext()){
            count++;
            FutureTask task = taskList.next();
            task.cancel(true);
            remove(task);
        }
        runnableMap.clear();
        Log.d("OCThreadExecutor",count +" Tasks canceled.");
        return count > 0;
    }

    public boolean removeTag(String tag){

        //  TAG,        
        if (runnableMap.remove(tag) != null){
            Log.d("OCThreadExecutor","TAG removed.");
            return true;
        }else {
            Log.d("OCThreadExecutor","TAG dose not exist. Skipped. ");
            return false;
        }
    }

    static class OCThreadFactory implements ThreadFactory {...}

    static class OCThread extends Thread {...}

最後に、外部呼び出し用のインタフェースを作成します.
//    
public void cancelTask(String tag){

        //               
        fetherExecutor.cancelTask(tag);

        //            
        cacheExecutor.cancelTask(tag);
    }

//      
public void cancelAllTask(){

        //                 
        fetherExecutor.cancelAllTask();

        //              
        cacheExecutor.cancelAllTask();
    }

第二に、ピクチャロードでピクチャを処理する
私たちは画像の処理を画像ロードのスレッドの中で同時に処理させなければなりません.このように実現する方法も簡単です.画像ロードが完了した後、インタフェースを通じてコールバックし、原図に転送し、処理後の画像を転送すればいいです.
私たちはやはりネットワークで抽出したタスクを例に挙げます.
private class Fetcher implements Callable<String>,ThreadinterFace {

    ... ...

    @Override
        public String call() throws Exception {

            if (imageView != null || onImageLoad != null){
                OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(5,TimeUnit.SECONDS).build();
                Request request = new Request.Builder().url(imageUrl).build();
                try {
                    Call call = okHttpClient.newCall(request);
                    Response response = call.execute();
                    cacheImage = BitmapFactory.decodeStream(response.body().byteStream());
                    if (cacheImage != null) imageCacher.putCache(tag,cacheImage);

                    //           ,   
                    if (onLoaded != null) cacheImage = onLoaded.reduce(cacheImage,tag);
                } catch (IOException e) {
                    Log.e("OCImageLoader", "
url:"
+ imageUrl +"
Error:"
+ e.toString()); onError(0); } runOnUIThread(new Runnable() { @Override public void run() { Log.d("OCImageLoader","Image :"+imageUrl+" downloaded"); onDownloadCompleted(cacheImage,imageView,tag,onImageLoad); } }); }else { runOnUIThread(new Runnable() { @Override public void run() { onError(1); } }); } return null; }

画像処理の呼び出し:
OCImageLoader.loader().loadImage(  tag,       , imageView  , new OnImageLoad() {
            @Override
            public void onLoadCompleted(Bitmap image, String tag) {
                //          
                ... ...
            }

            @Override
            public void onLoadFailed() {
                //          
                ... ...
            }
        }, new HandleOnLoaded() {
            @Override
            public Bitmap reduce(Bitmap bitmap, String tag) {

                //     bitmap      ,Return        。     
                return Blur.fastblur(UserDetailActivity.this,bitmap,20);
            }
        });

第三に、画像非同期処理タスクを追加する
书き终わってやっと前にこれを书いたことを思い出しました...いずれにしても、今回の解釈は前回よりはっきりしています--
private class ReduceImageEffect implements Callable<String>,ThreadinterFace{

        private OnHandleBitmap onHandleBitmap;  //      
        private boolean cacheAsFile;  //       
        private BitmapFactory.Options options; 
        private Bitmap bitmap;  //        
        private String path , url;  //       
        private String cacheTAG;  //       

        public ReduceImageEffect(OnHandleBitmap onHandleBitmap, Bitmap bitmap,BitmapFactory.Options options,boolean cacheAsFile,String path,String url,String id) {
            this.onHandleBitmap = onHandleBitmap;
            this.options = options;
            this.bitmap = bitmap;
            this.cacheAsFile = cacheAsFile;
            this.url = url;
            this.path = path;
            this.cacheTAG = id;
        }

        @Override
        public String call() throws Exception {

            //        Bitmap   ,     Option     
            if(bitmap == null || options != null){

                //       LRU              
                //     ,  TAG              ,             
                bitmap = imageCacher.getByLruCache(cacheTAG);

                if (bitmap == null){

                    //  LRU    ,            
                    Log.e("OCImageLoader","No reduced LRUcache.Trying to load reduced File cache...");
                    bitmap = imageCacher.getByFileCache(cacheTAG);
                    if (bitmap == null){

                        //           ,         
                        Log.e("OCImageLoader","No reduced File cache.Trying to load original File cache...");

                        String cachePath = null;
                        if (url != null){
                            //         ,                    
                            cachePath = imageCacher.getCacheFile(buildTag(url));
                        }else if (path != null){

                            //         ,                    
                            cachePath = imageCacher.getCacheFile(buildTag(path));
                        }

                        if (cachePath == null && path != null && imageCacher.isCanCacheAsFile()){
                        //            ,                  

                            //  Option(  option NULL  )       
                            Log.e("OCImageLoader","No original File cache.Trying to load original File by path...");
                            bitmap = BitmapFactory.decodeFile(path,options);
                        }else if (cachePath != null){
                        //        

                            //  Option(  option NULL  )       
                            bitmap = BitmapFactory.decodeFile(cachePath,options);
                        }
                    }
                }else {
                    Log.d("OCImageLoader","LRUcache found.");
                }
            }else{
                Log.d("OCImageLoader","Option is NULL , using original cache");
            }

            if (bitmap != null && onHandleBitmap != null){
            //           Bitmap   ,           

                //          
                bitmap = onHandleBitmap.onAsynHandleBitmap(path, bitmap);
                if (bitmap != null){
                //     Bitmap   

                    if (cacheAsFile){
                    //        ,     
                        Log.d("OCImageLoader","Tag:"+cacheTAG+" Cached as LRU & File ");
                        imageCacher.putCache(cacheTAG,bitmap);
                    }else {
                    //      LRU  
                        Log.d("OCImageLoader","Tag:"+cacheTAG+" Cached as LRU ");
                        imageCacher.putInLruCaches(cacheTAG,bitmap);
                    }

                    //         
                    cacheExecutor.removeTag(cacheTAG);
                    runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            //  UI  ,         
                            onHandleBitmap.onReduceCompleted(bitmap);
                        }
                    });
                }else {
                    //      Bitmap  ,           
                    Log.e("OCImageLoader","Bitmap become NULL , after onHandleBitmap.");
                    runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            onError(2);
                        }
                    });
                }
            }else {
                //         Bitmap  ,           
                Log.e("OCImageLoader","Failed to load bitmap...");
                runOnUIThread(new Runnable() {
                    @Override
                    public void run() {
                        onError(0);
                    }
                });
            }
            return null;
        }

        @Override
        public void onDownloadCompleted(Bitmap bitmap, ImageView imageView, String tag, OnImageLoad onImageLoadCompleted) {

        }

        @Override
        public void onError(int status) {
            cacheExecutor.removeTag(cacheTAG);
        }

        @Override
        public int hashCode() {
            return cacheTAG.hashCode();
        }

        @Override
        public boolean equals(Object o) {
            return this.hashCode() == o.hashCode() && o instanceof ReduceImageEffect;
        }

    }

第四に、前に発見された論理エラーの修正
呆比了QwQ..画像の読み取りが完了した後の論理に問題があり、コールバックに問題が発生します.
 @Override
        public void onDownloadCompleted(Bitmap bitmap, ImageView imageView, String tag, OnImageLoad onImageLoadCompleted) {
            //       

            //         
            cacheExecutor.removeTag(tag);

            if (bitmap != null && imageView != null && imageView.getTag().equals(tag)){
            //     Bitmap     ,  ImageView   ,    ImageView        

                if (durationMillis > 0 ){
                //              
                    Drawable prevDrawable = imageView.getDrawable();
                    if (prevDrawable == null) {
                        prevDrawable = new ColorDrawable(TRANSPARENT);
                    }
                    Drawable nextDrawable = new BitmapDrawable(imageView.getResources(), bitmap);
                    TransitionDrawable transitionDrawable = new TransitionDrawable(
                            new Drawable[] { prevDrawable, nextDrawable });
                    imageView.setImageDrawable(transitionDrawable);
                    transitionDrawable.startTransition(durationMillis);
                }else {
                    imageView.setImageBitmap(bitmap);
                }
            }

            if (onImageLoadCompleted != null){
            //         ,   
                onImageLoadCompleted.onLoadCompleted(bitmap,tag);
            }

        }