用GridView实现异步加载SD卡图片,图片无错位。
初学安卓,遇到了很多问题,在网上得到了很多帮助,谢谢各位好心人。把代码发下来与大家分享,有啥问题欢迎讨论~
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.widget.GridView;
public class MainActivity extends Activity {
private String mRootPath = Environment.getExternalStorageDirectory().getPath()+"/"+"dcim"+"/";
private Intent mIntent;
private ProgressDialog m_ProgressDialog = null;
final int MENU_ONE = Menu.FIRST;
final int MENU_TWO = Menu.FIRST + 1;
public static List<String> lstFilePath = null;
/** 清除LST */
public static void unloadLstFilePath() {
if (lstFilePath != null) {
lstFilePath.clear();
lstFilePath = null;
}
}
private void getValues() {
if (lstFilePath == null) {
Log.v("***InLstFilePath***", "OK");
lstFilePath = new ArrayList<String>();
lstFilePath.clear();
new FileTool().ListFiles(mRootPath, lstFilePath);
String addPath = this.getFilesDir().getPath();
new FileTool().ListFiles(addPath, lstFilePath);
} else {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
;
}
runOnUiThread(returnRes);
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIntent = this.getIntent();
Runnable viewOrders = new Runnable() {
public void run() { getValues(); }
};
Thread thread = new Thread(null, viewOrders, "MagentoBackground");
thread.start();
m_ProgressDialog = ProgressDialog.show( MainActivity.this, "请稍后", "数据读取中...", true);
}
private Runnable returnRes = new Runnable() {
public void run() {
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
int columnWidth = metric.widthPixels/4; // 屏幕宽度(像素)
GridView gridview = (GridView) findViewById(R.id.gv_photolist);
GridViewAdapter iadapter = new GridViewAdapter(MainActivity.this, lstFilePath);
gridview.setAdapter(iadapter);
gridview.setColumnWidth(columnWidth);
m_ProgressDialog.dismiss();
}
};
}
import java.util.List;
import com.yjx.yibu.AsyncImageLoader3.ImageCallback;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
public class GridViewAdapter extends BaseAdapter {
private LayoutInflater layoutInflater;
private List<String> imgUrls;
private AsyncImageLoader3 imageLoader = new AsyncImageLoader3();
public GridViewAdapter(Context context, List<String> imgUrls) {
layoutInflater = LayoutInflater.from(context);
this.imgUrls = imgUrls;
}
@Override
public int getCount() {
return imgUrls.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
String path = imgUrls.get(position);
if(convertView==null) {
viewHolder = new ViewHolder();
convertView = layoutInflater.inflate(R.layout.photolist_item, null);
viewHolder.ivImage = (ImageView)convertView.findViewById(R.id.iv_photoicon_photolist_item);
viewHolder.ivImage.setScaleType(ImageView.ScaleType.CENTER);
convertView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder)convertView.getTag();
}
Bitmap cachedImage = imageLoader.loadBitmap(path,viewHolder.ivImage, new ImageCallback() {
public void imageLoaded(Bitmap imageBitmap,ImageView image,String imageUrl) {
viewHolder.ivImage.setImageBitmap(imageBitmap);
}
});
if(cachedImage!= null) {
viewHolder.ivImage.setImageBitmap(cachedImage);
}
else if(cachedImage == null) {
viewHolder.ivImage.setImageResource(R.drawable.icon);
}
return convertView;
}
class ViewHolder {
/**
* 图片
*/
public ImageView ivImage;
/**
* 图片信息
*/
// public TextView tvInfo;
}
}
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.graphics.Bitmap;
import android.os.Handler;
import android.widget.ImageView;
public class AsyncImageLoader3 {
// 为了加快速度,在内存中开启缓存(主要应用于重复图片较多时,或者同一个图片要多次被访问,比如在ListView时来回滚动)
public Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>();
private ExecutorService executorService = Executors.newFixedThreadPool(5); // 固定五个线程来执行任务
private final Handler handler = new Handler();
/**
*
* @param imageUrl
* 图像url地址
* @param callback
* 回调接口
* @return 返回内存中缓存的图像,第一次加载返回null
*/
public Bitmap loadBitmap(final String imageUrl, final ImageView image,final ImageCallback callback) {
// 如果缓存过就从缓存中取出数据
if (imageCache.containsKey(imageUrl)) {
SoftReference<Bitmap> softReference = imageCache.get(imageUrl);
if (softReference.get() != null) {
return softReference.get();
}
}
// 缓存中没有图像,则从SDcard取出数据,并将取出的数据缓存到内存中
executorService.submit(new Runnable() {
public void run() {
try {
final Bitmap bitmap = loadImageFromSD(imageUrl);
imageCache.put(imageUrl, new SoftReference<Bitmap>(
bitmap));
handler.post(new Runnable() {
public void run() {
callback.imageLoaded(bitmap, image,imageUrl);
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
return null;
}
// 从SDcard取数据方法
protected Bitmap loadImageFromSD(String path) {
try {
// 测试时,模拟网络延时,实际时这行代码不能有
// SystemClock.sleep(2000);
Bitmap bm = new BitmapTool().charge(path);
return bm;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 对外界开放的回调接口
public interface ImageCallback {
// 注意 此方法是用来设置目标对象的图像资源
public void imageLoaded(Bitmap imageDrawable, ImageView image, String imageUrl);
}
}
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
public class BitmapTool {
public BitmapTool() {
}
/** 图片适配大小 */
public Bitmap change(String path) {
Bitmap bm = null;
BitmapFactory.Options optsa = new BitmapFactory.Options();
optsa.inSampleSize = 10;
bm = BitmapFactory.decodeFile(path, optsa);
if(bm != null) {
} else {
return null;
}
/**不同尺寸图片的缩放比例*/
if((bm.getHeight() ) <=150 || (bm.getWidth()) <=100 ) {
optsa.inSampleSize = 1;
bm = BitmapFactory.decodeFile(path, optsa);
}
else if( (bm.getHeight() )<=300 || (bm.getWidth()) <= 200){
optsa.inSampleSize =10;
bm = BitmapFactory.decodeFile(path, optsa);
}
else if( ( (bm.getHeight() )<=450 ) ||( (bm.getWidth()) <= 300)){
optsa.inSampleSize =20;
bm = BitmapFactory.decodeFile(path, optsa);
}
else if( ((bm.getHeight() )<=600 ) ||( (bm.getWidth()) <= 400)){
optsa.inSampleSize =30;
bm = BitmapFactory.decodeFile(path, optsa);
}
else if( ( (bm.getHeight() )<=750 ) ||( (bm.getWidth()) <= 500)) {
optsa.inSampleSize = 40;
bm = BitmapFactory.decodeFile(path, optsa);
}
else if( ((bm.getHeight() )<=900 ) ||( (bm.getWidth()) <= 600)) {
optsa.inSampleSize = 50;
bm = BitmapFactory.decodeFile(path, optsa);
}
else {
optsa.inSampleSize = 60;
bm = BitmapFactory.decodeFile(path, optsa);
}
return bm;
}
/** 图片适配大小 ,同时缩放比例*/
public Bitmap charge(String path) {
Bitmap bm = this.change(path);
int sWidth = bm.getWidth();
int sHeigth = bm.getHeight();
if(bm != null) {
bm = this.zoomImage(bm, sWidth,sHeigth);
}
return bm;
}
/***
* 图片的缩放方法
*
* @param bgimage
* :源图片资源
* @param newWidth
* :缩放后宽度
* @param newHeight
* :缩放后高度
* @return
*/
public Bitmap zoomImage(Bitmap bgimage, int newWidth, int newHeight) {
// 获取这个图片的宽和高
int width = bgimage.getWidth();
int height = bgimage.getHeight();
// 创建操作图片用的matrix对象
Matrix matrix = new Matrix();
// 计算缩放率,新尺寸除原始尺寸
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 缩放图片动作
matrix.postScale(scaleWidth, scaleHeight);
Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, width, height,
matrix, true);
return bitmap;
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import android.os.Environment;
import android.util.Log;
public class FileTool {
/** 图片内存最小值 5K */
private final static int PIC_FILE_SIZE_MIN = 5;
/** 图片内存最大值 300K */
private final static int PIC_FILE_SIZE_MAX = 6000;
/**
* 遍历目录,得到所有图片文件路径集群
* @param path
* @return
*/
public void ListFiles(String path, List<String> lstPaths){
File file = new File(path);
if(file == null)
return;
if(file.isDirectory() ) {
String curpath = Environment.getExternalStorageDirectory().getPath()+"/"+"dcim"+"/"+".thumbnails";
if(path.equals(curpath))
return;
}
File[] fs = file.listFiles();
if(fs==null)
return;
for(File f : fs){
if(f==null)
continue;
String fName = f.getName();
String htx = fName.substring(fName.lastIndexOf(".") + 1,
fName.length()).toLowerCase(); //得到扩展名
if(htx.equals("png") || htx.equals("jpg") ||
htx.equals("gif") || htx.equals("bmp")) {
if(fileSizeValidity(f.getPath())) {
lstPaths.add(f.getPath());
Log.v("***PIC_FILE***", fName);
}
} else {
}
path = f.getAbsolutePath();
if(f.isDirectory() == true) {
ListFiles(path, lstPaths); //当f为文件夹的时候,进入文件夹中
}
}
}
/**
* 判断文件大小有效性
* 如果文件内存在5K-300K之间则有效,否则返回FALSE
* @param path
* @return
*/
private boolean fileSizeValidity(String path) {
File f = new File(path);
if(f.exists()) {
int cur = 0;
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
cur = fis.available()/1000;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//图片内存在5K-300K之间,表示有效
if(cur>=PIC_FILE_SIZE_MIN && cur<=PIC_FILE_SIZE_MAX)
return true;
}
return false;
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fillable_area"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
android:orientation="vertical" >
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gv_photolist"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:numColumns="auto_fit"
android:columnWidth="100dp"
android:stretchMode="columnWidth"
android:gravity="center" >
</GridView>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:paddingBottom="4dip" android:layout_width="fill_parent">
<ImageView android:layout_height="100px"
android:layout_width="150px"
android:layout_centerHorizontal="true"
android:id="@+id/iv_photoicon_photolist_item"/>
</RelativeLayout>