-1

我正在尝试以缩略图的形式将图片文件从我的内部存储加载到列表视图。目前,我正在使用 ViewHolder,但滚动时加载仍然不稳定,所以我将尝试使用 AsyncTask。但是,我无法理解如何构建 AsyncTask,因为我发现的大多数示例都涉及从网站下载。我什至不确定是否应该在我的 BaseAdapter 或 MainActivity 中对它进行子类化。我在下面添加了我的 baseadapter,并在底部添加了未完成的 AsyncTask。如何将其构造为:使用 AsyncTask 协助 ViewHolder,或直接将图像传递给 AsyncTask 并让它返回位图,以便 ListView 平滑滚动?

public class ListViewAdapter extends BaseAdapter {

private static final int WIDTH = 250;
private static final int HEIGHT = 250;
private static final int ROTATION = 90;

private final static String TAG = "Pictures";

private final ArrayList<SelfieObject> mItems = new ArrayList<SelfieObject>();
private Context mContext;
private File mStorageDir;
private String mFilePrefix;

public ListViewAdapter(Context context, File storageDir, String filePrefix) {
    mContext = context;
    mStorageDir = storageDir;
    mFilePrefix = filePrefix;

    //get file list from storage to display
    InitializeItemsFromStorage(storageDir, filePrefix);
}

//this method creates an array of files stored on the device or SD card.
private void InitializeItemsFromStorage(File storageDir, String prefix) {

    log("in InitializeItemsFromStorage()");
    mItems.clear();

    File[] files = getFiles(storageDir, prefix);
    for (File f : files) {
        SelfieObject selfie = new SelfieObject(f);
        mItems.add(selfie);
    }

}

public void Update() {

    log("in Update()");
    InitializeItemsFromStorage(mStorageDir, mFilePrefix);
    notifyDataSetChanged();
}

/*
 * return the list of file objects of the given directory that begin with
 * the prefix.
 */
private File[] getFiles(File storageDir, final String prefix) {
    FileFilter fileFilter = new FileFilter() {

        @Override
        public boolean accept(File pathname) {
            if (pathname.isFile() && pathname.getName().startsWith(prefix))
                return true;
            else
                return false;
        }
    };

    File[] result = storageDir.listFiles(fileFilter);
    return result;
}

public int getCount() {

    log("in getCount()");
    return mItems.size();
}

public Object getItem(int position) {

    log("in getItem()");
    return mItems.get(position);
}

public long getItemId(int position) {

    log("in getItemId()");
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    Log.v(TAG, "in getView for position " + position +
            ", convertView is " +
            ((convertView == null)?"null":"being recycled"));

    View newView = convertView;
    ViewHolder holder;

    if (null == convertView) {

        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        newView = inflater.inflate(R.layout.single_item, null);

        holder = new ViewHolder();
        holder.description = (TextView) newView.findViewById(R.id.textView1);
        holder.picture = (ImageView) newView.findViewById(R.id.imageView1);
        newView.setTag(holder);

    } else {
        holder = (ViewHolder) newView.getTag();
    }

    holder.picture.setScaleType(ImageView.ScaleType.CENTER_CROP);

    SelfieObject selfie = (SelfieObject) getItem(position);
    setPic(holder.picture, new Point(WIDTH, HEIGHT), selfie.getPath());

    TextView textView = (TextView) holder.description;
    textView.setText(selfie.getName());     

    log("Exiting getView");
    return newView;
}

static class ViewHolder {

    ImageView picture;
    TextView description;   
}

public void add(SelfieObject listItem) {
    mItems.add(listItem);
    notifyDataSetChanged();
}

public ArrayList<SelfieObject> getList(){
    return mItems;
}

public void removeAllViews(){
    mItems.clear();
    this.notifyDataSetChanged();
}

public static void setPic(ImageView imageView, Point requestedSize,
        String pathName) {
    // set the dimensions of the View
    int targetW = requestedSize.x;
    int targetH = requestedSize.y;

    // Get the dimensions of the bitmap
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(pathName, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    // Determine how much to scale down the image
    int scaleFactor = Math.min(photoW / targetW, photoH / targetH);

    // Decode the image file into a Bitmap sized to fill the View
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    Bitmap bitmap = BitmapFactory.decodeFile(pathName, bmOptions);
    imageView.setImageBitmap(bitmap);
    imageView.setRotation(ROTATION);
}

//Automation logging tool
public void log(String s){

    Log.i(TAG, s);
}

private class AsyncTaskLoadImage extends AsyncTask<Object, Void, Bitmap>{

    private ImageView image;
    private String path;

    public AsyncTaskLoadImage(ImageView image){

        this.image = image; 
        this.path = image.getTag().toString();
    }

    @Override
    protected Bitmap doInBackground(Object... params) {

        Bitmap bitmap = null;
        File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + path);

        if(file.exists()){
            bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
        }

        return bitmap;
    }
}

}

4

1 回答 1

1

AsyncTask 应该做任何在 UI 线程中太慢而不能做的事情。在这个例子中,获取和下采样图像,以及设置 ViewHolder 应该在后台完成。

但是,我建议您不要尝试自己修复 ListView,而是查看现有的解决方案,例如:https ://github.com/lucasr/smoothie

另外,我强烈建议您对位图进行下采样,否则它们会消耗大量多余的计算时间和内存。虽然前者在滚动时会滞后于你的 UI,但后者会给你一个很好的 OutOfMemoryException。请参阅:http: //developer.android.com/training/displaying-bitmaps/cache-bitmap.html

于 2015-01-23T03:16:49.880 回答