Android画像はどのように効率的にロードとキャッシュするか--(3)機能の改善と増加
前の文章の中でまた多くの问题があります:例えばある画像の引き出しの任务を取り消して、画像のロードの过程の中の画像の効果の修正、いくつかのロジックの上の问题、今度は一つ一つ修正します!!
一、タスクを削除可能にする
最初のステップでは、FutureTaskとCallableを組み合わせて、タスクを作成します.△このFutureTaskを無視して、IONの中のものだと思っていたが、これは持参したQQQだとは思わなかった.
私たちはその1つを例に挙げて、これはネットワークがタスクを引き出したもので、他のタスクの作成もそうです.
ステップ2:スレッドプールをカスタマイズし、タスクの制御を実現
最後に、外部呼び出し用のインタフェースを作成します.
第二に、ピクチャロードでピクチャを処理する
私たちは画像の処理を画像ロードのスレッドの中で同時に処理させなければなりません.このように実現する方法も簡単です.画像ロードが完了した後、インタフェースを通じてコールバックし、原図に転送し、処理後の画像を転送すればいいです.
私たちはやはりネットワークで抽出したタスクを例に挙げます.
画像処理の呼び出し:
第三に、画像非同期処理タスクを追加する
书き终わってやっと前にこれを书いたことを思い出しました...いずれにしても、今回の解釈は前回よりはっきりしています--
第四に、前に発見された論理エラーの修正
呆比了QwQ..画像の読み取りが完了した後の論理に問題があり、コールバックに問題が発生します.
一、タスクを削除可能にする
最初のステップでは、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);
}
}