将ImageView上的setImageBitmap转换为可滚动的GridView的最佳实践

时间:2014-04-02 00:53:03

标签: android gridview android-asynctask

我整天都在搜索关于这个问题的答案,但是找不到满意的答案。

我有一个可滚动的GridView,它包含Tile对象(下面的代码)。当应用程序作为单个JSON对象启动时,将下载所有Tile对象的图像。然后我将JSON解析为Bitmap对象,并使用setImageBitmap函数显示每个图像。

我的问题是GridView滚动性能不好,但只是在一个tile转换中(这意味着,当Adapter正在回收一个Tile对象时)。它不会多次将findViewById调用到TextViews和ImageViews,而且我目前正在使用AsyncTask和ViewHolder来避免滚动性能不佳,但没有成功。

我的问题是:当ImageView在GridView中时,使用setImageView方法的最佳做法是什么?如何避免滚动性能不佳?代码如下:

布局中的GridView

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Grid that contains all event tiles  -->
    <GridView
        android:id="@+id/gridView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:numColumns="auto_fit"
        android:columnWidth="250dp"
        android:verticalSpacing="10dp"
        android:horizontalSpacing="10dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:overScrollMode="never"/>
</RelativeLayout>

平铺布局

<RelativeLayout 
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="250dp"
    android:focusable="false"
android:focusableInTouchMode="false">

    <ImageView
        android:id="@+id/grid_item_image"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scaleType="fitXY"
        android:focusable="false"
    android:focusableInTouchMode="false"/>

    <com.custom.CustomTextView
        app:textStyle="bold"
        android:id="@+id/grid_item_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:gravity="center"/>

    <CheckBox
        android:id="@+id/grid_item_checkbox"
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:layout_gravity="center"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:focusable="false"
    android:focusableInTouchMode="false"/>

    <LinearLayout 
        android:id="@+id/light_overlay"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:alpha="0"/>

</RelativeLayout>

GridView适配器

public class GridViewAdapter extends BaseAdapter {

...

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

    TileView tileView;

    // Chooses if creates new TileView or uses existing one
    if (convertView == null) {
        tileView = new TileView(context, parentFragment);
    } else {
        tileView = (TileView) convertView;
    }

    // Refreshes TileView with image and label at desired position.
    tileView.refresh
                (Images.getImage(position),
                 Labels.getLabel(position));

    return tileView;
}
}

TileView类

public class TileView extends RelativeLayout{

private TextView textView;
private ImageView imageView;
private CheckBox checkBox;

public TileViewHolder holder;

private SetEventTask setEventTask;

/* CONSTRUCTORS */

private void init() {

    LayoutInflater inflater = (LayoutInflater)       
                getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.event_tile, this, true);

    textView = (TextView) this.findViewById(R.id.grid_item_label);
    imageView = (ImageView) this.findViewById(R.id.grid_item_image);
    checkBox = (CheckBox) this.findViewById(R.id.grid_item_checkbox);

    holder = new TileViewHolder();

    holder.checkBox = checkBox;
    holder.imageView = imageView;
    holder.textView = textView;

    this.setTag(holder);
}

/**
 * Method that replaces image and label in TileView
 */
public void refresh(Bitmap image,String text){
    if(setEventTask != null && !setEventTask.isCancelled()){
        setEventTask.cancel(true);
    }
    setEventTask = new SetEventTask(image,text,holder);
    setEventTask.execute();
}

    public static class TileViewHolder{
    public TextView textView;
    public ImageView imageView;
    public CheckBox checkBox;
}

}

SetImageTask AsyncTask

public class SetEventTask extends AsyncTask<Void, Void, Void>{

private final Bitmap image;
    private final String text;
private final TileViewHolder holder;

public SetEventTask(Bitmap image, String text, EventTileViewHolder holder){
    this.image = image;
            this.text = text;
    this.holder = holder;
}

@Override
protected Void doInBackground(Void... params) {

    return null;
}

protected void onPostExecute(Void param){

    holder.imageView.setImageBitmap(image);
    holder.textView.setText(text);
}
}

图片类

public class Images{

    public static List<Bitmap> images = new ArrayList<Bitmap>();

    public static Bitmap getImage(int position){
        return images.get(position)
    }

    public static void addImage(Bitmap image){ // image is decoded in the start of app
        images.add(image);
    }

}

正如你所看到的,我使用Asynctask(即使知道它没有效果,因为onPostExecute将调用UI主线程)和ViewHolder。

1 个答案:

答案 0 :(得分:0)

好吧,我希望它有所帮助......

我没有在这里发布Manifest文件。由于动画,HardwareAcceleration是假的。我将它设置为true,我的GridView现在滚动顺畅!