GVKun编程网logo

ViewHolder模式在自定义CursorAdapter中正确实现了吗?(view holder)

15

如果您对ViewHolder模式在自定义CursorAdapter中正确实现了吗?和viewholder感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解ViewHolder模式在自定义Curso

如果您对ViewHolder模式在自定义CursorAdapter中正确实现了吗?view holder感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解ViewHolder模式在自定义CursorAdapter中正确实现了吗?的各种细节,并对view holder进行深入的分析,此外还有关于Android RecyclerView.Adapter onCreateViewHolder()工作、android – ListView with ArrayAdapter和ViewHolder将图标添加到错误的项目、android – Listview和CustomAdapter扩展SimpleCursorAdapter、android – ORMLite性能:ArrayAdapter vs CursorAdapter vs自定义适配器的实用技巧。

本文目录一览:

ViewHolder模式在自定义CursorAdapter中正确实现了吗?(view holder)

ViewHolder模式在自定义CursorAdapter中正确实现了吗?(view holder)

这是我的自定义CursorAdapter:

public class TasksAdapter extends CursorAdapter implements Filterable {    private final Context context;    public TasksAdapter(Context context, Cursor c) {        super(context, c);        this.context = context;    }    /**     * @see android.widget.CursorAdapter#newView(android.content.Context, android.database.Cursor, android.view.ViewGroup)     */    @Override    public View newView(Context context, Cursor cursor, ViewGroup parent) {        LayoutInflater inflater = LayoutInflater.from(context);        View v = inflater.inflate(android.R.layout.simple_list_item_checked, parent, false);        ViewHolder holder = new ViewHolder();        holder.textview = (CheckedTextView)v.findViewById(android.R.id.text1);        v.setTag(holder);        return v;    }    /**       * @see android.widget.CursorAdapter#bindView(android.view.View, android.content.Context, android.database.Cursor)     */    @Override    public void bindView(View view, Context context, Cursor cursor) {        ViewHolder holder = (ViewHolder)view.getTag();        int titleCol = cursor.getColumnIndexOrThrow(Tasks.TITLE);        int completedCol = cursor.getColumnIndexOrThrow(Tasks.COMPLETED);        String title = cursor.getString(titleCol);        boolean completed = Util.intToBool(cursor.getInt(completedCol));        holder.textview.setText(title);        holder.textview.setChecked(completed);    }    /**     * @see android.widget.CursorAdapter#runQueryOnBackgroundThread(java.lang.CharSequence)     */    @Override    public Cursor runQueryOnBackgroundThread(CharSequence constraint) {        StringBuffer buffer = null;        String[] args = null;        if (constraint != null) {            buffer = new StringBuffer();            buffer.append("UPPER (");            buffer.append(Tasks.TITLE);            buffer.append(") GLOB ?");            args = new String[] { "*" + constraint.toString().toUpperCase() + "*" };        }        Cursor c = context.getContentResolver().query(Tasks.CONTENT_URI,            null, (buffer == null ? null : buffer.toString()), args,            Tasks.DEFAULT_SORT_ORDER);        c.moveToFirst();        return c;    }    /**     * @see android.widget.CursorAdapter#convertToString(android.database.Cursor)     */    @Override    public CharSequence convertToString(Cursor cursor) {        final int titleCol = cursor.getColumnIndexOrThrow(Tasks.TITLE);        String title = cursor.getString(titleCol);        return title;    }    static class ViewHolder {        CheckedTextView textview;    }}

这是否属于ViewHolder模式的约束?我不确定,因为这是CursorAdapter,那里没有getView。如果有任何问题或建议,请指出。

答案1

小编典典

CursorAdapter``newView每次需要新行时都不会调用;如果它已经有一个View,它将调用bindView,因此创建的视图实际上已被重用。

就是说,正如 约瑟夫 在评论中指出的那样,您仍然可以使用ViewHolder以避免findViewById重复调用。

如果您仍然担心效率,那么请看一下SimpleCursorAdapter使用的实现WeakHashMap(的映射WeakReferences):

WeakHashMap<View, View[]> mHolders = new WeakHashMap<View, View[]>();

Android RecyclerView.Adapter onCreateViewHolder()工作

Android RecyclerView.Adapter onCreateViewHolder()工作

我正在使用RecyclerView.Adapter,但我对在CreateViewHolder上的方法工作感到困惑.
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup,int viewType) {
    if(viewType==TYPE_ITEM) {

        View mView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.inflate_common_item,viewGroup,false);
        ViewHolder vh = new ViewHolder(mView);
        return vh;

    } else {
        View mView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.inflate_uncommon_item,false);
        ViewHolderFooter vh = new ViewHolderFooter(mView);
        return vh;

    }
}

所以我在我的列表中有10个项目,所以每个项目这个方法将被调用,并且每当一个新的ViewHolder将被创建当然,它将有一次为每个视图,但现在我的问题是当我们使用ListView和BaseAdapter与我们将ViewHolder存储在标签中并使用它.我们不会为每个项目创建ViewHolder.

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

            if(convertView == null) {
                    convertView = inflater.inflate(R.layout.layout_list_item,null);
                    mViewHolder = new MyViewHolder();
                    convertView.setTag(mViewHolder);
            } else {
                    mViewHolder = (MyViewHolder) convertView.getTag();
            }

            mViewHolder.tvTitle = detail(convertView,R.id.tvTitle,myList.get(position).getTitle());
            mViewHolder.tvDesc  = detail(convertView,R.id.tvDesc,myList.get(position).getDescription());
            mViewHolder.ivIcon  = detail(convertView,R.id.ivIcon,myList.get(position).getImgResId());

            return convertView;
    }

所以我们不会创建额外的观看者对象.请帮我理解利弊.

谢谢

解决方法

当没有RecyclerView可以重用的现有视图持有者时,onCreateViewHolder仅创建一个新的视图持有者.所以,例如,如果您的RecyclerView可以一次显示5个项目,它将创建5-6个ViewHolders,然后自动重新使用它们,每次调用onBindViewHolder.

它类似于ListView中的代码(检查convertView是否为null,如果没有,请从标签中抓取现有的ViewHolder),但使用RecyclerView,这一切都将自动完成.

我想这是使用RecyclerView的专业人士之一 – 您不必担心像ViewView那样重用ViewHolders. con Rec RecyclerView是非常可定制的,但内置功能很少 – 与ListView不同,它不是很可定制的,但内置了很多功能.

android – ListView with ArrayAdapter和ViewHolder将图标添加到错误的项目

android – ListView with ArrayAdapter和ViewHolder将图标添加到错误的项目

我有一个使用ArrayAdapter的动态ListView.从微调器中选择名称时,名称以及显示它们是男性还是女性的图标将添加到ListView中.

通常一切都很好(名称正确地添加到列表中,与图标一起).但是显示性别的图标会被添加到ListView中的错误项目中.名称将添加到列表的底部,但图标将放置在列表顶部的名称处.我不知道这是否是我使用ViewHolder的方式,但在Android website中没有文档.

// Listview inflater
inflater = (LayoutInflater) (this).getSystemService(LAYOUT_INFLATER_SERVICE);

// List Array.
mAdapter = new ArrayAdapter<String>(this,R.layout.player_simple_list,R.id.label,mStrings) {

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

        Log.i("ANDY","View getView Called");
        // A ViewHolder keeps references to children views to 
        // avoid unneccessary calls to findViewById() on each row.
        ViewHolder holder;

        if (null == convertView) {
            Log.i("ANDY","Position not prevIoUsly used,so inflating");
            convertView = inflater.inflate(R.layout.player_simple_list,null);
            // Creates a ViewHolder and store references to the
            // two children views we want to bind data to.
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.label);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);
            if (sexmale == true) {
                holder.icon.setimageBitmap(maleicon);
            }
            else {
                holder.icon.setimageBitmap(femaleicon);
            }
            convertView.setTag(holder);
        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag();

        }
        // Bind the data efficiently with the holder.
        holder.text.setText(getItem(position));
        // Change icon depending is the sexmale variable is true or false.
        Log.i("ANDY","getCount = "+mAdapter.getCount());
        return convertView;
    }
};
setlistadapter(mAdapter);

解决方法

您必须在if-else-if之后设置图标以创建或绑定持有者.否则,图标将仅在列表中的前几个项目中正确显示,即直到未填充ListView.
public View getView(int position,ViewGroup parent) {

    Log.i("ANDY","View getView Called");
    // A ViewHolder keeps references to children views
    // to avoid unneccessary calls to findViewById() on each row.
    ViewHolder holder;

        if (null == convertView) {
            Log.i("ANDY",null);

            // Creates a ViewHolder and store references to
            // the two children views we want to bind data to.
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.label);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);
            convertView.setTag(holder);
        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag();

        }
        // Bind the data efficiently with the holder.
        holder.text.setText(getItem(position));

        // Change icon depending is the sexmale variable is true or false.
        if (sexmale == true) {
            holder.icon.setimageBitmap(maleicon);
        }
        else {
            holder.icon.setimageBitmap(femaleicon);
        }
        Log.i("ANDY","getCount = "+mAdapter.getCount());
        return convertView;
}

android – Listview和CustomAdapter扩展SimpleCursorAdapter

android – Listview和CustomAdapter扩展SimpleCursorAdapter

我希望操纵ListView中所选行的背景颜色,从阅读中我需要使用CustomAdapter进行扩展.我的主适配器是SimpleCursorAdapter类型,所以我修改了一个将ArrayAdapter扩展为SimpleCursorAdapter的CustomAdapter.

我的问题是使用CustomAdapter时listview是空白但如果不扩展并使用SimpleCursorAdapter,listview有行/项.
Logcat在我的CustomAdapter中显示一个问题,见下文.

这是我的主要活动代码:

phrasesdb helper = new phrasesdb(this);
database = helper.getWritableDatabase();
data = database.query("phrases",fields,null,fields[0] + " COLLATE NOCASE ASC");
//WORKING SimpleCursorAdapter
//dataSource = new SimpleCursorAdapter(this,R.layout.phrases,data,new int[] { R.id.phrase });

//NOT WORKING
dataSource = new CustomAdapter(this,new int[] { R.id.phrase });

view = getListView();
setlistadapter(dataSource);

这是Custom Adapter类,我已经标记了logcat错误的位置:

import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;

public class CustomAdapter extends SimpleCursorAdapter {

protected static final int NO_SELECTED_COLOR = 0xFF191919;
protected static final int SELECTED_COLOR = 0xFF3366CC;

Cursor items;
private LayoutInflater mInflater;
private int viewResourceId;
private int selectedPosition;


public CustomAdapter(Context context,int resourceId,Cursor data,String[] fields,int[] is) {
    super(context,resourceId,is);
    mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    viewResourceId = resourceId;
    items = data;
}


@Override
public View getView(int position,View convertView,ViewGroup parent) {
    TextView tv = (TextView)convertView;
    if (tv == null) {
  //WHEN DEBUGGING THIS IS WHERE LOGCAT ERROR MESSAGES STARTS
        tv = (TextView)mInflater.inflate(viewResourceId,null);
    }
    tv.setText(items.getString(position));



    // Change the background color
    if (position==selectedPosition) tv.setBackgroundColor(SELECTED_COLOR);
    else tv.setBackgroundColor(NO_SELECTED_COLOR);

    return tv;
}

public void setSelected(int position) {
    selectedPosition = position;
}
}

这是LogCat:

10-18 13:33:17.869: E/ListView(28378): android.widget.LinearLayout
10-18 13:33:17.869: E/ListView(28378): java.lang.classCastException: android.widget.LinearLayout
10-18 13:33:17.869: E/ListView(28378): at com.xxx.xxx.CustomAdapter.getView(CustomAdapter.java:49)
10-18 13:33:17.869: E/ListView(28378): at android.widget.AbsListView.obtainView(AbsListView.java:1449)
10-18 13:33:17.869: E/ListView(28378): at android.widget.ListView.makeAndAddView(ListView.java:1801)
10-18 13:33:17.869: E/ListView(28378): at android.widget.ListView.fillSpecific(ListView.java:1339)
10-18 13:33:17.869: E/ListView(28378): at android.widget.ListView.layoutChildren(ListView.java:1637)
10-18 13:33:17.869: E/ListView(28378): at android.widget.AbsListView.onLayout(AbsListView.java:1279)
10-18 13:33:17.869: E/ListView(28378): at android.view.View.layout(View.java:7321)
10-18 13:33:17.869: E/ListView(28378): at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
10-18 13:33:17.869: E/ListView(28378): at android.view.View.layout(View.java:7321)
10-18 13:33:17.869: E/ListView(28378): at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
10-18 13:33:17.869: E/ListView(28378): at android.view.View.layout(View.java:7321)
10-18 13:33:17.869: E/ListView(28378): at android.view.ViewRoot.performTraversals(ViewRoot.java:1217)
10-18 13:33:17.869: E/ListView(28378): at android.view.ViewRoot.handleMessage(ViewRoot.java:1991)
10-18 13:33:17.869: E/ListView(28378): at android.os.Handler.dispatchMessage(Handler.java:99)
10-18 13:33:17.869: E/ListView(28378): at android.os.Looper.loop(Looper.java:150)
10-18 13:33:17.869: E/ListView(28378): at android.app.ActivityThread.main(ActivityThread.java:4385)
10-18 13:33:17.869: E/ListView(28378): at java.lang.reflect.Method.invokeNative(Native Method)
10-18 13:33:17.869: E/ListView(28378): at java.lang.reflect.Method.invoke(Method.java:507)
10-18 13:33:17.869: E/ListView(28378): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
10-18 13:33:17.869: E/ListView(28378): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
10-18 13:33:17.869: E/ListView(28378): at dalvik.system.NativeStart.main(Native Method)

这是布局

android – ORMLite性能:ArrayAdapter vs CursorAdapter vs自定义适配器

android – ORMLite性能:ArrayAdapter vs CursorAdapter vs自定义适配器

我有相对较小的H2数据库.我期待不超过100个参赛作品,甚至感觉高居榜首.

我有一个列表视图与一些控件,并使用ArrayAdapter调用QueryAll()来填充数据.它完美地工作,因为我可以在按下按钮时修改内存中数组中的数据,然后将结果写入DB而无需重新加载它.但最初的负荷却出乎意料地缓慢

我想知道是否应该使用CursorAdapter,因为它似乎更适合问题或编写自定义适配器来使用DAO Iterator.

使用Cursor或自定义适配器会有性能提升吗?在我看来,感觉就像定制适配器应该提供最佳性能.

解决方法

最好使用自定义适配器
Content provider.

今天关于ViewHolder模式在自定义CursorAdapter中正确实现了吗?view holder的分享就到这里,希望大家有所收获,若想了解更多关于Android RecyclerView.Adapter onCreateViewHolder()工作、android – ListView with ArrayAdapter和ViewHolder将图标添加到错误的项目、android – Listview和CustomAdapter扩展SimpleCursorAdapter、android – ORMLite性能:ArrayAdapter vs CursorAdapter vs自定义适配器等相关知识,可以在本站进行查询。

本文标签: