由于自己写了一个CustomAdapter来继承CursorAdapter,要重写bindView和newView方法。
当一个ListActivity的启动时,onCreate方法中会setListAdapter为CustomAdapter。
当我打Log的时候发现每一个Item中bindView方法被调用了两次。也就是说,如果你有3个Item在List中,bindView就被调用了6次。
我想问一下CursorAdapter的bindView方法在什么时候被调用,为什么一个Item要调用两次bindView来显示?谢谢大家
这样的情形导致的问题是,有时候在查看List的时候,会发现字体出现明显的抖动,因为第一次刷新显示了所有了Item,但是后面又刷新显示了一次,这是因为每个Item两次调用bindView所致。当然,这种问题只有在数据量比较大的时候会出现延迟显示。不知道哪位高人能不能帮我解决一下。下面是简化的代码:
public class MyNotepad extends ListActivity {
    
    private NotesDbAdapter mDbHelper;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.notes_list);
        mDbHelper = new NotesDbAdapter(this);
        mDbHelper.open();        fillData();
       
        registerForContextMenu(getListView());
    }
    
    private void fillData() {
        Cursor notesCursor = mDbHelper.fetchAllNotes();
        startManagingCursor(notesCursor);
        
        CustomAdapter adapter = new CustomAdapter (this, notesCursor);
        setListAdapter(adapter);
    }
    
    
    final class CustomAdapter extends CursorAdapter{
    
public CustomAdapter (Context context, Cursor c) {
super(context, c);
// TODO Auto-generated constructor stub
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
            Log.i("huaping", "newView");
            LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    return li.inflate(R.layout.notes_row, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
    // TODO Auto-generated method stub
    Log.i("huaping", "bindView");
    String title = cursor.getString(KEY_TITLE);
    final TextView views = (TextView) view.findViewById(R.id.text1);
    views.setText(title);
}
    }}

解决方案 »

  1.   

    listactivity中的每个item都是一个view, 是view就要牵扯到layout了,那么这些view是怎么根据adapter生成的呢?1,newview生成新的view并返回,2,新生成的view在bindview中和数据bind. 就说这么多了,自己去搜搜看吧。
     关键字:Holder,listview.
      

  2.   

    你试试在public void onResume(){
                                     super.onResume();
                                          fillData();
                                     } 处理下看看,因该可以提高点速度
      

  3.   

    bindView是google自己写的方法,就算对屏幕进行拖动动作都会不停的执行这个方法。你把对数据库的执行放在这个方法里明显会拖慢系统速度。
    你可以在bindView里加段log,然后你轻轻拖动一下屏幕,你会发现你的Log简直多的可以用刷屏来形容,而你对数据库也是同样以刷屏般的频率执行着!
    所以你要做的就是改变代码结构,将对数据库的操作放到别处,用一次性处理的方法也好还是什么其他方法,总之这个bindView方法中绝对不要放一些“重量级“动作。
      

  4.   

    高手们说说adapter与这2个函数的调用过程吧!
      

  5.   

    看这里:
    http://stackoverflow.com/questions/3535074/getview-vs-bindview-in-a-custom-cursoradapter或者去看android的CustomAdapter的源码.
    CustomAdapter覆盖了BaseAdapter的getView方法,并在里面调用了newView()和bindView().所以你就知道这三个方法的调用关系了吧。adapter的机制和list的机制有关,其实,无论你实际数据项有多少,显示在屏幕上的只有固定个数的item(取决于list的高或宽)。
    在list滑动时,判断是否有Item已经滑出屏幕,滑出去的item被释放掉,加入新的item并显示。每次加入新的item就要调用getView()方法了。
    打log的话,你会看到,只要你滑动的距离超过一个item项的高度,就会调用一次getView()
      

  6.   

    在newView方法中,判断一下当前是否有View存在,如果存在就调用存在的View。就不会出现楼主说的结果了
      

  7.   

        /**
         * @see android.widget.ListAdapter#getView(int, View, ViewGroup)
         */
        public View getView(int position, View convertView, ViewGroup parent) {
            if (!mDataValid) {
                throw new IllegalStateException("this should only be called when the cursor is valid");
            }
            if (!mCursor.moveToPosition(position)) {
                throw new IllegalStateException("couldn't move cursor to position " + position);
            }
            View v;
            if (convertView == null) {
                v = newView(mContext, mCursor, parent);
            } else {
                v = convertView;
            }
            bindView(v, mContext, mCursor);
            return v;
        }源码很清晰。。做了更多的工作。省去了很多自己写的代码