异步读取图片到GridView
android设备要求UI线程不能占用太多资源, 而控件资源只能在主线程操作.因此为了得到更好的用户体验, 在加载和处理大量图片是必须采用多线程技术.
又android的每个应用只能分配到大约16M内存. 因此GridView采用了循环回收的机制, 只有当前屏幕的ImageView中的内容被保存在内存中....
各种限制使得GridView的多线程操作并不简单.
这次网上接单要求GridView如德芙般顺滑....苦逼多日....
终于, 参照android 官方系列教程: http://developer.android.com/training/displaying-bitmaps/display-bitmap.html
实现了多线程GridView的操作:
package com.example.ftp_09;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore.Images.Media;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
public class MainActivity extends Activity {
private GridView gridView;
private ArrayList<HashMap<String, String>> list;
private ContentResolver cr;
private ImageView imageview;
private ArrayList<String> imageSrcs = new ArrayList<String>();
//private ImageLoader mImageLoader;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findView();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private void findView(){
gridView = (GridView) findViewById(R.id.gridView1);
list = new ArrayList<HashMap<String, String>>();
cr = getContentResolver();
String[] projection = { Media.DATA,Media._ID,Media.TITLE,Media.DISPLAY_NAME ,Media.MIME_TYPE };
Cursor cursor = cr.query(Media.EXTERNAL_CONTENT_URI, projection,
null, null, null);
getColumnData(cursor);
String[] from = { "path","path"};
int[] to = { R.id.imageView1 ,R.id.textView1};
gridView.setAdapter(new GridAdapter(this));
//gridView.setAdapter(adapter);
gridView.setOnItemClickListener(listener);
}
private void getColumnData(Cursor cur) {
if (cur.moveToFirst()) {
String image_path;
String image_type;
int dataColumn = cur.getColumnIndex(Media.DATA);
int int_type=cur.getColumnIndexOrThrow(Media.MIME_TYPE);
do {
image_path = cur.getString(dataColumn);
image_type=cur.getString(int_type);
HashMap hash = new HashMap();
if(image_type.equals("image/jpeg")){
hash.put("path", image_path);
hash.put("checked", "no");
list.add(hash);
}
} while (cur.moveToNext());
}
}
OnItemClickListener listener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(MainActivity.this, "you chose id: "+id+"\n position: "+position,
Toast.LENGTH_SHORT).show();
TextView txt_show=(TextView)view.findViewById(R.id.textView1);
String image_src = list.get(position).get("path");
txt_show.setText(image_src);
}
};
class GridAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater inflater;
public GridAdapter(Context c){
mContext=c;
inflater=LayoutInflater.from(mContext);
}
public int getCount(){
return list.size();
}
public Object getItem(int position){
return null;
}
public long getItemId(int position){
return 0;
}
public View getView(int position, View convertView, ViewGroup parent){
//ImageView imageView1;
ViewHolder holder=null;
if(holder==null){
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.grid_item, null);
holder.image1 = (ImageView)convertView.findViewById(R.id.imageView1);
holder.image2 = (ImageView)convertView.findViewById(R.id.imageView2);
holder.txt1=(TextView)convertView.findViewById(R.id.textView1);
convertView.setTag(holder);
}
loadBitmap(list.get(position).get("path"), holder.image1);
holder.txt1.setText(list.get(position).get("path"));
if(list.get(position).get("checked").equals("no")){
holder.image2.setVisibility(View.GONE);
}else{
holder.image2.setVisibility(View.VISIBLE);
}
return convertView;
}
public class ViewHolder{
public ImageView image1; //main view
public ImageView image2; //check view
public TextView txt1; //picture info
}
}
/*
*
* Load PICs to GridView from Files on the SD Card.
*
*
*
*
*/
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap decodeBitmapFromFile(String Uri,int reqWidth, int reqHeight){
final BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
//获得图片大小信息
BitmapFactory.decodeFile(Uri, options);
//计算 inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return Bitmap.createScaledBitmap(BitmapFactory.decodeFile(Uri, options), 200, 200, true);
//return BitmapFactory.decodeFile(Uri);
}
public void loadBitmap(String pic_uri, ImageView imageView) {
if (cancelPotentialWork(pic_uri, imageView)) {
final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
final AsyncDrawable asyncDrawable =
new AsyncDrawable(getResources(), BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher), task);
imageView.setImageDrawable(asyncDrawable);
task.execute(pic_uri);
}
}
public static boolean cancelPotentialWork(String data, ImageView imageView) {
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
// final int bitmapData = bitmapWorkerTask.data;
final String bitmapUri=bitmapWorkerTask.uri;
// If bitmapData is not yet set or it differs from the new data
if (bitmapUri.equals("")|| (!bitmapUri.equals(data))) {
// Cancel previous task
bitmapWorkerTask.cancel(true);
} else {
// The same work is already in progress
return false;
}
}
// No task associated with the ImageView, or an existing task was cancelled
return true;
}
private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getBitmapWorkerTask();
}
}
return null;
}
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private String uri="";
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(String... uris) {
//data = params;
uri=uris;
//change to decode from files.
//return decodeSampledBitmapFromResource(getResources(), data, 100, 100);
return decodeBitmapFromFile(uri, 200, 200);
}
// Once complete, see if ImageView is still around and set bitmap.
@Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
final BitmapWorkerTask bitmapWorkerTask =
getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask && imageView != null) {
//放置图片到Item
imageView.setImageBitmap(bitmap);
}
}
}
}
static class AsyncDrawable extends BitmapDrawable{
private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
public AsyncDrawable(Resources res, Bitmap bitmap,
BitmapWorkerTask bitmapWorkerTask) {
super(res, bitmap);
bitmapWorkerTaskReference =
new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
}
public BitmapWorkerTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
}
<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/gridView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:numColumns="3" >
</GridView>
</RelativeLayout>
<?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" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="200px"
android:layout_height="200px"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
<ImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|left"
android:src="@android:drawable/checkbox_on_background" />
</FrameLayout>
</LinearLayout>
闲来无聊贴上一部分...
休息一下, 继续实现FTP上传功能...
敬请期待...
页:
[1]