Android的ListView的滚动后显示虚假的数据(自定义适配器) [英] android listview displays false data after scrolling (custom adapter)

查看:267
本文介绍了Android的ListView的滚动后显示虚假的数据(自定义适配器)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个奇怪的问题,让我发疯。在我的Andr​​oid应用程序,我定制我自己的适配器,从ArrayAdapter延伸。在ListView的项目,而我加入我的适配器可以被标记文本(不可编辑),可编辑的文本或微调。 疯狂的东西是:当我滚动ListView中,有两个问题:

(1)(选择)的这显示在微调项目的修改有时候虽然我只滚动!当我点击微调,老选定值仍显示(一,应当由微调显示) 在ListViewItems(2)在为了 修改:当我滚动!

=>而在适配器中的数据不会改变(无论是数据本身也没有顺序) - 所以它必须是视图本身的问题?在后台,也许Android的高速缓存,并且不刷新ListViewItems很快向往这样?!

任何人能帮助我吗?

THX了很多!

好吧,我已经找到了解决方案,它是不是很漂亮,但它的工作原理。我根本没有使用convertView了,虽然关于内存和性能是不理想的。在我的情况下,它应该没问题,因为我的ListView的最大项目数量为15。 这是我的适配器级:

 公共类FinAdapter扩展ArrayAdapter<参数> {
    公共参数[] PARAMS;
    私人布尔merkzettel;
    受保护的EditText PV;

    公共FinAdapter(上下文的背景下,INT textViewResourceId,参数[]项目,布尔merkzettel){
        超(背景下,textViewResourceId,项目);
        this.params =项目;
        this.merkzettel = merkzettel;
    }

    @覆盖
    公共查看getView(INT位置,查看convertView,ViewGroup中父){
        最终的参数P = PARAMS [位置]
        如果(P!= NULL){
            如果(merkzettel){
                如果(convertView == NULL){
                    LayoutInflater VI =(LayoutInflater)的getContext()getSystemService(Context.LAYOUT_INFLATER_SERVICE)。
                    convertView = vi.inflate(R.layout.merk_det_item,NULL);
                }
                TextView的TVL =(TextView中)convertView.findViewById(R.id.paramM);
                TextView的EDL =(TextView中)convertView.findViewById(R.id.param_valueM);
                TextView的PAL =(TextView中)convertView.findViewById(R.id.param_unitM);
                如果(TVL!= NULL){
                    tvl.setText(p.getName());
                }
                如果(PAL!= NULL){
                    pal.setText(p.getUnit());
                }
                如果(EDL!= NULL){
                    edl.setText(p.getDefData());
                }
            }
            其他{
                如果(p.isSelect()){

                如果(convertView == NULL){
                    LayoutInflater VI =(LayoutInflater)的getContext()getSystemService(Context.LAYOUT_INFLATER_SERVICE)。
                    convertView = vi.inflate(R.layout.fin_prod_list_item_select,NULL);
                }
                TextView的电视=(TextView中)convertView.findViewById(R.id.paramS);
                微调SP =(微调)convertView.findViewById(R.id.spinner_kalk);
                TextView的PAU =(TextView中)convertView.findViewById(R.id.param_unitS);


                如果(电视!= NULL){
                    tvs.setText(p.getName());
                }
                如果(PAU!= NULL){
                    paU.setText(p.getUnit());
                }
                如果(SP!= NULL){
                    的String []值=新的String [p.getData()的大小()];
                    的for(int i = 0; I< values​​.length;我++){
                        值[I] = p.getData()得到(一)。
                    }
                    ArrayAdapter<字符串>适配器=新的ArrayAdapter<字符串>(this.getContext(),android.R.layout.simple_spinner_item,价值观);
                    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                    sp.setAdapter(适配器);
                    sp.setSelection(p.getData()的indexOf(p.getDefData())。);
                    sp.setOnItemSelectedListener(新OnItemSelectedListener(){
                        公共无效onItemSelected(适配器视图<>父,
                                查看convertView,INT POS,长I​​D){
                            p.setDefData(p.getData()得到(POS));
                            p.setChanged(真正的);
                        }
                        公共无效onNothingSelected(适配器视图<>为arg0){
                            // TODO自动生成方法存根

                        }

                    });
                }
            }
            否则如果(p.isEdit()){
                如果(convertView == NULL){
                    LayoutInflater VI =(LayoutInflater)的getContext()getSystemService(Context.LAYOUT_INFLATER_SERVICE)。
                    convertView = vi.inflate(R.layout.fin_prod_list_item_edit,NULL);
                }
                TextView的PA =(TextView中)convertView.findViewById(R.id.param);
                PV =(EditText上)convertView.findViewById(R.id.param_value);
                TextView的PAE =(TextView中)convertView.findViewById(R.id.param_unit);
                如果(PA!= NULL){
                    pa.setText(p.getName());
                }
                如果(PAE!= NULL){
                    paE.setText(p.getUnit());
                }
                如果(PV!= NULL){
                    pv.setText(p.getDefData());
                    pv.setOnEditorActionListener(新OnEditorActionListener(){
                        公共布尔onEditorAction(TextView的convertView,诠释actionId,
                                KeyEvent的事件){
                            // TODO自动生成方法存根
                            p.setDefData(pv.getText()的toString());
                            p.setChanged(真正的);
                            返回false;
                        }
                    });
                }

            }
            否则如果(p.isLabel()){
                如果(convertView == NULL){
                    LayoutInflater VI =(LayoutInflater)的getContext()getSystemService(Context.LAYOUT_INFLATER_SERVICE)。
                    convertView = vi.inflate(R.layout.fin_prod_list_item_label,NULL);
                }
                TextView的TVL =(TextView中)convertView.findViewById(R.id.paramL);
                TextView的EDL =(TextView中)convertView.findViewById(R.id.param_valueL);
                TextView的PAL =(TextView中)convertView.findViewById(R.id.param_unitL);
                如果(TVL!= NULL){
                    tvl.setText(p.getName());
                }
                如果(PAL!= NULL){
                    pal.setText(p.getUnit());
                }
                如果(EDL!= NULL){
                    edl.setText(p.getDefData());
                }
            }}
        }
        返回convertView;
    }
}
 

解决方案

我也有类似的问题,多种项目类型列表中。在我的情况下列表项是任何一个部分(标签)项目或一个共同的列表项。

要与这样类型的列表工作,你应该重写 getViewTypeCount getItemViewType 的方法。 事情是这样的:

 私有静态最终诠释ITEM_VIEW_TYPE_ITEM = 0;
私有静态最终诠释ITEM_VIEW_TYPE_SEPARATOR = 1;

@覆盖
公众诠释getViewTypeCount(){
    返回2;
}

@覆盖
公众诠释getItemViewType(INT位置){
    返回this.getItem(位置).isSection()? ITEM_VIEW_TYPE_SEPARATOR:ITEM_VIEW_TYPE_ITEM;
}

@覆盖
公共查看getView(INT位置,查看convertView,ViewGroup中父){
    最后一个项目的项目= this.getItem(位置);

    如果(convertView == NULL){
        convertView = mInflater.inflate(item.isSection()R.view1:R.view2,NULL);
    }

    如果(item.isSection()){
        // ...
    }
    其他{
        // ...
    }

    返回convertView;
}
 

那么convertView参数永远是正确的,包含的类型,你所需要的。

和另一件事:你明确添加了公共参数[] PARAMS 字段,当你已经拥有它在基类中 ArrayAdapter<参数>

我会建议从 BaseAdapter 类继承。

编辑: 这里是code,你可以尝试使用,从而使你的微调工作

  sp.setTag(P);
sp.setOnItemSelectedListener(新OnItemSelectedListener(){
公共无效onItemSelected(适配器视图<>母公司,查看convertView,INT POS,长I​​D){
    参数currentItem =(参数)parent.getTag();
    currentItem.setDefData(currentItem.getData()得到(POS));
    currentItem.setChanged(真正的);
}
// ...
 

尝试使用的 getTag setTag 相结合的方法。我记得我有类似的问题,事件处理程序和最终的变量,但我完全忘记了他们的事业,所以我无法解释到底为什么发生这种情况。

I've got a strange problem that drives me crazy. In my android application I customized my own adapter that extends from ArrayAdapter. The items of the ListView to which I added my adapter can either be labeled-text (not editable), editable text or a spinner. The crazy stuff is: when I scroll the ListView, there are two problems:

(1) the (selected) value that is shown in the spinner items changes sometimes although I only scrolled!! when I click on the spinner, the old selected value is still shown (the one, that should be shown by the spinner) (2) the order of the ListViewItems changes when I scroll!

=> BUT the data in the adapter doesn't change (neither the data itself nor the order) - so it must be a problem of the View itself?! maybe android caches in background and doesn't refresh the ListViewItems soon enough or sth like that?!

Can anybody help me please?

Thx a lot!

Ok, I have found a solution that is not very nice, but it works. I simply did not use convertView anymore although that is suboptimal regarding to memory and performance. In my case it should be ok because my ListView's maximal amount of items is 15. Here is my Adapter-Class:

 public class FinAdapter extends ArrayAdapter<Param>{
    public Param[] params;
    private boolean merkzettel;
    protected EditText pv;

    public FinAdapter(Context context, int textViewResourceId, Param[] items, boolean merkzettel) {
        super(context, textViewResourceId, items);
        this.params = items;
        this.merkzettel = merkzettel;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final Param p = params[position];
        if(p != null){
            if(merkzettel){
                if (convertView == null) {
                    LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    convertView = vi.inflate(R.layout.merk_det_item, null);
                }
                TextView tvl = (TextView) convertView.findViewById(R.id.paramM);
                TextView edl = (TextView) convertView.findViewById(R.id.param_valueM);
                TextView pal = (TextView) convertView.findViewById(R.id.param_unitM);
                if (tvl != null) {
                    tvl.setText(p.getName());                            
                }
                if(pal != null){
                    pal.setText(p.getUnit());
                }
                if(edl != null){
                    edl.setText(p.getDefData());
                }
            }
            else{
                if(p.isSelect()){

                if (convertView == null) {
                    LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    convertView = vi.inflate(R.layout.fin_prod_list_item_select, null);
                }            
                TextView tvs = (TextView) convertView.findViewById(R.id.paramS);
                Spinner sp = (Spinner) convertView.findViewById(R.id.spinner_kalk);
                TextView paU = (TextView) convertView.findViewById(R.id.param_unitS);


                if (tvs != null) {
                    tvs.setText(p.getName());                            
                }
                if(paU != null){
                    paU.setText(p.getUnit());
                }
                if(sp != null){
                    String[] values = new String[p.getData().size()];
                    for(int i=0; i<values.length; i++){
                        values[i] = p.getData().get(i);
                    }
                    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this.getContext(), android.R.layout.simple_spinner_item, values);
                    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                    sp.setAdapter(adapter);
                    sp.setSelection(p.getData().indexOf(p.getDefData()));
                    sp.setOnItemSelectedListener(new OnItemSelectedListener(){
                        public void onItemSelected(AdapterView<?> parent,
                                View convertView, int pos, long id) {
                            p.setDefData(p.getData().get(pos));
                            p.setChanged(true);
                        }
                        public void onNothingSelected(AdapterView<?> arg0) {
                            // TODO Auto-generated method stub

                        }

                    });
                }
            }       
            else if(p.isEdit()){
                if (convertView == null) {
                    LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    convertView = vi.inflate(R.layout.fin_prod_list_item_edit, null);
                }
                TextView pa = (TextView) convertView.findViewById(R.id.param);
                pv = (EditText) convertView.findViewById(R.id.param_value);
                TextView paE = (TextView) convertView.findViewById(R.id.param_unit);
                if (pa != null) {
                    pa.setText(p.getName());                            
                }
                if(paE != null){
                    paE.setText(p.getUnit());
                }
                if(pv != null){
                    pv.setText(p.getDefData());
                    pv.setOnEditorActionListener(new OnEditorActionListener(){
                        public boolean onEditorAction(TextView convertView, int actionId,
                                KeyEvent event) {
                            // TODO Auto-generated method stub
                            p.setDefData(pv.getText().toString());
                            p.setChanged(true);
                            return false;
                        }                   
                    }); 
                }

            }
            else if(p.isLabel()){
                if (convertView == null) {
                    LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    convertView = vi.inflate(R.layout.fin_prod_list_item_label, null);
                }
                TextView tvl = (TextView) convertView.findViewById(R.id.paramL);
                TextView edl = (TextView) convertView.findViewById(R.id.param_valueL);
                TextView pal = (TextView) convertView.findViewById(R.id.param_unitL);
                if (tvl != null) {
                    tvl.setText(p.getName());                            
                }
                if(pal != null){
                    pal.setText(p.getUnit());
                }
                if(edl != null){
                    edl.setText(p.getDefData());
                }   
            }}
        }
        return convertView;
    }
}

解决方案

I had a similar problem with multiple item types in the list. In my case the list item was either a section (label) item or a common list item.

To work with such types of lists, you should override getViewTypeCount and getItemViewType methods. Something like this:

private static final int ITEM_VIEW_TYPE_ITEM = 0;
private static final int ITEM_VIEW_TYPE_SEPARATOR = 1;

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

@Override
public int getItemViewType(int position) {
    return this.getItem(position).isSection() ? ITEM_VIEW_TYPE_SEPARATOR : ITEM_VIEW_TYPE_ITEM;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final Item item = this.getItem(position);

    if (convertView == null) {
        convertView = mInflater.inflate(item.isSection() ? R.view1 : R.view2, null);
    }

    if(item.isSection()){
        //...
    }
    else{
        //...
    }

    return convertView;
}

Then the convertView parameter will always be correct and contain that type which you need.

And another thing: you explicitly added the public Param[] params field when you already have it in the base class ArrayAdapter<Param>.

I would recommend to inherit from the BaseAdapter class.

Edit: Here is the code which you can try to use in order to make your Spinner work:

sp.setTag(p);
sp.setOnItemSelectedListener(new OnItemSelectedListener(){
public void onItemSelected(AdapterView<?> parent, View convertView, int pos, long id) {
    Param currentItem = (Param)parent.getTag();
    currentItem.setDefData(currentItem.getData().get(pos));
    currentItem.setChanged(true);
}
//...

Try to use the combination of the getTag and setTag methods. I remember that I had similar problems with event handlers and final variables, but I completely forgot the cause of them, so I can't explain exactly why this happens.

这篇关于Android的ListView的滚动后显示虚假的数据(自定义适配器)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆