1. 程式人生 > >banner輪播圖快取實現(記憶體+硬碟+網路)

banner輪播圖快取實現(記憶體+硬碟+網路)

距離最後一次部落格已經有1年將近一年半多時間了,目前在android應用開發中匍匐前進著,記得當時很喜歡遊戲開發,只是理想是豐滿的,現實卻是殘酷的。好了,扯淡有點過了~~
現在介紹的是banner輪播圖快取的實現,大部分程式碼都是來自:(http://blog.csdn.net/singwhatiwanna/article/details/17588159),在此再次謝謝任老師的開原始碼。裡面用了圖片的三級cache策略(記憶體、檔案、網路),其實個人覺得如果用上郭神部落格中的DiskLruCache硬碟快取效果可能會更好,具體連結請看:(http://blog.csdn.net/guolin_blog/article/details/34093441)。
以下是ShowTime時間:

~~、、
首先,如果是在工作中,那麼基本上技術總監給你的評估時間會比較少,而且,重複造輪子覺得沒多大必要,最多就是有時間的時候對著程式碼擼一遍,熟悉一下程式碼。對於我來言,我只想知道里面用了哪些技術點,程式碼的實現邏輯就行了,其他的程式碼相對來說並不太重要(當然,如果是看原始碼的話就儘量多理解了,不要一下子跳過看)。
任老師已經把大量的程式碼寫出來了,我們的主要目的就是把程式碼稍微理通順,把分離的程式碼集合起來,讓程式碼能夠正常跑起來,然後再去實現我們最終要實現的效果。其中,cache快取的工具類我基本上沒有做大的修改,
cache快取工具類,基本上都是任老師的程式碼:

**備註:專案執行效果,其中由於我去掉了訪問後臺資料,所以只出現載入中的預設圖片,實際上要根據後臺呼叫介面來進行處理**
備註:上圖為專案執行效果,其中由於我去掉了訪問後臺資料,所以只出現載入中的預設圖片,實際上要根據後臺呼叫介面來進行處理

一、修改的類:1、ImageFileCache(裡面我寫了SD卡處理的工具類,後面我會放出所有相關聯的程式碼)
public ImageFileCache()
{
IMGCACHDIR = SdCardUtil.getDirString();
//清理部分檔案快取
removeCache(IMGCACHDIR);
}
2、ScrollBanner類,主要類
(1)實現思路:
快取方面:入口程式碼:public ScrollBanner(Context context, final int width, final int height,
OnBannerClickListener bannerClickListener) {…
這段程式碼開始 ScrollBanner類的執行,其中,我在裡面用到了:
SharedPreferences sp = context.getSharedPreferences(“isFirstGet”,
Context.MODE_PRIVATE);
isFirst = sp.getBoolean(“isFirst”, true);
主要作用是在沒有網路的情況下,“判斷是否第一次獲取banner(預設為true) ”,如果是第一次且沒有網路時顯示預設banner圖,否則就從資料庫中讀取資料;在有網路的情況下,我會呼叫以下兩個方法:getDataFromDB();
fetchBannerInfo();
從字面意思上面可以看出 執行了從資料庫獲取資料和向後臺獲取資料的操作,那樣的話即使網路不給力,也能從資料庫中讀取到資料,正常情況下從資料庫中獲取資料耗時更少,獲取資料更快。
在getDataFromDB()方法裡面,我呼叫了onBannerInfoSuccess(mBannerItemsList)方法,目的是通過Handler把訊息傳送到訊息佇列,然後在Handler的回撥方法handleMessage(Message msg)中執行讀取圖片的操作,讀取圖片操作的主要方法入口是fetchBannerImages(); —-> imageManager.loadBitmap(item.getImgUrl(), mBitmapHandler);
有網路的情況下邏輯一樣的,只是有網路並且有資料的情況下會把資料儲存在資料庫,詳情請看提供的原始碼~~
新增View邏輯方面:入口程式碼

在入口public ScrollBanner(Context context, final int width, final int height,
OnBannerClickListener bannerClickListener) {…
中,有一個設定了預設載入圖片的方法:setDefaultBannerImages(),banner輪播中任老師的實現邏輯是:通過動態新增View和刪除View來展示輪播圖片出來,在方法initScrollView()(從字面意思上看是初始化ScrollView)中,

// 初始化三個滑動view
for (int i = 0; i < PAGE_COUNT; i++) {
LinearLayout linearLayoutScreen = new LinearLayout(mContext);
linearLayoutScreen.setOrientation(LinearLayout.VERTICAL);
linearLayoutScrolLayout.addView(linearLayoutScreen,
new LayoutParams(mScreenWidth, LayoutParams.FILL_PARENT));
mLinearLayoutScreens.add(i, linearLayoutScreen);

linearLayoutScrolLayout全域性變數的作用就是新增LinearLayout ,實際上就是新增Bitmap,即為要顯示出來的輪播圖片,在該方面裡面,也初始化小圓點檢視,用了一個RelativeLayout來新增各個小圓點,然後通過addView方法把RelativeLayout物件新增進去,最後執行輪播時間:
// 自動滑屏 5秒一次
timer.schedule(mTimerTask, 5000, TIMER_DURATION);
加一個banner和刪除一個banner的邏輯程式碼的方法分別如下:addBannerItem() ,deleteBannerItem() 這兩個方法看上去原理都差不多。
滑動邏輯:入口程式碼 在入口initScrollView()方法裡面,通過 mHorizontalScrollViewEx = new HorizontalScrollViewEx(mContext, null,mBannerClickListener); new出來一個繼承了ViewGroup的物件mHorizontalScrollViewEx,然後在mHorizontalScrollViewEx該類中實現了OnGestureListener手勢監聽介面,通過onFling(…)方法來滑動輪播圖片,裡面呼叫了switchView(mWhichScreen);方法。
點選輪播圖片進入不同介面邏輯:入口程式碼 private class HorizontalScrollViewEx extends ViewGroup implements
OnGestureListener {…
在該類中聲明瞭一個方法,點選輪播圖片後跳轉的邏輯程式碼寫在了這個方法裡面,其中,涉及到一個BannerItem實體類bean,裡面的內容可以自己根據伺服器返回的欄位來更改,該方法裡面用到了一個回撥介面private OnBannerClickListener mBannerClickListener;
,主要程式碼是

if (bannerItem != null) {
BannerMotionEvent bannerMotionEvent = new BannerMotionEvent(
mWhichScreen, bannerItem.getPicLink(),
bannerItem.getTitle());
mBannerClickListener.onBannerClick(bannerMotionEvent);
}

避免出現OOM的圖片的簡單邏輯程式碼:

public static Bitmap decodeSampledBitmapFromResource(Resources res,
int resId, int reqWidth, int reqHeight) {
// 第一次解析將inJustDecodeBounds設定為true,來獲取圖片大小
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// 呼叫上面定義的方法計算inSampleSize值
options.inSampleSize = 2;
// options.inSampleSize = calculateInSampleSize(options, reqWidth,
// reqHeight);
// 使用獲取到的inSampleSize值再次解析圖片
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
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的值,這樣可以保證最終圖片的寬和高
// 一定都會大於等於目標的寬和高。
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}

主程式中的呼叫程式碼:

      bannerView = new ScrollBanner(getActivity(), screenWidth, -1,
          new OnBannerClickListener() {
              @Override
              public void onBannerClick(
                      BannerMotionEvent bannerMotionEvent) {

                  final String picLink = bannerMotionEvent.getPicLink().trim().toString();
                  Intent intent = new Intent(getActivity(),
                          BannerActivity.class);
                  intent.putExtra("picLink", picLink);
                  intent.putExtra("title", bannerMotionEvent.getTitle());

                  if (!Te`這裡寫程式碼片`xtUtils.isEmpty(picLink) && !picLink.equals("#")) {
                      getActivity().startActivity(intent);
                  }
              }
          });

好了,上面就是一些簡單的分析,總體來說借用了任老師的程式碼,在此再次表示感謝,另外謝謝開源的codersss。.