Android 如何在BaseAdapter.getView中为创建的视图保持稳定的位置?

Android 如何在BaseAdapter.getView中为创建的视图保持稳定的位置?,android,Android,在BaseAdapter.getView()中保留已创建视图的位置似乎是个问题 在我的例子中,我创建了一个数据对象(-array),它保存了listview的所有数据。列表项有三种类型:分隔符、带有复选框的项和带有可单击图像的项以打开对话框。该数据将由自定义阵列适配器执行,始终使用单独的布局。为此,我使用了不同的取景器。创造不是问题,但如果回收商开始工作,所有的标识/位置都会改变。但我的数据是基于这一点 我知道回收器是如何工作的,但是程序员应该如何保持与自己数据的关系呢 在stackoverfl

在BaseAdapter.getView()中保留已创建视图的位置似乎是个问题

在我的例子中,我创建了一个数据对象(-array),它保存了listview的所有数据。列表项有三种类型:分隔符、带有复选框的项和带有可单击图像的项以打开对话框。该数据将由自定义阵列适配器执行,始终使用单独的布局。为此,我使用了不同的取景器。创造不是问题,但如果回收商开始工作,所有的标识/位置都会改变。但我的数据是基于这一点

我知道回收器是如何工作的,但是程序员应该如何保持与自己数据的关系呢

在stackoverflow.com中,有些人问了同样的问题,答案是“覆盖getItemViewType Methode”。没问题,但如果位置总是改变,那就没什么帮助了,对吧

有人有解决办法吗

问候 皮埃尔

以下是我的概念代码证明:

// *** Activity: onCreate()

...
ArrayList<DataObj> data = getData();

    final ListView list = (ListView)findViewById( R.id.listView1 );
    list.setAdapter( new PackedListAdapter( this, data ) );
...

// *** Activity: getData()

private ArrayList<DataObj> getData() {
ArrayList<DataObj> dataArr = new ArrayList<DataObj>();
DataObj dataset;
int i;

dataset = new DataObj();
dataset.setType( DataObj.TYPE_CATEGORY );
dataset.setItemText( "Category CheckItems" );
dataArr.add( dataset );

for ( i = 0; i < 5; i++ ) {
            dataset = new DataObj();
    dataset.setType( DataObj.TYPE_ITEM_CHECK );
    dataset.setItemText( "ItemCheck #" + i );
    dataArr.add( dataset );
}

dataset = new DataObj();
dataset.setType( DataObj.TYPE_CATEGORY );
dataset.setItemText( "Category DialogItems" );
dataArr.add( dataset );

for ( i = 0; i < 5; i++ ) {
     dataset = new DataObj();
    dataset.setType( DataObj.TYPE_ITEM_DLG );
    dataset.setItemText( "ItemDlg #" + i );
    dataArr.add( dataset );
}

return dataArr;
}

// *** Data-Object:

public class DataObj {
private int type = 1;
// further variables here (e.g. String text1 ) ...

public final static int TYPE_CATEGORY = 1;
public final static int TYPE_ITEM_CHECK = 2;
public final static int TYPE_ITEM_DLG = 3;

public void setType( int type ) { this.type = type; }
public int getType() { return type; }

// further setter/getter-methodes for variables here ...
}

// *** BaseAdapter:

public class PackedListAdapter extends BaseAdapter {

private static ArrayList<DataObj> mData;
private LayoutInflater mInflater;

PackedListAdapter( Context context, ArrayList<DataObj> data ) {
    mData = data;
    mInflater = LayoutInflater.from( context );
}

public int getCount() {
    return mData.size();
}

public Object getItem( int position ) {
    return mData.get( position );
}

public long getItemId( int position ) { return position; }

public int getItemViewType( int position ) { 
    return mData.get( position ).getType();
}

public boolean hasStableIds() { return false; }

public int getViewTypeCount() { return 3; }

public View getView( int position, View convertView, ViewGroup parent ) {
    int type = this.getItemViewType( position );

    if ( convertView == null ) {
        switch ( type ) {
            case DataObj.TYPE_CATEGORY:
            {
                convertView = mInflater.inflate( R.layout.listcat, null );
                ViewHolderCat holder = new ViewHolderCat();
                // setting up data from mData(position) here
                convertView.setTag( holder );
                break;
            }
            case DataObj.TYPE_ITEM_CHECK:
            {
                convertView = mInflater.inflate( R.layout.listrow, null );
                ViewHolderItem holder = new ViewHolderItem();
                // setting up data from mData(position) here
                convertView.setTag( holder );
                break;
            }
            case DataObj.TYPE_ITEM_DLG:
            {
                convertView = mInflater.inflate( R.layout.listdlg, null );
                ViewHolderDlg holder = new ViewHolderDlg();
                // setting up data from mData(position) here
                convertView.setTag( holder );
                break;
            }
        }
    } else {
        switch ( type ) {
            case DataObj.TYPE_CATEGORY:
            {
                ViewHolderCat holder = (ViewHolderCat)convertView.getTag();
                // setting up data from mData(position) here
                break;
            }
            case DataObj.TYPE_ITEM_CHECK:
            {
                ViewHolderItem holder = (ViewHolderItem)convertView.getTag();
                // setting up data from mData(position) here
                break;
            }
            case DataObj.TYPE_ITEM_DLG:
            {
                ViewHolderDlg holder = (ViewHolderDlg)convertView.getTag();
                // setting up data from mData(position) here
                break;
            }
        }
    }

    return convertView;
}

public static class ViewHolderCat {
    public TextView txtCat;
}

public static class ViewHolderItem {
    public TextView txtItem;
    public TextView txtDescr;
    public ImageView imgCheckButton;
}

public static class ViewHolderDlg {
    public TextView txtItem;
    public TextView txtDescr;
    public ImageView imgDlgButton;
}

}
/***活动:onCreate()
...
ArrayList data=getData();
最终ListView列表=(ListView)findViewById(R.id.listView1);
setAdapter(新的PackedListAdapter(this,data));
...
//***活动:getData()
私有ArrayList getData(){
ArrayList dataArr=新的ArrayList();
DataObj数据集;
int i;
数据集=新数据对象();
dataset.setType(DataObj.TYPE_类别);
dataset.setItemText(“类别检查项”);
dataArr.add(数据集);
对于(i=0;i<5;i++){
数据集=新数据对象();
dataset.setType(DataObj.TYPE_ITEM_CHECK);
setItemText(“ItemCheck#”+i);
dataArr.add(数据集);
}
数据集=新数据对象();
dataset.setType(DataObj.TYPE_类别);
dataset.setItemText(“类别对话框项”);
dataArr.add(数据集);
对于(i=0;i<5;i++){
数据集=新数据对象();
dataset.setType(DataObj.TYPE\u ITEM\u DLG);
setItemText(“ItemDlg#”+i);
dataArr.add(数据集);
}
返回数据arr;
}
//***数据对象:
公共类数据对象{
私有int类型=1;
//此处还有其他变量(例如字符串text1)。。。
公共最终静态整数类型\类别=1;
公共最终静态整数类型\项目\检查=2;
公共最终静态整数类型\项目\ DLG=3;
public void setType(int-type){this.type=type;}
public int getType(){return type;}
//这里有更多变量的setter/getter方法。。。
}
//***基本适配器:
公共类PackedListAdapter扩展BaseAdapter{
私有静态ArrayList mData;
私人停车场;
PackedListAdapter(上下文、ArrayList数据){
mData=数据;
mInflater=LayoutInflater.from(上下文);
}
public int getCount(){
返回mData.size();
}
公共对象getItem(int位置){
返回mData.get(位置);
}
公共长getItemId(int位置){return position;}
public int getItemViewType(int位置){
返回mData.get(position.getType();
}
公共布尔hasStableIds(){return false;}
public int getViewTypeCount(){return 3;}
公共视图getView(int位置、视图转换视图、视图组父视图){
int type=this.getItemViewType(位置);
if(convertView==null){
开关(类型){
案例数据对象类型\类别:
{
convertView=mInflater.充气(R.layout.listcat,空);
ViewHolderCat holder=新ViewHolderCat();
//在此处设置来自mData(位置)的数据
convertView.setTag(支架);
打破
}
案例数据对象类型项目检查:
{
convertView=mInflater.充气(R.layout.listrow,null);
ViewHolderItem holder=新的ViewHolderItem();
//在此处设置来自mData(位置)的数据
convertView.setTag(支架);
打破
}
案例数据对象类型项目:
{
convertView=mInflater.充气(R.layout.listdlg,null);
ViewHolderDlg holder=新ViewHolderDlg();
//在此处设置来自mData(位置)的数据
convertView.setTag(支架);
打破
}
}
}否则{
开关(类型){
案例数据对象类型\类别:
{
viewHolderCatHolder=(ViewHolderCat)convertView.getTag();
//在此处设置来自mData(位置)的数据
打破
}
案例数据对象类型项目检查:
{
ViewHolderItem holder=(ViewHolderItem)convertView.getTag();
//在此处设置来自mData(位置)的数据
打破
}
案例数据对象类型项目:
{
ViewHolderDlg holder=(ViewHolderDlg)convertView.getTag();
//在此处设置来自mData(位置)的数据
打破
}
}
}
返回视图;
}
公共静态类ViewHolderCat{
公共文本视图txtCat;
}
公共静态类ViewHolderItem{
公共文本视图txtItem;
公共文本视图txtDescr;
公共图像查看imgCheckButton;
}
公共静态类viewHolderDg{
公共文本视图txtItem;
公共文本视图txtDescr;
公共图像查看imgdlg按钮;
}
}
除了和之外,还应重写。这将类似于:

@Override
public boolean hasStableIds() {
    /* the view types for rows will change over time */
    return false;
}

@Override
public int getViewTypeCount() {
    return 3;
}

@Override
public int getItemViewType(int position) {
    /* calculate the view type for this row */
    return ... ;
}

我相信这会让框架知道它不应该基于项目id进行缓存。

我最近尝试创建一个与我的数据集相关的视图本地缓存,但在看了之后,我决定放弃:


如果ListView开发人员建议不要这样做,我觉得我应该听从他们的建议,而不是试图破解它。

解决方案似乎是一个包含更多适配器的BaseAdapter


正如您所提到的,您不能保留视图的位置,因为视图是re-u