ListView의 체크박스 정렬 문제 해결


이 섹션 소개:

ListView의 고전적인 문제 중 하나로서, 체크박스를 사용하여 ListView 항목을 사용자 정의하려고 시도한 경우 이 문제는 항목 수가 한 페이지를 초과할 때 발생합니다. 이 문제의 원인과 해결 방법을 분석해 보겠습니다. 이 문제를 해결해보세요!


1 문제의 원인:

이것은 인터넷에서 발견된 ListView getView 메서드 호출 메커니즘에 대한 그림입니다.

1.jpg

위 그림에는 Recycler 항목이 있습니다. 일반적으로 ListView는 표시되는 항목은 메모리에 있으며 해당 항목은 다음 위치에 배치됩니다. 이 Recycler에서는 항목이 처음 로드될 때 현재 페이지의 ConvertView가 NULL입니다. 화면 밖으로 스크롤할 때 이번에는 ConvertView가 비어 있지 않으므로 새 항목은 이 ConvertView를 재사용합니다! 간단한 예제를 작성하고 로그를 따라갈 수 있습니다. 실행 후 로그 다이어그램은 다음과 같습니다.

2.png

그림에서 볼 수 있듯이 12번째 위치부터 ConvertView는 더 이상 비어 있지 않습니다. 정확히 무엇을 의미하나요? 모르겠습니다. 소스 코드를 시각적으로 검토해야 합니다... 우리는 이러한 이유로 ConvertView가 여기에 캐시된다는 것을 알고 있습니다. 확인란이 잘못 정렬되었으므로 첫 번째 해결 방법은 이 ConvertView를 재사용하지 않는 것입니다. getView가 이 ConvertView를 null로 설정할 때마다 표시해야 하는 Item의 수가 많다면, 이 방법은 매우 비대해 보일 것입니다. 일반적으로 실제 개발에서는 다음 솔루션을 사용합니다. 현재 항목 CheckBox의 상태를 저장할 항목을 찾고, 선택 여부를 초기화 중에 판단합니다!


2. 해결 방법:

이 체크박스를 HashMap<Integer, Boolean>에 저장할 수 있는 좋은 방법이 많이 있습니다. 각 초기화 중에 위치에 따라 해당 부울 값이 제거되고 확인란 상태가 설정됩니다. 저자의 접근 방식은 판단을 위해 엔터티 클래스에 부울 값을 추가하는 것입니다. 다음은 저자의 프로젝트 중 하나입니다. 추출된 코드는 비교적 간단하므로 몇 초 안에 이해하실 수 있을 거라 믿습니다~

Entity 클래스: Person.java:

public class Person은 직렬화 가능{
    private String name;
    private String number;
    private boolean checkStatus;
    
    public Person(String name, String number) {
        super();
        this.name = name;
        이. number = number;
        this.checkStatus = false;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    공개 문자열 getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public boolean getCheckStatus() {
        return checkStatus;
    }

    public void setCheckStatus(boolean checkStatus) {
        this.checkStatus = checkStatus;
    }
    
}

구현된 어댑터 클래스: ContactListAdapter.java:

public 클래스 ContactListAdapter는 BaseAdapter를 확장하여 CompoundButton.OnCheckedChangeListener{

    private List<Person>을 구현합니다. mData;
    private Context mContext;

    public ContactListAdapter(List<Person> data, Context context) {
        mData = data;
        mContext = context;
    }

    / / 정확한 个刷 새로운 방식의 방법
    public void changeData(List< ;사람>  데이터) {
        mData = data;
        notifyDataSetChanged();
    }

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

    @Override
    public Person getItem(int position) ) {{return mdata.get (position);
}@override
public long getItemid (int position) {

리턴 위치;
}@atriade} public getView (int position, view convertView, viewGroup Parent) {
        최종 int 색인 = position;
        ViewHolder viewHolder;
        if (convertView == null) {
           convertView = LayoutInflater.from(mContext).inflate(
                    R.layout.item_contact, parent, false);
            viewHolder = 새 ViewHolder ();
           viewHolder.ly = (RelativeLayout) convertView
                  .findViewById(R.id.lyContactListItem);
            viewHolder.txtName = (TextView) convertView
                   .findViewById(R.id.txtName);
           viewHolder.txtNumber = (TextView) convertView
                   .findView ById(R.id.txtNumber);
            viewHolder.cbxStatus = (CheckBox) convertView
                  . findViewById(R.id.cbxStatus);
            convertView.setTag(viewHolder);
           viewHolder.cbxStatus.setTag(index);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        viewHolder.cbxStatus. setOnCheckedChangeListener(this);
        viewHolder.cbxStatus.setChecked(mData.get(position).getcheckStatus());
        viewHolder.txtName.setText(mData.get(index).getName());
        viewHolder.txtNumber.setText( mData.get(index).getNumber());
        return convertView;
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        int index =(int)buttonView.getT ag();
        만약 ( isChecked)
           mData.get(index).setCheckStatus(true);
        else
            mData.get(index).setCheckStatus(false);
    }


    비공개 클래스 ViewHolder {
        RelativeLayout ly;
        TextView txtName;
        TextView txtNumber ;
        CheckBox cbxStatus;
}
}

아주 간단합니다. 한 가지 더 잊지 마세요. 체크박스 상태를 초기화하는 코드 앞에 체크박스 리스너 메서드를 추가해야 합니다~


이 섹션 소개:

알겠습니다. , 이 섹션에서는 ListView의 전형적인 문제를 설명하겠습니다. ListView의 확인란이 잘못되었습니다. 체크박스 선택 상태를 기록하는 값을 추가한 후 체크박스를 다시 작성하면 문제가 해결됩니다. 이벤트 클릭시 판단을 먼저 해주세요~감사합니다~