Android之ListView優化(使用Lrucache,圖片滑動時使用預設圖片,停止時載入)
注意:LruCache是有版本限制的,低版本的sdk需要在libs資料夾新增相應的support-4v檔案。
本文改造的大部分是參考http://www.iteye.com/topic/1118828,感謝。
不廢話直接上工程程式碼,內有關鍵註釋,專案就不上傳了,自己對照著上面網址改唄。
首先是Application檔案,負責建立圖片儲存資料夾:
public class MyApp extends Application{ @Override public void onCreate() { super.onCreate(); File f = newFile(Environment.getExternalStorageDirectory()+"/TestSyncListView/pic/"); if (!f.exists()) { f.mkdirs(); } } }
影象讀取工具類:
public
class SyncImageLoaderUtil {
private
Object lock = new
Object();
private
boolean mAllowLoad =
true ;
private
boolean firstLoad = true ;
private
int mStartLoadLimit =
0 ;
private
int mStopLoadLimit =
0 ;
final
Handler handler = new
Handler();
// private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
private
LruCache<String,Bitmap> mMemoryCache; RunInOtherThread runInOutherThread;
public
SyncImageLoaderUtil(Context context) {
super ();
int
memClass = ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
int
cacheSize = 1024
* 1024 *memClass /
8 ;
mMemoryCache =
new LruCache<String, Bitmap>(cacheSize){
@Override
protected
int sizeOf(String key, Bitmap value) {
// TODO Auto-generated method stub
return
value.getRowBytes();
}
};
runInOutherThread =
new RunInOtherThread();
runInOutherThread.start();
}
public
interface OnImageLoadListener {
public
void onImageLoad(Integer t, Drawable drawable);
public
void onError(Integer t);
}
public
void setLoadLimit( int
startLoadLimit, int
stopLoadLimit) {
if
(startLoadLimit > stopLoadLimit) {
// LogUtil.i("test", startLoadLimit+"--錯誤---"+stopLoadLimit);
return ;
}
mStartLoadLimit = startLoadLimit;
mStopLoadLimit = stopLoadLimit;
}
public
void restore() {
mAllowLoad =
true ;
firstLoad =
true ;
}
public
void lock() {
mAllowLoad =
false ;
firstLoad =
false ;
}
public
void unlock() {
mAllowLoad =
true ;
synchronized
(lock) {
lock.notifyAll();
}
}
public
void loadImage(Integer t, String imageUrl,
OnImageLoadListener listener) {
final
OnImageLoadListener mListener = listener;
final
String mImageUrl = imageUrl;
final
Integer mt = t;
runInOutherThread.getHandler().post( new
Runnable() {
@Override
public
void run() {
if
(!mAllowLoad) {
synchronized
(lock) {
try
{
lock.wait();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if
(mAllowLoad && firstLoad) {
loadImage(mImageUrl, mt, mListener);
}
// LogUtil.e("test", "原始開始:"+mStartLoadLimit+"原始當前位置:"+mt+"原始結束:"+mStopLoadLimit);
if
(mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit) {
// LogUtil.e("test", "開始:"+mStartLoadLimit+"當前位置:"+mt+"結束:"+mStopLoadLimit);
loadImage(mImageUrl, mt, mListener);
}
}
});
}
private
void loadImage( final
String mImageUrl, final
Integer mt,
final
OnImageLoadListener mListener) {
if
(mImageUrl!= null
&& mMemoryCache.get(mImageUrl)!= null ) {
// SoftReference<Drawable> softReference = imageCache.get(mImageUrl);
final
Drawable d = new
BitmapDrawable(mMemoryCache.get(mImageUrl));
// LogUtil.d("ppp", "drawable:"+d);
if
(d != null ) {
handler.post( new
Runnable() {
@Override
public
void run() {
if
(mAllowLoad) {
mListener.onImageLoad(mt, d);
}
}
});
return ;
}
}
try
{
final
Drawable d = loadImageFromUrl(mImageUrl);
if
(d != null ) {
mMemoryCache.put(mImageUrl, ((BitmapDrawable)d).getBitmap());
}
handler.post( new
Runnable() {
@Override
public
void run() {
if
(mAllowLoad) {
mListener.onImageLoad(mt, d);
}
}
});
}
catch (IOException e) {
handler.post( new
Runnable() {
@Override
public
void run() {
mListener.onError(mt);
}
});
e.printStackTrace();
}
}
public
static Drawable loadImageFromUrl(String url)
throws IOException {
//DebugUtil.debug(url);
if
(Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
File f =
new File(Environment.getExternalStorageDirectory()
+
"/Weiyu/pic/" + MD5Util.getMD5(url.getBytes()));
if
(f.exists()) {
FileInputStream fis =
new FileInputStream(f);
Drawable d = Drawable.createFromStream(fis,
"src" );
return
d;
}
URL m =
new URL(url);
InputStream i = (InputStream) m.getContent();
DataInputStream in =
new DataInputStream(i);
FileOutputStream out =
new FileOutputStream(f);
byte [] buffer =
new byte [ 1024 ];
int
byteread = 0 ;
while
((byteread = in.read(buffer)) != - 1 ) {
out.write(buffer,
0 , byteread);
}
in.close();
out.close();
return
loadImageFromUrl(url);
}
else {
URL m =
new URL(url);
InputStream i = (InputStream) m.getContent();
Drawable d = Drawable.createFromStream(i,
"src" );
return
d;
}
}
}
|
執行緒輔助類:
public
class RunInOtherThread {
private
static final
String LOG_TAG = "RunInOtherThread" ;
private
LooperThread localThread = new
LooperThread();
private
boolean isRunning =
true ;
public
Handler getHandler(){
return
localThread.getHandler();
}
private
class LooperThread
extends Thread {
private
Handler mHandler;
public
void run() {
Looper.prepare();
mHandler =
new Handler() {
public
void handleMessage(Message msg) {
onReceiveMessage(msg.what);
}
};
Looper.loop();
}
Handler getHandler(){
return
mHandler;
}
}
public
void start(){
localThread.start();
}
public
void quit(){
localThread.getHandler().getLooper().quit();
}
public
void sendMessage( int
what){
getHandler().sendEmptyMessage(what);
}
public
Thread getThread(){
return
localThread;
}
public
void onReceiveMessage( int
what){};
}
|
使用類:
// 例項化工具類
SyncImageLoaderUtil syncImageLoader =
new SyncImageLoaderUtil(mContext);
syncImageLoader.loadImage(position, model.mPic, imageLoadListener); //應用介面:引數一是載入圖片的位置;引數二是載入的ImageView;引數三是回撥介面
// map儲存的鍵是位置,值是listview對應位置的佈局
HashMap map =
new HashMap();
map.put(position, convertView);
SyncImageLoaderUtil.OnImageLoadListener imageLoadListener =
new SyncImageLoaderUtil.OnImageLoadListener() {
@Override
public
void onImageLoad(Integer t, Drawable drawable) {
View view = (View) map.get(t);
if
(view != null ) {
ImageView iv = (ImageView) view.findViewById(R.id.image);
iv.setBackgroundDrawable(drawable);
}
}
@Override
public
void onError(Integer t) {
// 圖片載入失敗
// 取得listview對應的位置的行的內容佈局
MusicModel model = (MusicModel) getItem(t);
View view = mListView.findViewWithTag(model);
if
(view != null ) {
ImageView iv = (ImageView) view.findViewById(R.id.image);
iv.setBackgroundResource(R.drawable.img_pic);
}
}
};
// 實現類而且需要實現OnScrollListener介面
public
void loadImage() {
// 不要在這裡使用listview的getFirstVisiblePosition方法,位置不準
if
(end >= getCount()) {
end = getCount() -
1 ;
}
syncImageLoader.setLoadLimit(start, end);
syncImageLoader.unlock();
}
@Override
public
void onScrollStateChanged(AbsListView view,
int scrollState) {
// TODO Auto-generated method stub
if
(lodingView) {
switch
(scrollState) {
case
AbsListView.OnScrollListener.SCROLL_STATE_FLING:
syncImageLoader.lock();
break ;
case
AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
loadImage();
break ;
case
AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
syncImageLoader.lock();
break ;
default :
break ;
}
}
}
@Override
public
void onScroll(AbsListView view,
int firstVisibleItem,
int
visibleItemCount, int
totalItemCount) {
// 在這裡取得的位置較準確,不過也會出現特殊的奇疤機型是不行的
// start與end是定義的變數
start = firstVisibleItem;
end = firstVisibleItem + visibleItemCount;
if
(firstVisibleItem != 0 ) {
// lodingView是控制變數,用來控制第一次進來檢視載入讀取圖片
lodingView =
true ;
}
else {
lodingView =
false ;
loadImage();
}
}
|
相關推薦
Android之ListView優化(使用Lrucache,圖片滑動時使用預設圖片,停止時載入)
注意:LruCache是有版本限制的,低版本的sdk需要在libs資料夾新增相應的support-4v檔案。 本文改造的大部分是參考http://www.iteye.com/topic/1118828,感謝。 不廢話直接上工程程式碼,內有關鍵註釋,專案就不上傳了,自己對照著
Android開發之listview優化+圖片非同步載入+避免圖片顯示閃爍(修改版)
小鹿路過此地。。心熱之下寫寫Android開發中的listview運用(閒的沒事幹,改動了一點程式碼,但實現功能不變) 小鹿學Android開發已有兩年多了,總算有一點點小收穫,雖算不上大牛大神級人物,但有些東西可以和一家一起分享一起交流一起學習一起進步...。還有,望檢視
Android Studio ListView的item點選事件彈出AlertDialog,和item的滑動
首先看看效果圖: 點選彈出AlertDialog的確認框! (一)第一步,建立一個xml檔案顯示item的佈局 student_item.xml <?xml version="1.0" encoding="utf-8"?> <LinearLa
Android開發之ListView 優化之快取優化
通過平時對ListView的使用,目前我把ListView的優化分為以下幾個方面: 快取優化、資料優化、其他方面優化 0.未優化簡單程式碼 <span style="font-size:14
Android優化系列之ListView優化老生常談
本文內容:adapter,listview的優化,RecycleBi,google大會推薦優化, 實現ListView的過程,Adapter起到了至關重要的作用,不僅僅因為getview()方法。那麼,先從Adapter說起~ Adapter: 它在ListView
Android之ListView的getItemViewType和getViewTypeCount
ldr get 思路 pre 簡單 erl 他會 add item PS:感覺這兩個方法其實還是很容易理解的,也算是給我其他兩個朋友寫的吧,幫他們搞清楚這兩個方法的用法和概念。同時還有一些小細節問題需要註意。 學習內容: 1.getItemViewType和get
Android之WebView優化之路
前言 隨著app的迭代,嵌入的html5介面越來越多了,Webview這個強大元件引起的問題越發的多起來,例如: 1、WebView導致的oom問題 2、Android版本不同,採用了不同的核心,相容性crash 3、不同版本實現不同,甚至URI不規範也會引起不同程度的問題
Android之ListView的item獲取不到焦點
前兩天我在寫一個ListView,其中自定義的item中的控制元件有ImageView、TextView、Button,反正是比較複雜,寫完一整套流程後,真機一執行,詭異的事情出現了,點選item居然無響應。這怎麼回事呢?找了又找,程式碼看了一遍又一遍,沒問題
Android 之 效能優化
眾所周知,android裝置作為一種移動裝置,不管是cpu還是記憶體都無法跟pc裝置相提並論。這就意味著我們不能無限制地使用記憶體和cpu的資源,過多地使用記憶體會導致oom,過多地使用cpu資源,做大量的耗時任務,會導致手機變得異常卡頓,甚至無法響應出現ANR。所以我們在平常做開發時,一定要注意效
Android之效能優化問題
1、UI優化 在xml佈局檔案中,合理選擇RelativeLayout、LinearLayout、FrameLayout,其中RelativeLayout會讓子View呼叫兩次onMeasure()方法,並且佈局複雜時,onMeasure也相對複雜,效率比較低;在LinearLayout中
Android之ListView分頁獲取網路資料(伺服器端)(一)
資料庫分頁: mysql:select pname from product limit 0,2;第一個引數是指要開始的地方,第二個引數是指每頁顯示多少條資料;注意:第一頁用0表示。 oracle:rownumber SqlServer:top 一、伺服器端 ①新建包com
Android之listview新增資料篇
一、ListView: 1、 ListView通常有兩個職責: 1、向佈局填充資料 2、處理選擇點選等操作 2、ListView的建立需要3個元素:
android之listview分頁載入上拉重新整理、更新listview
==========系統方法實現上啦重新整理=========public class GreatToolsActivity extends Activity { private TextView tv; private ListView listtest;
原來操控介面可以這麼簡單----安卓上下滑動縮放頂部圖片,左右滑動結束當前Activity,及View柔和回彈效果
先上效果圖: 上傳圖片不能超過2M,費了好大勁。每一張gif動的有點快,將就看。 首先說原理: 為activity的xml檔案根佈局新增setOnTouchListener。上下滑動和左右滑動的所有操作都是在OnTouchListener的onTouch方法中實現的,通過
android之ViewPager簡單實現區域性頁面滑動效果
-Viewpager能實現什麼效果? -實現左右滑動,切換view的效果。 -既可以實現整個頁面左右滑動,也可以實現同一個頁面中區域性左右滑動。 搞清楚viewpager的作用後,開始寫一個簡單例子,實現同一個頁面中區域性滑動的效果。 在coding前要做的準備工作 2
android之listView快取機制
package com.example.day_05_06; import java.util.ArrayList; import java.util.List; import com.litsoft.General.General; import android.support.v7.app.ActionB
android之用scrollview實現控制元件滑動固定效果
專案中最近用到需要佈局滑動到某一個地方的時候某個控制元件固定在螢幕頂部不動,就去研究了下,思路其實挺簡單的。我置頂的懸浮控制元件上邊還需要留個控制元件,比如搜尋框之類的,專案需求不一樣就留的不一樣,所以就研究了一下,網上也有很多,其實方法思路都一樣的,很簡單,自定義一下Sc
[Android 之美] 那些你不知道的APK 瘦身,讓你的APK更小
[Android 之美] APK 瘦身,減少APK的大小 讓我們的apk檔案儘可能更小,移除那些未使用的程式碼和資原始檔。本章節介紹瞭如何做到讓APK更小,效能更好,下載轉化率會更高,以及如何指定在構建APK過程中保留或移除專案中的程式碼和資源,在我們還
Android之ListView包含RadioButton的單選問題解決辦法
1.最簡潔的解決辦法。 adapter裡儲存當前選中的位置變數,getView方法裡,禁用radiobutton的點選事件,只通過listview的onItemClick事件設定選中位置變數,並且通過notifyDataSetChanged重新整理列表。getView方法裡
一起學Android之ListView
foo 每一個 .get 知識點 mar inf 布局 textview item 本文以一個小例子,簡述Android開發中ListView的相關應用,僅供學習分享使用。 概述 ListView是一個顯示可滾動項目列表的視圖組(view group),列表項通過適配器(A