0

これはよくある質問のようですが、見つけた解決策を実装できませんでした。Listviewサムネイルとテキスト フィールドを連続して表示するカスタム アダプターを使用しています。サムネイルは、以前に作成したフォルダーからのもので、アプリから撮った写真を入れています。

これが私のリスト活動です:

private LayoutInflater mInflater;
private Vector<RowData> data;
private CustomAdapter adapter;
private RowData rd;

static File path = Environment.getExternalStorageDirectory();
static File fnames = new File(path, "MyImages");

static String[] title = fnames.list();

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

    mInflater = (LayoutInflater) getSystemService(
    Activity.LAYOUT_INFLATER_SERVICE);
    setListName();
    data = new Vector<RowData>();
    for(int i=0;i<title.length;i++){
        try {
            rd = new RowData(i,title[i]);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        data.add(rd);
    }

    getListView().setTextFilterEnabled(true);
    getListView().setScrollingCacheEnabled(false);
}

public void onRestart()
{
    super.onRestart();
    setListName();
}

private Vector<RowData> setListName()
{
    data = new Vector<RowData>();
    String[] title = fnames.list();

    //get the databases textblog
    DatabaseHandler db = new DatabaseHandler(this);
    List<TextBlog> textBlogs = db.getAllText();
    int positionRaw = textBlogs.size();

    for (int i=0;i<textBlogs.size(); i++) {
        rd = new RowData(i, textBlogs.get(i).getText());
        data.add(rd);
    }

    for(int i=0;i<title.length;i++) {
        try {
            rd = new RowData(positionRaw,title[i]);
            positionRaw++;
        } catch (ParseException e) {
            e.printStackTrace();
        }

        data.add(rd);
    }

    adapter = new CustomAdapter(this, R.layout.list,R.id.title, data);
    setListAdapter(adapter);
    getListView().setTextFilterEnabled(true);
    adapter.notifyDataSetChanged();

    return data;
}


//Create thumbnail from file picture
private Bitmap decodeFile(File f) {
    try {
        //Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f),null,o);

        //The new size we want to scale to
        final int REQUIRED_SIZE=70;

        //Find the correct scale value. It should be the power of 2.
        int scale=1;
        while (o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
            scale*=2;

        //Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {

    }

    return null;
}

//Set row object
private class RowData 
{
    protected int mId;
    protected String mTitle;
    RowData(int id,String title){
    mId=id;
    mTitle = title;
}

@Override
public String toString() {
    return mId+" "+mTitle+" ";
}

ここに私のカスタムアダプターがあります:

public class CustomAdapter extends ArrayAdapter<RowData>
{
    public CustomAdapter(Context context, int resource, int textViewResourceId, 
                                        List<RowData> objects) 
    {               
        super(context, resource, textViewResourceId, objects);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {   
        ViewHolder holder = null;
        TextView title = null;
        ImageView thumb=null;
        RowData rowData= getItem(position);

        if(null == convertView) {
            convertView = mInflater.inflate(R.layout.list, null);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        }

        holder = (ViewHolder) convertView.getTag();
        title = holder.gettitle();
        title.setText(rowData.mTitle);

        thumb=holder.getImage();
        File file = new File(path + "/MyImages/" + rowData.mTitle);

        //Check what kind of file is it to add thumbnail
        //Way too slow use asynchronous task

        if (rowData.mTitle.substring(rowData.mTitle.lastIndexOf('.') + 1).equalsIgnoreCase("mp4") == true)
        {    
            Bitmap thumbVideo = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);
            thumb.setImageBitmap(thumbVideo);
        }
        else if (rowData.mTitle.substring(rowData.mTitle.lastIndexOf('.') + 1).equalsIgnoreCase("3gpp") == true)
        {
            thumb.setImageDrawable(getResources().getDrawable(R.drawable.voice));
        }
        else
        {
            thumb.setImageBitmap(decodeFile(file));
        }

        return convertView;
    }

    private class ViewHolder {
        private View mRow;
        private TextView title = null;
        private ImageView thumb=null; 

        public ViewHolder(View row) {
            mRow = row;
        }

        public TextView gettitle() {
            if(null == title) {
                title = (TextView) mRow.findViewById(R.id.title);
            }
                return title;
        }     

        public ImageView getImage() {
            if (null == thumb) {
                thumb = (ImageView) mRow.findViewById(R.id.img);
                                      }
                return thumb;
            }
        }
    }
}

サムネイルの作成が原因であると確信しており、 に実装する必要がありますがAsynchTask、成功することなく試しました。

誰かが私が間違っている場所を提案できますか、またはリストでヒントを教えてもらえますか?

4

1 に答える 1

1

ここで ViewHolder パターンを実装しようとしていますが、実装が間違っているようです。

このパターンの考え方はfindViewById()、パフォーマンスに影響を与える呼び出しを減らすことです。行が null (convertView) の場合のみ、 を呼び出す必要がありますfindViewById()。それ以外の場合は、setTag()

あなたのコードを見てみましょう:

if(null == convertView){
    convertView = mInflater.inflate(R.layout.list, null);
    holder = new ViewHolder();
    convertView.setTag(holder);
}

// .......          
title = holder.gettitle();
// .........
thumb=holder.getImage();

holder.getTitle()、およびがステートメントholder.getImage()の後に呼び出されることに注意してください。これは、が null であるかifどうかに関係なく、毎回呼び出されることを意味します。 これらのゲッターを見ると、以下を呼び出すコードが含まれていることがわかります。convertView
findViewById();

元。のためにgetTitle()

public TextView gettitle() {
     if(null == title){
          title = (TextView) mRow.findViewById(R.id.title);
     }
     return title;
} 

したがって、基本的に、ここではViewHolderパターンを使用せず、混合コードのみを使用し、最終的にfindViewById()は毎回呼び出され、パフォーマンスが低下しますListView.

正しく行うには、が nullfindViewById()の場合にのみ呼び出す必要があります。convertView元:

if(null==convertView){
    convertView = mInflater.inflate(R.layout.list, null);
    holder = new ViewHolder();

    // Getting a refernce to the views with findViewById()
    title = holder.gettitle();
    thumb=holder.getImage();

    convertView.setTag(holder);
}else{
     holder = (ViewHolder) convertView.getTag();
}

// Then you set the appropriate values to your views through the holder:
holder.title.setText("");
holder.thumb.setImageBitmap(...);

ViewHolderこれはパターンを実装する正しい方法です

(PS: タイトル、サムなどのアクセス修飾子を public に変更する必要があります。)

于 2012-08-09T10:10:13.963 に答える