Android notifyDatasetChanged刷新的奇怪行为 背景

Android notifyDatasetChanged刷新的奇怪行为 背景,android,Android,您好,我是Android新手,正在尝试熟悉ListView。所以我决定编写一个简单的程序,让用户输入引号并按顺序显示它们。我实现了一个StringAdapter,并在每次用户确认时调用notifyDataSetChanged 问题: 奇怪的是,ListView有时会更新最旧的引号,有时更新最新的引号。我不知道问题出在哪里 请忽略查看数据按钮。在此状态下,我输入了四个引号: 引言:嗨-签名:威廉·莎士比亚 引言:你好-签名:威廉·莎士比亚 格言:美德是勇敢的,善良是永不畏惧的。-签名:威廉·莎士

您好,我是Android新手,正在尝试熟悉
ListView
。所以我决定编写一个简单的程序,让用户输入引号并按顺序显示它们。我实现了一个
StringAdapter
,并在每次用户确认时调用
notifyDataSetChanged

问题: 奇怪的是,
ListView
有时会更新最旧的引号,有时更新最新的引号。我不知道问题出在哪里

请忽略查看数据按钮。在此状态下,我输入了四个引号:

  • 引言:嗨-签名:威廉·莎士比亚
  • 引言:你好-签名:威廉·莎士比亚
  • 格言:美德是勇敢的,善良是永不畏惧的。-签名:威廉·莎士比亚
  • 格言:爱所有人,信任少数人,不伤害任何人签名:威廉·莎士比亚
  • (按相反顺序,意思是按时间顺序,它是4,3,2,1)

    代码 主要活动
    公共类存储扩展了AppCompatActivity{
    //适配器
    私家车;
    //编辑文本视图
    公共编辑文本etString,etSignature;
    //列表视图
    公共列表视图lv;
    //用于捕获引号和签名的数组列表
    private ArrayList dataString=new ArrayList();
    //添加字符串并通知
    public void addString(字符串[]s){
    this.dataString.add(0,s);
    ((BaseAdapter)this.lv.getAdapter()).notifyDataSetChanged();
    }
    @凌驾
    创建时受保护的void(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity\u存储);
    //链接视图元素
    this.etString=(EditText)findViewById(R.id.etInput);
    this.etSignature=(EditText)findViewById(R.id.etSignature);
    this.lv=(ListView)findViewById(R.id.stringList);
    按钮btn_确认=(按钮)查找视图id(R.id.btn确认),
    btn_viewData=(按钮)findViewById(R.id.btnViewData);
    //加载适配器
    this.sa=新的StringAdapter(this,this.dataString);
    低压设置适配器(sa);
    btn_confirm.setOnClickListener(新视图.OnClickListener(){
    @凌驾
    公共void onClick(视图v){
    存储s=(存储)v.getContext();
    //获取字符串
    字符串sString=s.etString.getText().toString(),
    sSignature=s.etSignature.getText().toString();
    System.out.println(“引号:+sString+”\n签名:+sSignature);
    //确认它不是空的
    如果(!sString.isEmpty()&&!sSignature.isEmpty()){
    //添加新字符串并通知
    s、 addString(新字符串[]{s.etString.getText().toString(),
    s、 etSignature.getText().toString()});
    ((StringAdapter)s.lv.getAdapter()).print_stringData();
    //提示结果
    Toast.makeText(s.getBaseContext(),
    输入“+etSignature.getText().toString()、Toast.LENGTH_SHORT.show()中的引号;
    }否则{
    //提示结果
    Toast.makeText(s.getBaseContext(),
    “请输入引号和签名!”,Toast.LENGTH_SHORT.show();
    }
    }
    });
    }
    }
    
    字符串适配器
    公共类StringAdapter扩展了BaseAdapter{
    私有上下文;
    私有ArrayList数据字符串=新ArrayList();
    publicstringadapter(Context c,arraylistdatastrings){this.mContext=c;this.dataStrings=dataStrings;}
    public int getCount(){返回this.dataStrings.size();}
    公共对象getItem(int-position){返回this.dataStrings.get(position);}
    public long getItemId(int position){return(long)position;}
    public void print_stringData(){
    System.out.println(“字符串适配器输出:”);
    对于(字符串[]s:this.dataStrings){
    System.out.println(“引号:+s[0]+”\n签名:+s[1]);
    }
    }
    公共视图getView(int位置、视图转换视图、视图组父视图){
    线性布局;
    if(convertView==null){
    //设置线性布局
    ll=新的线性布局(this.mContext);
    ll.设置方向(线性布局、垂直);
    ll.setLayoutParams(新的ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_父对象,
    ViewGroup.LayoutParams.WRAP_CONTENT);
    //获取数据并在其中设置文本
    String[]data=this.dataStrings.get(位置);
    TextView//tvNo=新的TextView(this.mContext),
    tvString=新文本视图(this.mContext),
    tvSignature=新文本视图(this.mContext);
    ll.addView(tvString);
    ll.addView(tvSignature);
    tvString.setText(数据[0]);
    tvString.setLayoutParams(新的LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_父级,
    LinearLayout.LayoutParams.WRAP_内容);
    tvSignature.setText(数据[1]);
    tvSignature.setLayoutParams(新的LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_父级,
    LinearLayout.LayoutParams.WRAP_内容);
    tvSignature.setGravity(Gravity.RIGHT);
    }
    否则{
    ll=(线性布局)转换视图;
    }
    返回ll;
    }
    }
    
    评论 有些人可能会注意到,我总是将
    字符串[]
    添加到第一个元素中。事实上,我已经尝试添加到最后一个。这种奇怪的行为仍然存在

    环境 Android SDK版本:API 23棒棒糖


    Emulator版本:Nexus S API 23

    是的,当然,您会遇到该错误。为什么?因为
    ListView
    总是在
    Adapter
    getView
    函数中重复使用
    convertView

    查看您的
    if,else

    else{
        ll = (LinearLayout) convertView;
    }
    return ll;
    
    在这
    public class StringAdapter extends BaseAdapter {
        private Context mContext;
    
        private ArrayList<String[]> dataStrings = new ArrayList<String[]>();
    
        public StringAdapter(Context c,ArrayList<String[]> dataStrings){this.mContext=c;this.dataStrings=dataStrings;}
    
        public int getCount(){return this.dataStrings.size();}
    
        public Object getItem(int position){ return this.dataStrings.get(position);}
    
        public long getItemId(int postion){ return (long) postion;}
    
        public void print_stringData(){
            System.out.println("String Adapter Output:");
            for(String [] s: this.dataStrings){
                System.out.println("Quotes: "+s[0]+"\nSignature:"+s[1]);
            }
        }
    
        public View getView(int position, View convertView, ViewGroup parent){
            LinearLayout ll;
            if(convertView == null){
                // set the linear layout
                ll = new LinearLayout(this.mContext);
                ll.setOrientation(LinearLayout.VERTICAL);
                ll.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT));
    
                // get the data and set the text inside
                String[] data = this.dataStrings.get(position);
                TextView //tvNo = new TextView(this.mContext),
                        tvString = new TextView(this.mContext),
                        tvSignature = new TextView(this.mContext);
                ll.addView(tvString);
                ll.addView(tvSignature);
    
    
                tvString.setText(data[0]);
                tvString.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.WRAP_CONTENT));
    
                tvSignature.setText(data[1]);
                tvSignature.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.WRAP_CONTENT));
                tvSignature.setGravity(Gravity.RIGHT);
            }
            else{
                ll = (LinearLayout) convertView;
            }
            return ll;
        }
    }
    
    else{
        ll = (LinearLayout) convertView;
    }
    return ll;