Android 当我向listView添加新项时,getVIew的convertView==null表示已经存在的项

Android 当我向listView添加新项时,getVIew的convertView==null表示已经存在的项,android,listview,Android,Listview,我正在尝试动态地在ListView中添加项目。当我第一次这样做时(所以列表是空的),getView()工作得很好,convertView是null,就像它应该的那样,所以我可以使用ViewHolder来存储对项目视图的引用,并通过setTag()将其绑定到视图。但是当我向列表中添加第二项数据并调用notifyOnDataSetChanged()时,人们注意到了非常奇怪的行为 基本上,notifyOnDataSetChanged()会重新绘制所有可见项,并从第一个可见项开始。问题是,当重画第一个项

我正在尝试动态地在
ListView
中添加项目。当我第一次这样做时(所以列表是空的),
getView()
工作得很好,convertView是
null
,就像它应该的那样,所以我可以使用
ViewHolder
来存储对项目视图的引用,并通过setTag()将其绑定到视图。但是当我向列表中添加第二项数据并调用
notifyOnDataSetChanged()
时,人们注意到了非常奇怪的行为

基本上,
notifyOnDataSetChanged()
会重新绘制所有可见项,并从第一个可见项开始。问题是,当重画第一个项目(之前已经绘制过)时,convertView==null,因此我需要为它膨胀新视图,并使用
findViewById()
查找我之前已经找到并存储在ViewHolder中的所有引用。对于第二个项目,我收到的convertView引用了第一个项目,因此我需要为第二个项目找到它。我想要的是为第一个项目获取之前创建的视图(并且在其ViewHolder中包含所有引用),并为第二个项目创建新的视图,即在绘制我刚刚添加的项目时,让convertView==null。有办法吗

编辑1:添加新项目:

alarmClocksList.add(新的AlarmClock(时间、歌曲标题、工作日可视、工作日子));
alarmsArrayAdapter.notifyDataSetChanged();

阵列适配器:

package com.example;

import android.content.Context;
import android.content.Intent;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.ArrayList;

public class AlarmsArrayAdapter extends ArrayAdapter {

    ArrayList<AlarmClock> alarmClockArrayList;
    private Context context;

    static class ViewHolder {
        TextView time;
        TextView songTitle;
        TextView nextRingTime;
        CheckBox repeatCheckBox;
        RelativeLayout repeatPanel;
        WeekDayCheckBox monday;
        WeekDayCheckBox tuesday;
        WeekDayCheckBox wednesday;
        WeekDayCheckBox thursday;
        WeekDayCheckBox friday;
        WeekDayCheckBox saturday;
        WeekDayCheckBox sunday;
    }

    public AlarmsArrayAdapter(Context context, ArrayList<AlarmClock> alarmClocks) {
        super(context, -1, alarmClocks);
        alarmClockArrayList = alarmClocks;
        this.context = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.alarm_clock_item, parent, false);

            holder = new ViewHolder();

            holder.time = (TextView) convertView.findViewById(R.id.alarmClockTime);
            holder.songTitle = (TextView) convertView.findViewById(R.id.alarmClockSong);
            holder.nextRingTime = (TextView) convertView.findViewById(R.id.nextRindDay);
            holder.repeatCheckBox = (CheckBox) convertView.findViewById(R.id.repeatCheckBox);

            holder.repeatPanel = (RelativeLayout) convertView.findViewById(R.id.repeatPanel);

            holder.monday = (WeekDayCheckBox) convertView.findViewById(R.id.MO);
            holder.tuesday = (WeekDayCheckBox) convertView.findViewById(R.id.TU);
            holder.wednesday = (WeekDayCheckBox) convertView.findViewById(R.id.WE);
            holder.thursday = (WeekDayCheckBox) convertView.findViewById(R.id.TH);
            holder.friday = (WeekDayCheckBox) convertView.findViewById(R.id.FR);
            holder.saturday = (WeekDayCheckBox) convertView.findViewById(R.id.SA);
            holder.sunday = (WeekDayCheckBox) convertView.findViewById(R.id.SU);

            holder.songTitle.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                }
            });

            holder.time.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(context, TimePickerActivity.class);
                    ((FragmentActivity) context).startActivityForResult(intent, MainActivity.TIME_PICK_REQUEST);
                }
            });

            holder.repeatCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if (!isChecked) {
                        holder.repeatPanel.setVisibility(View.GONE);
                    } else {
                        holder.repeatPanel.setVisibility(View.VISIBLE);
                    }
                }
            });
            convertView.setTag(holder);
        } else
            holder = (ViewHolder) convertView.getTag();

        AlarmClock alarmClock = alarmClockArrayList.get(position);
        holder.time.setText(alarmClock.time);
        holder.songTitle.setText(alarmClock.songTitle);
        holder.nextRingTime.setText("No data");
        return convertView;
    }
}
package.com.example;
导入android.content.Context;
导入android.content.Intent;
导入android.support.v4.app.FragmentActivity;
导入android.util.Log;
导入android.view.LayoutInflater;
导入android.view.view;
导入android.view.ViewGroup;
导入android.widget.ArrayAdapter;
导入android.widget.CheckBox;
导入android.widget.CompoundButton;
导入android.widget.RelativeLayout;
导入android.widget.TextView;
导入java.util.ArrayList;
公共类AlarmsArrayAdapter扩展ArrayAdapter{
ArrayList alarmClockArrayList;
私人语境;
静态类视窗夹{
文本查看时间;
文本视图歌曲标题;
TextView下一个tringtime;
复选框重复复选框;
相对性重复面板;
平日和星期一;
平日及星期二;;
平日星期三;
平日及星期四;;
平日,星期五;;
平日及星期六;;
周日;
}
公共AlarmsArrayAdapter(上下文上下文,ArrayList alarmClocks){
超级(上下文,-1,报警时钟);
alarmClockArrayList=alarmClocks;
this.context=上下文;
}
@凌驾
公共视图getView(int位置、视图转换视图、视图组父视图){
最终持票人;
if(convertView==null){
LayoutFlater充气器=(LayoutFlater)context.getSystemService(context.LAYOUT\u充气器\u服务);
convertView=充气机。充气(R.layout.alarm\u clock\u项目,父项,false);
holder=新的ViewHolder();
holder.time=(TextView)convertView.findViewById(R.id.alarmClockTime);
holder.songTitle=(TextView)convertView.findViewById(R.id.alarmClockSong);
holder.nextRingTime=(TextView)convertView.findViewById(R.id.nextRindDay);
holder.repeatCheckBox=(复选框)convertView.findViewById(R.id.repeatCheckBox);
holder.repeatPanel=(RelativeLayout)convertView.findViewById(R.id.repeatPanel);
holder.monday=(WeekDayCheckBox)convertView.findViewById(R.id.MO);
holder.tuday=(WeekDayCheckBox)convertView.findViewById(R.id.TU);
holder.周三=(WeekDayCheckBox)convertView.findViewById(R.id.WE);
holder.星期四=(WeekDayCheckBox)convertView.findViewById(R.id.TH);
holder.friday=(WeekDayCheckBox)convertView.findViewById(R.id.FR);
holder.saturday=(WeekDayCheckBox)convertView.findViewById(R.id.SA);
holder.sunday=(WeekDayCheckBox)convertView.findViewById(R.id.SU);
holder.songTitle.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
}
});
holder.time.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
意向意向=新意向(上下文、TimePickerActivity.class);
((FragmentActivity)context).startActivityForResult(intent,MainActivity.TIME\u PICK\u REQUEST);
}
});
holder.repeatCheckBox.setOnCheckedChangeListener(新建CompoundButton.OnCheckedChangeListener()){
@凌驾
检查更改后的公共无效(复合按钮视图,布尔值已检查){
如果(!已检查){
支架.重复面板.设置可见性(视图.消失);
}否则{
支架.repeatPanel.setVisibility(视图.可见);
}
}
});
convertView.setTag(支架);
}否则
holder=(ViewHolder)convertView.getTag();
AlarmClock AlarmClock=alarmClockArrayList.get(位置);
holder.time.setText(alarmClock.time);
holder.songTitle.setText(alarmClock.songTitle);
holder.nextRingTime.setText(“无数据”);
返回视图;
}
}

您应该使用Recyclerview来支持ListView。使用Recyclerview,可以更精确地将数据数组中的更改发布到GUI,例如
Recyclerview.Adapter.notifyItemInserted
Recyclerview.Adapter.notifyItemChanged

您试图实现的基本目标是优化
ListView
s缓存解决方案,这是您不能也不应该实现的