我在我的应用程序中使用了Lazy Loading List,我只需要加载ListView的可见元素。我已经在互联网上搜索,尝试了很多东西,但仍然无法让事情发挥作用。你可以给我建议怎么做?
这是ImageLoader类:
package com.stampii.stampii.tableview;
import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Stack;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import com.stampii.stampii.R;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.widget.ImageView;
public class ImageLoader {
//the simplest in-memory cache implementation. This should be replaced with something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>();
private File cacheDir;
private AssetManager mAssetManager;
public ImageLoader(Context context){
//Make the background thead low priority. This way it will not affect the UI performance
photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
mAssetManager = context.getAssets();
//Find the dir to save cached images
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"Stampii");
else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
}
final int stub_id=R.drawable.default_img;
public void DisplayImage(String url, Activity activity, ImageView imageView)
{
if(cache.containsKey(url))
imageView.setImageBitmap(cache.get(url));
else
{
queuePhoto(url, activity, imageView);
imageView.setImageResource(stub_id);
}
}
private void queuePhoto(String url, Activity activity, ImageView imageView) //opashka
{
//This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them.
photosQueue.Clean(imageView);
PhotoToLoad p=new PhotoToLoad(url, imageView);
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.push(p);
photosQueue.photosToLoad.notifyAll();
}
//start thread if it's not started yet
if(photoLoaderThread.getState()==Thread.State.NEW)
photoLoaderThread.start();
}
private Bitmap getBitmap(String src) {
Bitmap myBitmap = null;
//Decryption
try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec("01234567890abcde".getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec("fedcba9876543210".getBytes());
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
InputStream input = mAssetManager.open(src);
CipherInputStream cis = new CipherInputStream(input, cipher);
myBitmap = BitmapFactory.decodeStream(cis);
}
catch(Exception e){
e.printStackTrace();
Log.v("ERROR","Error : "+e);
}
return myBitmap;
}
//Task for the queue
private class PhotoToLoad
{
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i){
url=u;
imageView=i;
}
}
PhotosQueue photosQueue=new PhotosQueue();
public void stopThread()
{
photoLoaderThread.interrupt();
}
//stores list of photos to download
class PhotosQueue
{
private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();
//removes all instances of this ImageView
public void Clean(ImageView image)
{
for(int j=0 ;j<photosToLoad.size();){
if(photosToLoad.get(j).imageView==image)
photosToLoad.remove(j);
else
++j;
}
}
}
class PhotosLoader extends Thread {
public void run() {
try {
while(true)
{
//thread waits until there are any images to load in the queue
if(photosQueue.photosToLoad.size()==0)
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.wait();
}
if(photosQueue.photosToLoad.size()!=0)
{
PhotoToLoad photoToLoad;
synchronized(photosQueue.photosToLoad){
photoToLoad=photosQueue.photosToLoad.pop();
}
Bitmap bmp=getBitmap(photoToLoad.url);
cache.put(photoToLoad.url, bmp);
Object tag=photoToLoad.imageView.getTag();
if(tag!=null && ((String)tag).equals(photoToLoad.url)){
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
if(Thread.interrupted())
break;
}
} catch (InterruptedException e) {
//allow thread to exit
}
}
}
PhotosLoader photoLoaderThread=new PhotosLoader();
//Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
ImageView imageView;
public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
public void run()
{
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
imageView.setImageResource(stub_id);
}
}
public void clearCache() {
//clear memory cache
long size=0;
cache.clear();
//clear SD cache
File[] files=cacheDir.listFiles();
for(File f:files){
size=size+f.length();
f.delete();
}
}
}
EDIT1:
我的LazyAdapter类中的getView方法:
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
ViewHolder holder;
if(convertView==null){
vi = inflater.inflate(R.layout.item, null);
holder=new ViewHolder();
holder.name=(TextView)vi.findViewById(R.id.name);
holder.info=(TextView)vi.findViewById(R.id.info);
holder.image=(ImageView)vi.findViewById(R.id.image);
vi.setTag(holder);
}
else
holder=(ViewHolder)vi.getTag();
holder.name.setText("MotoGP Rider");
holder.info.setText("Category");
holder.image.setTag(data[position]);
imageLoader.DisplayImage(data[position], activity, holder.image);
return vi;
}
有什么想法吗?
答案 0 :(得分:3)
检查代码后:我确信只会加载可见的图像!
但是因为一些图像下来有相同的网址!您会认为它们以不同的顺序加载。然而,它们是基于可见的图像加载的,但具有相同URL的任何其他listitem将显示图像。
为ListView 上可见的每个位置调用我在我的应用程序中使用了Lazy Loading List,我只需要加载ListView的可见元素。
getView
您需要加载的图片必须从适配器的getView
所以你应该覆盖
public View getView (int position, View convertView, ViewGroup parent){
super(position,convertView,parent);
//now add the picture at position to the queue
}
注意:小心
假设您已将照片1添加到队列中:并不意味着 {1}将不会再次调用位置1。
换句话说,考虑到使用getView
可以多次调用某个职位这一事实。
答案 1 :(得分:0)
要仅加载您需要的可见元素,以实现AbsListView.OnScrollListener的接口。通过此界面,您可以找到&#34;滚动事件&#34;和&#34; scrolleventstate&#34;改变其方法。
ListView list = (ListView) findViewById(R.id.listview);
MyAdapter adapter = new MyAdapter(context, items);
list.setAdapter(adapter);
list.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view,
int scrollState) {
// Do nothing
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// threshold being indicator if bottom of list is hit
if (firstVisibleItem = threshold) {
pullMoreData();
}
}
});
有关此内容的更多解释。你可以按照这个教程。 smart loading listview,dynamic data listview,detect end scroll,get visible data index