在Android开发App中经常会用到ListView和Gridview的item中加载图片显示的情况。但是如果图片多了就会遇到内存溢出的情况,及时你对图片做了缩放处理但是图片张数多了还是一样的会内存溢出。所以这个时候就需要我们动态的释放和加载图片资源。附件中是小弟根据自己的想法实现的动态加载和释放图片,但是有个图片不能动态刷新的问题未能解决。欢迎各位相继完善、探讨和吐糟。若各位有新的想法或实现请发小弟邮箱(592421989@qq.com)一份,小弟学习一下。各位下载项目后在手机SD卡DCIM/Camera/文件夹下可以放300-500张高清图片,就可以测试了。
以下是小弟实现的代码块:
MainActivity.java
package com.example.bitmaprecycledemo;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends Activity implements OnScrollListener {
private GridView mGridView;
private List<ImageBean> imageList;
private Bitmap defaultBitmap;
private final int UPDATE_IMAGE = 0;
private int firstVisibleItem;
private int visibleItemCount;
private int totalItemCount;
private int lastVisibleItem;
private boolean isScrollDone;
private boolean isFirstShow = true;
private MyAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGridView = (GridView) findViewById(R.id.mGridView);
mGridView.setOnScrollListener(this);
getImageList();
myAdapter = new MyAdapter();
mGridView.setAdapter(myAdapter);
loadImage();
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.firstVisibleItem = firstVisibleItem;
this.visibleItemCount = visibleItemCount;
this.totalItemCount = totalItemCount;
lastVisibleItem = firstVisibleItem + visibleItemCount;
System.out.println(String.format("onScroll--------firstVisibleItem=%d && visibleItemCount=%d && totalItemCount=%d",firstVisibleItem, visibleItemCount,totalItemCount));
isScrollDone = false;
if(isFirstShow && imageList!= null && imageList.size() > 0 && totalItemCount > 0){
isFirstShow = false;
loadImage();
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
System.out.println("onScrollStateChanged--------");
isScrollDone = true;
mHandler.sendEmptyMessageDelayed(UPDATE_IMAGE, 2000);
}
private void getImageList(){
String ROOT_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"DCIM/Camera/";
System.out.println(ROOT_PATH);
File file = new File(ROOT_PATH);
File[] files = file.listFiles();
System.out.println(files.length);
imageList = new ArrayList<ImageBean>();
defaultBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image_prompt);
for (File tempFile : files) {
ImageBean mImageBean = new ImageBean();
mImageBean.imagePath = tempFile.getPath();
mImageBean.imageName = tempFile.getName();
mImageBean.imageBitmap = defaultBitmap;
imageList.add(mImageBean);
}
}
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
// TODO Auto-generated method stub
return imageList.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return imageList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
System.out.println("getView--->"+position);
convertView = View.inflate(MainActivity.this, R.layout.image_item, null);
ImageView iv = (ImageView) convertView.findViewById(R.id.iv);
iv.setBackgroundDrawable(new BitmapDrawable(imageList.get(position).imageBitmap));
imageList.get(position).iv = iv;
TextView tv = (TextView) convertView.findViewById(R.id.tv);
tv.setText(imageList.get(position).imageName);
return convertView;
}
}
/**
* 读取图片文件到bitmap中
* @param filePath
* @param size 规定文件大小(KB)
* @return
*/
public Bitmap getBitmapForPath(String filePath,int size){
File f = new File(filePath);
if(!f.exists()){
return null;
}
BitmapFactory.Options options = new BitmapFactory.Options();
InputStream is = null;
try {
is = new FileInputStream(f);
int fileSize = is.available();
System.out.println(f.getName()+"-->"+fileSize/1000+"KB");
//如果文件大于15K就缩放
if(fileSize/1000 > size)
{
int sampleSize = fileSize/(size*1000);
options.inSampleSize=sampleSize;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return BitmapFactory.decodeStream(is,null,options);
}
Handler mHandler = new Handler(){
@SuppressLint("HandlerLeak")
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UPDATE_IMAGE:
System.out.println("mHandler...");
if(isScrollDone){
releseImage();
loadImage();
}
break;
default:
break;
}
};
};
private void releseImage(){
System.out.println("releseImage...");
for(int i = firstVisibleItem - mGridView.getNumColumns();i>=0;i--){
ImageBean bean = imageList.get(i);
if(bean.imageBitmap != null && bean.imageBitmap != defaultBitmap){
Bitmap tempBitmap = bean.imageBitmap;
bean.imageBitmap = defaultBitmap;
tempBitmap.recycle();
tempBitmap = null;
}
}
System.gc();
for(int i = lastVisibleItem + mGridView.getNumColumns();i<totalItemCount;i++){
ImageBean bean = imageList.get(i);
if(bean.imageBitmap != null && bean.imageBitmap != defaultBitmap){
Bitmap tempBitmap = bean.imageBitmap;
bean.imageBitmap = defaultBitmap;
tempBitmap.recycle();
tempBitmap = null;
}
}
System.gc();
}
private void loadImage(){
System.out.println("loadImage...");
for(int i = firstVisibleItem;i<lastVisibleItem;i++){
ImageBean bean = imageList.get(i);
if(bean.imageBitmap != null){
bean.imageBitmap = getBitmapForPath(bean.imagePath, 130);
bean.iv.setBackgroundDrawable(new BitmapDrawable(getResources(), bean.imageBitmap));
}
if(myAdapter != null){
System.out.println("myAdapter.notifyDataSetChanged()...");
myAdapter.notifyDataSetChanged();
}
}
}
@Override
protected void onDestroy() {
for(int i = 0;i<imageList.size();i++){
ImageBean bean = imageList.get(i);
if(bean.imageBitmap != null){
bean.imageBitmap.recycle();
bean.imageBitmap = null;
}
}
if(defaultBitmap != null){
defaultBitmap.recycle();
defaultBitmap = null;
}
super.onDestroy();
}
}
ImageBean.java
package com.example.bitmaprecycledemo;
import android.graphics.Bitmap;
import android.widget.ImageView;
public class ImageBean {
public String imagePath;
public Bitmap imageBitmap;
public String imageName;
public ImageView iv;
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<GridView
android:id="@+id/mGridView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:numColumns="4"
android:verticalSpacing="5dip"/>
</RelativeLayout>
image_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="100dip"/>
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:lines="2"/>
</LinearLayout>
附件下载地址:点击打开链接