編輯:關於Android編程
鏈接上一篇博文
本篇博文接著講述本地圖片的獲取。
下面給出獲取本地圖片的異步線程類LoadLoacalPhotoCursorTask的代碼:
/**
* 獲取本地圖片的異步線程類
*/
public class LoadLoacalPhotoCursorTask extends AsyncTask
下面給出加載圖片的類ImageWorker的代碼:
/**
* 手機本地圖片異步加載處理類
* 圖片的加載性能影響很大,使用弱引用和軟引用
* 緩存圖片,加快響應的速度,提高性能。
*/
public class ImageWorker {
//這個值設置的是加載圖片的動畫效果的間隔時間,達到漸隱漸顯的效果
private static final int FADE_IN_TIME = 200;
private boolean mExitTasksEarly = false;//判斷圖片加載任務是否提前退出
private boolean mPauseWork = false;//加載圖片線程是否掛起
private final Object mPauseWorkLock = new Object();//鎖對象,這個鎖對象是為了判斷是否進行圖片的加載
protected final Resources mResources;
private final ContentResolver mContentResolver;//內容解析者
private final BitmapFactory.Options mOptions;
private final HashMap> bitmapCache = new HashMap>();//用於緩存圖片,每一個緩存的圖片對應一個Long類型的id值,SoftReference對應該圖片的軟引用
private Bitmap mLoadBitmap;//GridView中默認的背景圖片
//構造器
public ImageWorker(Context context) {
this.mResources = context.getResources();
this.mContentResolver = context.getContentResolver();
mOptions = new BitmapFactory.Options();
mOptions.inSampleSize = 3;//縮放圖片為原來的1/9。一般應用中加載圖片都會進行圖片的縮放,防止內存溢出的問題。這部分的內容有關Bitmap,請參考我的博文(http://blog.csdn.net/u010156024/article/details/44103557)
}
/**
* 加載圖片
* @param origId 每個本地圖片對應一個id值
* @param imageView
*/
public void loadImage(long origId, ImageView imageView) {
BitmapDrawable bitmapDrawable = null;
//先從緩存中加載圖片,如果緩存中有,加載圖片即可。
//如果緩存中沒有,首先判斷當前任務是否暫停,沒有暫停則使用loadBitmapTask異步任務線程加載圖片
if (bitmapCache.containsKey(origId)) {
bitmapDrawable = bitmapCache.get(origId).get();
}
if (bitmapDrawable != null) {
imageView.setImageDrawable(bitmapDrawable);
} else if (cancelPotentialWork(origId, imageView)) {
final LoadBitmapTask loadBitmapTask = new LoadBitmapTask(imageView);
final AsyncDrawable asyncDrawable =
new AsyncDrawable(mResources, mLoadBitmap, loadBitmapTask);
imageView.setImageDrawable(asyncDrawable);
//SERIAL_EXECUTOR 啟動線程,保證線程順序依次執行
loadBitmapTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, origId);
}
}
/**
* 該類提供這個方法設置GridView中每個item默認的圖片
*/
public void setLoadBitmap(Bitmap mLoadBitmap) {
this.mLoadBitmap = mLoadBitmap;
}
/**
* 設置圖片動畫 加載圖片漸隱漸顯的效果
*
* @param imageView
* @param drawable
*/
private void setImageDrawable(ImageView imageView, Drawable drawable) {
final TransitionDrawable td =
new TransitionDrawable(new Drawable[]{
new ColorDrawable(android.R.color.transparent),
drawable
});
imageView.setImageDrawable(td);
td.startTransition(FADE_IN_TIME);
}
/**
* 取消可能在運行並且暫停的任務。
*
* @param origId
* @param imageView
* @return
*/
private static boolean cancelPotentialWork(long origId, ImageView imageView) {
final LoadBitmapTask loadBitmapTask = getBitmapWorkerTask(imageView);
if (loadBitmapTask != null) {
final long bitmapOrigId = loadBitmapTask.origId;
if (bitmapOrigId == origId) {
loadBitmapTask.cancel(true);
} else {
// The same work is already in progress.
return false;
}
}
return true;
}
/**
* 圖片異步加載線程類-任務線程
*/
private class LoadBitmapTask extends AsyncTask {
private long origId;
private WeakReference imageViewReference;//指向Imageview的弱引用,把圖片緩存在HashMap> bitmapCache中。
public LoadBitmapTask(ImageView imageView) {
imageViewReference = new WeakReference(imageView);
}
@Override
protected BitmapDrawable doInBackground(Long... params) {
origId = params[0];
Bitmap bitmap = null;
BitmapDrawable drawable = null;
// Wait here if work is paused and the task is not cancelled
synchronized (mPauseWorkLock) {
while (mPauseWork && !isCancelled()) {
try {
mPauseWorkLock.wait();
} catch (InterruptedException e) {
}
}
}
if (bitmapCache != null && !isCancelled() && getAttachedImageView() != null
&& !mExitTasksEarly) {
//這裡是根據圖片的id值查詢手機本地的圖片,獲取圖片的縮略圖,MICRO_KIND 代表96*96大小的圖片
bitmap = MediaStore.Images.Thumbnails.getThumbnail(
mContentResolver,
origId,
MediaStore.Images.Thumbnails.MICRO_KIND,
mOptions
);
}
if (bitmap != null) {
drawable = new BitmapDrawable(mResources, bitmap);
bitmapCache.put(origId,new SoftReference(drawable));
}
return drawable;
}
@Override
protected void onPostExecute(BitmapDrawable drawable) {
if (isCancelled() || mExitTasksEarly) {
drawable = null;
}
final ImageView imageView = getAttachedImageView();
if (drawable != null && imageView != null) {
setImageDrawable(imageView, drawable);
}
}
@Override
protected void onCancelled(BitmapDrawable drawable) {
super.onCancelled(drawable);
synchronized (mPauseWorkLock) {
mPauseWorkLock.notifyAll();
}
}
/**
* 返回與此任務相關的ImageView,
* 如果ImageView 內的任務是當前任務,
* 則返回當前ImageView,否則返回null。
* @return
*/
private ImageView getAttachedImageView() {
final ImageView imageView = imageViewReference.get();
final LoadBitmapTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask) {
return imageView;
}
return null;
}
}
/**
* 存儲異步信息圖片資源類
*/
private static class AsyncDrawable extends BitmapDrawable {
private final WeakReference bitmapWorkerTaskReference;//虛引用
public AsyncDrawable(Resources res, Bitmap bitmap, LoadBitmapTask bitmapWorkerTask) {
super(res, bitmap);
bitmapWorkerTaskReference =
new WeakReference(bitmapWorkerTask);
}
public LoadBitmapTask getLoadBitmapTask() {
return bitmapWorkerTaskReference.get();
}
}
/**
* 返回圖片資源內存放的異步線程,如果存在,則返回,不存在,返回null。
*
* @param imageView 當前存放異步資源圖片的ImageView
* @return
*/
private static LoadBitmapTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getLoadBitmapTask();
}
}
return null;
}
/**
* 設置異步任務是否暫停,false為啟動,true為暫停。
* @param pauseWork
*/
public void setPauseWork(boolean pauseWork) {
synchronized (mPauseWorkLock) {
mPauseWork = pauseWork;
if (!mPauseWork) {
mPauseWorkLock.notifyAll();
}
}
}
/**
* 退出線程
* @param exitTasksEarly
*/
public void setExitTasksEarly(boolean exitTasksEarly) {
mExitTasksEarly = exitTasksEarly;
setPauseWork(false);//這個設置為false,使得退出任務優雅。這個設置為true也是可行的,也沒有問題,可以達到同樣的效果。但是可以比較設置為true或false的區別。
}
}
至此 全部講述了android手機中獲取本地圖片的全部內容。這個項目代碼在Github中開放學習,非常值得大家深入研究學習之後。
總結:
整個項目使用到了ContentResolver、軟引用、弱引用、緩存、異步線程、節省內存技巧-滾動不加載、鎖機制、圖片縮放、線程通信、動畫等非常實用的方法、技巧。
開發Android APP微信支付功能,需要完成三個步驟:第一步生成預支付訂單、第二步生成微信支付參數、第三步調起微信APP支付。除了需要審核通過的APP應用外,還需要獲
將Fragment與Layout結合使用,一般都是主Activity以frame填充Activity的方式交互管理Fragment :1.由於用到getSupportFr
結構型模式中的適配器模式、外觀模式、裝飾模式、代理模式都屬於包裝模式,都是對另外的類或對象的包裝,只是各自的意圖不同。
效果圖:看網上的都是兩個view拼接,默認右側的不顯示,水平移動的時候把右側的view顯示出來。但是看最新版QQ上的效果不是這樣的,但給人的感覺卻很好,所以獻丑來一發比較