0

您好stackoverflow,我正在尝试开发一个应用程序,例如Gallery针对SD Card. 例如我拿了WhatsApp Images目录,这是我的代码

public class WhatsAppInboxImagesActivity extends Activity {

private ImageAdapter imageAdapter;
private ProgressDialog pd;
ArrayList<String> f = null;
File[] listFile;
Button btnDelete;
HashSet<String> selectedFile = null;
GridView imagegrid;
AlertDialog alertDialog = null;

static
{
    File noFile = new File(Environment.getExternalStorageDirectory().getPath(), "/WhatsApp/Media/WhatsApp Images/Sent/.nomedia");
    if(noFile.exists())
    {
        noFile.delete();
    }
}//End of static block

private void initialize()
{
    imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
    btnDelete = (Button) findViewById(R.id.btnDeleteImg);
    selectedFile = new HashSet<String>();// list of file paths boolean checked
    f = new ArrayList<String>();// list of file paths
}//End of initialize method

@Override
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_whats_app_images_inbox);

    this.initialize();
    getFromSdcard();        
    imageAdapter = new ImageAdapter();

    /*
     * Performing time consuming actions
     */
    new AsyncTask<Void, Void, Void>() 
    {
        @Override
        protected void onPreExecute() 
        {
            pd = ProgressDialog.show(WhatsAppInboxImagesActivity.this,
                    "Loading..", "Please Wait", true, false);
        }// End of onPreExecute method

        @Override
        protected Void doInBackground(Void... params) 
        {
            return null;
        }// End of doInBackground method

        @Override
        protected void onPostExecute(Void result) 
        {
            imagegrid.setAdapter(imageAdapter);
            imageAdapter.notifyDataSetChanged();
            pd.dismiss();
        }
    }.execute((Void[]) null);


    btnDelete.setOnClickListener(new View.OnClickListener() 
    {
        @Override
        public void onClick(View v) 
        {
             new AsyncTask<Void, Void, Void>() 
             {
                    @Override
                    protected void onPreExecute() 
                    {
                        pd = ProgressDialog.show(WhatsAppInboxImagesActivity.this,
                                "Loading..", "Please Wait", true, false);
                    }// End of onPreExecute method

                    @Override
                    protected Void doInBackground(Void... params) 
                    {
                        @SuppressWarnings("rawtypes")
                        Iterator iterator = selectedFile.iterator();
                        while (iterator.hasNext())
                        {
                            new File(iterator.next().toString()).delete();
                        }//End of while loop
                        return null;
                    }// End of doInBackground method

                    @Override
                    protected void onPostExecute(Void result) 
                    {
                        pd.dismiss();
                    }//End of onPostExecute method
                }.execute((Void[]) null);

                finish();
                startActivity(getIntent());
        }//End of onClick method
    });//End of btnDelete anonymous class

}//End of onCreate method

public void getFromSdcard() 
{
    File file = new File( Environment.getExternalStorageDirectory().getPath(), "/WhatsApp/Media/WhatsApp Images");

    if (file.isDirectory()) 
    {
        listFile = file.listFiles();
        for (int i = 0; i < listFile.length; i++) 
        {
            if(listFile[i].isDirectory())
            {
                continue;
            }
            f.add(listFile[i].getAbsolutePath());
        }//End of for loop
    }//End of if condition
}//End of getFromSdcard method

public class ImageAdapter extends BaseAdapter 
{
    private LayoutInflater mInflater;

    public ImageAdapter() 
    {
        mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }//End of ImageAdapter constructor

    public int getCount() 
    {
        return f.size();
    }//End of getCount method

    public Object getItem(int position) 
    {
        return position;
    }//End of getItem method

    public long getItemId(int position) 
    {
        return position;
    }//End of getItemId method

    public View getView(int position, View convertView, ViewGroup parent) 
    {
        ViewHolder holder;
        if (convertView == null) 
        {
            holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.galleryitem, null);
            holder.imageview = (ImageView) convertView.findViewById(R.id.thumbImage);
            holder.checkbox = (CheckBox) convertView.findViewById(R.id.itemCheckBox);

            convertView.setTag(holder);
        }//End of if condition
        else 
        {
            holder = (ViewHolder) convertView.getTag();
        }//End of else

        BitmapFactory.Options options = new BitmapFactory.Options();
        // will results in a much smaller image than the original
        options.inSampleSize = 4;

        // don't ever use a path to /sdcard like this, but I'm sure you have a sane way to do that
        // in this case nebulae.jpg is a 19MB 8000x3874px image
        final Bitmap b = BitmapFactory.decodeFile(f.get(position), options);

        holder.imageview.setImageBitmap(b);

        return convertView;
    }//End of getView method
}//End of ImageAdapter instance inner class

class ViewHolder 
{
    ImageView imageview;
    CheckBox checkbox;
    int id;
}//End of ViewHolder instance inner class
}//End of WhatsAppImagesActivity

到目前为止,一切都很好,但问题是图像全部加载one shot,所以滚动非常慢,有时OutOfMemoryException会出现decoded文件BitMapFactory,请任何人帮助我解决这个难题。

编辑:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view = null;
    if (convertView == null) {
        LayoutInflater inflator = context.getLayoutInflater();
        view = inflator.inflate(R.layout.list_layout, null);
        final ViewHolder viewHolder = new ViewHolder();
        viewHolder.text = (TextView) view.findViewById(R.id.label);
        viewHolder.text.setTextColor(Color.BLACK);
        viewHolder.image = (ImageView) view.findViewById(R.id.image);
        viewHolder.image.setVisibility(View.GONE);
        viewHolder.cb = (CheckBox) view.findViewById(R.id.item_check_box);
        viewHolder.pb = (ProgressBar) view.findViewById(R.id.progressBar);
        view.setTag(viewHolder);
    } else {
        view = convertView;
    }
    final int pos = position;
    ViewHolder holder = (ViewHolder) view.getTag();
    holder.text.setText(list.get(position).getName());
    holder.image.setTag(list.get(position).getURL());
    holder.image.setId(position);
    PbAndImage pb_and_image = new PbAndImage();
    pb_and_image.setImg(holder.image);
    pb_and_image.setPb(holder.pb);
    new DownloadImageTask().execute(pb_and_image);
    return view;
}

谢谢。

4

2 回答 2

3

你应该使用延迟加载

在此处访问本教程以进行延迟加载。它非常简单。如果您对此有任何问题,请告诉我。

Edit

public class MainActivity extends ListActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    String path = Environment.getExternalStorageDirectory()+"/WhatsApp/Media/WhatsApp Images";

    final List<Model> list = new ArrayList<Model>();
    final File file = new File(path);

    final ProgressDialog dialog = ProgressDialog.show(MainActivity.this, "",
            "Please Wait...", true);
    new Thread(new Runnable() {
        public void run() {

            dismissDialog(dialog);
            for(File fileChild : file.listFiles()){
                list.add(get(fileChild.getName(), fileChild.getAbsolutePath()));
            }

        }
    }).start();

    ArrayAdapter<Model> adapter = new MyCustomArrayAdapter(this, list);
    setListAdapter(adapter);
}

public void dismissDialog(final ProgressDialog dialog) {
    runOnUiThread(new Runnable() {
        public void run() {
            dialog.dismiss();
        }
    });
}

private Model get(String s, String url) {
    return new Model(s, url);
}

}
于 2013-10-16T07:22:27.847 回答
0

这可能会有所帮助:UniversalImageLoader

这就是我所做的:

/**
 * UniversalImageLoader載入遠端圖片,僅使用RAM做圖片快取 (Load pic & use RAM as cache)
 * @param android.content.Context
 * @author https://github.com/nostra13/Android-Universal-Image-Loader
 * @param android.widget.ImageView - 顯示圖片的元件 (your image container)
 * @param int - 載入失敗的預設圖片Resource ID (default pic if load fail, I put default pic in resources folder)
 * @param java.lang.String - 檔案URL (pic URL or path)
 */
public static void imageLoaderMemoryCache(Context context, final ImageView img, final int failImgID, String url)
{
  ImageLoader imageLoader=ImageLoader.getInstance();
  ImageLoaderConfiguration config=new ImageLoaderConfiguration.Builder(context)
    .memoryCacheExtraOptions(100, 100) // max width, max height
    .threadPoolSize(5)
    .threadPriority(Thread.NORM_PRIORITY+1)
    .denyCacheImageMultipleSizesInMemory()
    .tasksProcessingOrder(QueueProcessingType.FIFO)
    .defaultDisplayImageOptions(DisplayImageOptions.createSimple())
    .enableLogging()
    .build();
  imageLoader.init(config);

  DisplayImageOptions options = new DisplayImageOptions.Builder()
    .showImageForEmptyUri(R.drawable.cover_sample)
    .cacheInMemory(true)
    .imageScaleType(ImageScaleType.IN_SAMPLE_INT)
    .bitmapConfig(Bitmap.Config.RGB_565)
    .delayBeforeLoading(1)
    .displayer(new FadeInBitmapDisplayer(500))
    .build();

  imageLoader.displayImage(url, img, options, new ImageLoadingListener()
  {
    @Override
    public void onLoadingStarted(String url, View view)
    {img.setImageResource(failImgID);} //一開始先顯示預設圖 (display default pic at first)
    @Override
    public void onLoadingFailed(String url, View view, FailReason failReason)
    {img.setImageResource(failImgID);}
    @Override
    public void onLoadingComplete(String url, View view, Bitmap loadedImage)
    {}
    @Override
    public void onLoadingCancelled(String url, View view)
    {}
  });
}

用法(列表视图)

public View getView(...)
{
  vh.imgCover=(ImageView)convertView.findViewById(R.id.imgCover);
  //...
  // some stuff
  //...
  Util.imageLoaderDiskCache(getActivity(), vh.imgCover, R.drawable.cover_sample, "(pic file path)");
}

希望有帮助~

于 2013-10-16T07:26:23.113 回答