如何處理來自UI線程的位圖

如何處理來自UI線程的位圖,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

為平潭等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及平潭網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)、平潭網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

BitmapFactory的decode()方法,在Load Large Bitmaps Efficiently要 點(diǎn)中進(jìn)行討論,不應(yīng)該執(zhí)行在主UI線程如果要讀取源數(shù)據(jù)從磁盤或網(wǎng)絡(luò)位置(或相對(duì)內(nèi)存來說任何別的真實(shí)來源).該數(shù)據(jù)需要加載的時(shí)間是不可預(yù)知的,并取決 于多種因素(從磁盤或網(wǎng)絡(luò)的讀取速度,圖像大小,CPU的功率,等).如果這些任務(wù)阻塞UI線程,系統(tǒng)標(biāo)志您的應(yīng)用程序無響應(yīng),用戶可以選擇關(guān)閉它響應(yīng) (有關(guān)更多信息,請(qǐng)參閱Designing for Responsiveness).

將引導(dǎo)您通過在后臺(tái)線程中使用AsyncTask處理位圖,并告訴您如何處理并發(fā)問題.

使用一個(gè)異步任務(wù)

AsyncTask類提供了一種簡(jiǎn)單的方式來在一個(gè)后臺(tái)線程中執(zhí)行許多任務(wù),并且把結(jié)果反饋給UI線程.使用的方法是,創(chuàng)建一個(gè)繼承與它的子類并且實(shí)現(xiàn)提供的方法.這里是一個(gè)使用AsyncTask和decodeSampledBitmapFromResource()加載一個(gè)大圖片到ImageView中的例子:

class BitmapWorkerTask extends AsyncTask {     private final WeakReference imageViewReference;     private int data = 0;      public BitmapWorkerTask(ImageView imageView) {         // Use a WeakReference to ensure the ImageView can be garbage collected         imageViewReference = new WeakReference(imageView);     }      // Decode image in background.     @Override     protected Bitmap doInBackground(Integer... params) {         data = params[0];         return decodeSampledBitmapFromResource(getResources(), data, 100, 100));     }      // Once complete, see if ImageView is still around and set bitmap.     @Override     protected void onPostExecute(Bitmap bitmap) {         if (imageViewReference null) {             final ImageView imageView = imageViewReference.get();             if (imageView != null) {                 imageView.setImageBitmap(bitmap);             }         }     }  }

對(duì)于ImageView來說WeakReference確保那時(shí)AsyncTask并不會(huì)阻礙ImageView和任何它的引用被垃圾回收期回收.不能保證ImageView在任務(wù)完成后仍然存在,所以你必須在onPostExecute()方法中檢查它的引用.ImageView可能不再存在,如果例如,如果在任務(wù)完成之前用戶退出了活動(dòng)或者配置發(fā)生了變化.

為了異步地加載位圖,簡(jiǎn)單地創(chuàng)建一個(gè)新的任務(wù)并且執(zhí)行它:

public void loadBitmap(int resId, ImageView imageView) {     BitmapWorkerTask task = new BitmapWorkerTask(imageView);     task.execute(resId);  }

處理并發(fā)

常見的視圖組件例如ListView和GridView如在上一節(jié)中當(dāng)和AsyncTask結(jié)合使用時(shí)引出了另外一個(gè)問題.為了優(yōu)化內(nèi)存,當(dāng)用戶滾 動(dòng)時(shí)這些組件回收了子視圖.如果每個(gè)子視圖觸發(fā)一個(gè)AsyncTask,當(dāng)它完成時(shí)沒法保證,相關(guān)的視圖還沒有被回收時(shí)已經(jīng)用在了別的子視圖當(dāng)中.此外, 還有異步任務(wù)開始的順序是不能保證他們完成的順序.

這篇文章透過Multithreading for  Performance功能討論處理并發(fā),并且提供了一個(gè)當(dāng)任務(wù)完成后ImageView將一個(gè)引用存儲(chǔ)到后面能被檢查的AsyncTask的解決方案. 使用類似的方法,從上一節(jié)的AsyncTask可以擴(kuò)展到遵循類似的模式.

創(chuàng)建一個(gè)專用的Drawable的子類來存儲(chǔ)一個(gè)引用備份到工作任務(wù)中.在這種情況下,一個(gè)BitmapDrawable被使用以便任務(wù)完成后一個(gè)占位符圖像可以顯示在ImageView中:

static class AsyncDrawable extends BitmapDrawable {     private final WeakReference bitmapWorkerTaskReference;      public AsyncDrawable(Resources res, Bitmap bitmap,             BitmapWorkerTask bitmapWorkerTask) {         super(res, bitmap);         bitmapWorkerTaskReference =             new WeakReference(bitmapWorkerTask);     }      public BitmapWorkerTask getBitmapWorkerTask() {         return bitmapWorkerTaskReference.get();     }  }

執(zhí)行BitmapWorkerTask前,你創(chuàng)建一個(gè)AsyncDrawable,并將其綁定到目標(biāo)ImageView:

public void loadBitmap(int resId, ImageView imageView) {     if (cancelPotentialWork(resId, imageView)) {         final BitmapWorkerTask task = new BitmapWorkerTask(imageView);         final AsyncDrawable asyncDrawable =                 new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);         imageView.setImageDrawable(asyncDrawable);         task.execute(resId);     }  }

如果別的正在運(yùn)行的任務(wù)已經(jīng)和這個(gè)ImageView關(guān)聯(lián),cancelPotentialWork引用在上面的代碼示例檢查中.如果這樣,它試圖通過調(diào)用cancel()取消先前的任務(wù).在少數(shù)情況下,新的任務(wù)數(shù)據(jù)匹配現(xiàn)有的任務(wù),而且并不需要做什么.下面是實(shí)現(xiàn) cancelPotentialWork:

public static boolean cancelPotentialWork(int data, ImageView imageView) {     final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);     if (bitmapWorkerTask != null) {         final int bitmapData = bitmapWorkerTask.data;         if (bitmapData != data) {             // Cancel previous task             bitmapWorkerTask.cancel(true);         } else {             // The same work is already in progress             return false;         }     }     // No task associated with the ImageView, or an existing task was cancelled     return true;  }

一個(gè)幫助方法,getBitmapWorkerTask(),使用以上來檢索一個(gè)和特定ImageView相關(guān)的任務(wù):

private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {    if (imageView != null) {        final Drawable drawable = imageView.getDrawable();        if (drawable instanceof AsyncDrawable) {            final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;            return asyncDrawable.getBitmapWorkerTask();        }     }     return null;  }

這***一步是在BitmapWorkerTask更新onPostExecute()方法,以便任務(wù)取消時(shí)并且當(dāng)前任務(wù)和這個(gè)ImageView關(guān)聯(lián)時(shí)進(jìn)行檢查:

class BitmapWorkerTask extends AsyncTask {     ...     @Override     protected void onPostExecute(Bitmap bitmap) {         if (isCancelled()) {             bitmap = null;         }         if (imageViewReference != null && bitmap != null ) {             final ImageView imageView = imageViewReference.get();             final BitmapWorkerTask bitmapWorkerTask =                     getBitmapWorkerTask(imageView);             if (this == bitmapWorkerTask && imageView != null) {                 imageView.setImageBitmap(bitmap);             }         }     }  }

現(xiàn)在這個(gè)實(shí)現(xiàn)適合使用ListView和GridView控 件組件以及回收其子視圖的任何其他組件.在你正常地給你的ImageView控件設(shè)置圖片時(shí)簡(jiǎn)單地調(diào)用loadBitmap就行了.例如,在一個(gè) GridView中實(shí)現(xiàn)的方式是在支持的適配中的[android.view.View, android.view.ViewGroup)  getView()](http://docs.eoeandroid.com/reference/android/widget /Adapter.html#getView(int,)方法中.

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。

本文名稱:如何處理來自UI線程的位圖
網(wǎng)站網(wǎng)址:http://bm7419.com/article2/igesic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、建站公司、外貿(mào)網(wǎng)站建設(shè)、定制網(wǎng)站、標(biāo)簽優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計(jì)公司