sky! 发表于 2014-3-16 23:30:42

异步读取图片到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]
查看完整版本: 异步读取图片到GridView