ListView 범용 범용 어댑터

우리 가 전에 말 한 ListView 를 기억 하 십 니까?(이 어 려 운 컨트롤-.+)우 리 는 그 를 사용 하 는 동시에 어댑터 어댑터 라 는 것 도 사용 했다.일반적으로 우 리 는 하나의 클래스 로 BaseAdapter 를 계승 하여 데이터 와 컨트롤 의 적합 을 진행 합 니 다.
그러나 우리 의 모든 어댑터 는 하나의 데이터 소스 와 하나의 구 조 를 맞 추기 위해 서 일 뿐 입 니 다.만약 에 적 게 사용 하면 괜 찮 습 니 다.만약 에 십 여 가 지 를 사용 하려 면 우 리 는 십 여 개의 어댑터 를 써 야 합 니까?이 생각 은 정말 너무 어리석다!
어댑터 작성 법 이 있 습 니 다.어댑터 와 다양한 유형의 데이터 와 구 조 를 조합 할 수 있 습 니 다.이 물건 은 유 니 버 설 어댑터 라 고 합 니 다.
쓰기 전에 사용 한 BaseAdapter 어댑터 를 기억 해 봅 시다.
우 리 는 BaseAdapter 를 계승 하여 그의 네 가지 방법 을 실현 했다.getCount,getPosition,getItem,getView.그 중에서 가장 쓰기 어 려 운 것 은 getView 이다.그리고 우 리 는 그 를 최적화 시 켰 다.View Holder 라 는 종 류 를 써 서 그 안에 해당 하 는 컨트롤 을 넣 었 다.
이제 유 니 버 설 어댑터 와 일반 어댑터 의 차이 점 과 공통점 을 말씀 드 리 겠 습 니 다.

다음은 유 니 버 설 어댑터 의 작성 방법 을 본 격 적 으로 살 펴 보 겠 습 니 다.
1.오늘 우리 가 필요 로 하 는 컨트롤,소스 데이터,Bean 클래스 를 만 듭 니 다.
컨트롤 이 하나 밖 에 없어 요.ListView.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".activities.MainActivity">
  <ListView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/mlv"/>
</LinearLayout>
beans 방법 은 가짜 데 이 터 를 모 의 했다.

private void beans() {
  list = new ArrayList<>();
  for (int i = 0; i < 16; i += 4) {
    list.add(new Student("  " + i, " ", 15 + i, R.drawable.a, true));
    list.add(new Student("  " + (i + 1), " ", 15 + i, R.drawable.b, false));
    list.add(new Student("  " + (i + 2), " ", 15 + i, R.drawable.c, false));
    list.add(new Student("  " + (i + 3), " ", 15 + i, R.drawable.d, true));
  }
}
이것 은 bean 류 입 니 다.

package zy.pers.homework_20.bean;
public class Student {
  private String name;
  private String sex;
  private int age;
  private int imgId;
  private boolean isOver;
  public Student(String name, String sex, int age, int imgId,boolean isOver) {
    this.name = name;
    this.sex = sex;
    this.age = age;
    this.imgId = imgId;
    this.isOver = isOver;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getSex() {
    return sex;
  }
  public void setSex(String sex) {
    this.sex = sex;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
  public int getImgId() {
    return imgId;
  }
  public void setImgId(int imgId) {
    this.imgId = imgId;
  }
  @Override
  public String toString() {
    return "Student{" +
        "name='" + name + '\'' +
        ", sex='" + sex + '\'' +
        ", age=" + age +
        ", imgId=" + imgId +
        '}';
  }
  public boolean isOver() {
    return isOver;
  }
  public void setOver(boolean over) {
    isOver = over;
  }
}
2.MyBaseAdapter 계승 BaseAdapter 만 들 기

public class MyBaseAdapter<T> extends BaseAdapter {
  @Override
  public int getCount() {
    return 0;
  }
  @Override
  public Object getItem(int position) {
    return null;
  }
  @Override
  public long getItemId(int position) {
    return 0;
  }
  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    return null;
  }
}
3.유 니 버 설 어댑터 가 레이아웃 id 와 소스 데 이 터 를 전송 한다 고 말 하기 때문에 우 리 는 이 두 개의 양 이 전 송 된 데 이 터 를 받 는 것 을 정의 합 니 다.

private List<Student> list;
private int mLayRes;
public MyBaseAdapter(List<Student> list, int mLayRes) {
  this.list= list;
  this.mLayRes = mLayRes;
}
4.우리 의 앞의 세 가지 방법 을 다시 쓴다.
앞의 세 가지 방법 은 비교적 간단 한 셈 이지 만,

@Override
public int getCount() {
  return list != null ? list.size() : 0;
}
@Override
public T getItem(int position) {
  return list.get(position);
}
@Override
public long getItemId(int position) {
  return position;
}
첫 번 째 간단 한 판단 으로 list 의 크기 를 되 돌려 줍 니 다.두 번 째 는 세 번 째 와 이전 어댑터 와 마찬가지 로 getItem 의 반환 값 만 범 형 으로 썼 다.
5.Viewholder 클래스 를 쓰 는 것 은 매우 번 거 로 운 일 입 니 다.우 리 는 먼저 Viewholder 를 만 들 고 그 다음 방법 을 한 걸음 한 걸음 추가 합 니 다.

public static class ViewHolder {
  private SparseArray<View> mViews = new SparseArray<>();
  private Context mContext;
  private int position;
  private int layRes;
  private View itemView;

 private ViewHolder(Context context, ViewGroup parent, int layRes) {
  this.mContext = context;
  this.layRes= layRes;
  this.itemView = LayoutInflater.from(context).inflate(layRes, parent, false);
  this.itemView.setTag(this);
 }

 public static ViewHolder bind(int position, View convertView, ViewGroup parent, int layRes, Context context) {
  ViewHolder holder;
  if (convertView == null) {
    holder = new ViewHolder(context, parent, layRes);
  } else {
    holder = (ViewHolder) convertView.getTag();
    holder.itemView = convertView;
  }
  holder.position = position;
  return holder;
}
물건 이 좀 많아 서 우 리 는 논리 에 따라 천천히 보 았 다.
1)먼저 하나의 사례 를 통 해 이 루어 지기 때문에 우 리 는 사유 화 구조 방법 이 필요 합 니 다.그 안에 세 개의 매개 변수 가 있 는데 그것 이 바로 문맥,ViewGroup 과 레이아웃 id 입 니 다.이 세 가지 속성 은 우리 가 반드시 사용 해 야 하 는 것 입 니 다.우 리 는 문맥 에 들 어가 inflater 를 얻 고 레이아웃 id 를 전달 한 다음 에 holder 를 우리 의 itemView 에 전달 합 니 다.
이 단 계 는 우리 가 비교적 잘 알 고 있 을 것 이다.우 리 는 예전 에 getView 에서 이 단 계 를 이 루 었 다.
2)그리고 우 리 는 아래 의 bind 방법 을 보 았 다.그의 매개 변 수 는 다섯 개 이다.사실은 세 개의 매개 변수 가 있 습 니 다.우 리 는 잘 알 고 있 습 니 다.바로 우리 getView 의 세 개의 매개 변수 입 니 다.이 를 바탕 으로 우 리 는 두 개의 매개 변수,레이아웃 id 와 문맥 을 추가 했다.
그 다음 에 최적화 하기 위해 서 현재 convertView 가 비어 있 는 지 여 부 를 판단 하고 비어 있 으 면 Viewholder 를 새로 만 들 고 convertView 를 개인 구조 기 에 불 러 옵 니 다.비어 있 지 않 으 면 getTag 를 통 해 직접 받 습 니 다.
holder 의 두 매개 변 수 를 수정 해 야 합 니 다.하 나 는 itemView 이 고 하 나 는 position 입 니 다.우리 가 최적화 한 후에 convertView 가 비어 있 지 않 으 면 그 안에 이전의 데이터 가 있 고 다른 몇 가지 속성 은 우리 가 상관 할 필요 가 없 지만 이 두 가 지 는 이전 내용 이 저장 되 어 있 기 때문이다.우 리 는 그 로 하여 금 현재 의 convertView 와 position 을 다시 가리 키 게 해 야 한다.모두 에 게 그림 을 한 장 그 려 주면 잘 알 수 있다.

색인 같은 그림 은 정확 하지 않 을 수 있 지만,주로 이런 뜻 입 니 다.여러분 은 정신 을 이해 하 세 요.
마지막 으로 holder 로 돌아 갑 니 다.
3)우 리 는 우리 가 불 러 온 convertView 를 되 돌려 야 합 니 다.

public View getItemView() {
  return itemView;
}
이제 우리 Viewholder 의 기본 프레임 워 크 를 다 썼 습 니 다.우 리 는 잠시 그 를 상관 하지 않 고 getView 를 쓰 러 갑 니 다.
6.재 작성 방법 getView:
우 리 는 방금 adapter 에 추상 적 인 방법 을 쓴 다음 에 리 셋 방법 을 통 해 여러 가지 유형 이 적당 하 다 고 말 했다.즉,이 추상 적 인 방법 은 우리 가 구체 적 인 컨트롤 에 데 이 터 를 추가 하 는 것 이다.우 리 는 이 안에서 두 개의 매개 변 수 를 전달 하 는 것 이다.하 나 는 우리 의 Viewholder 이 고 다른 하 나 는 해당 하 는 위치 에 있 는 데이터 이 며 유형 은 범 형 이다.

public abstract void bindView(ViewHolder holder,T obj);
우 리 는 추상 적 인 방법 이 나 타 났 기 때문에 우리 의 MyBaseAdapter 는 추상 적 인 유형 이 되 어야 한다.

public abstract class MyBaseAdapter<T> extends BaseAdapter {
저희 getView 입 니 다.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
  ViewHolder holder = ViewHolder.bind(position,convertView,parent,mLayRes,parent.getContext());
  bindView(holder,list.get(position));
  return holder.getItemView();
}
현재 우리 의 어댑터 는 이미 90%를 완 성 했 습 니 다.아직 조금 부족 합 니 다.우 리 는 몇 가지 보조 방법 을 써 야 합 니 다.우리 가 잠시 후에 적당 한 배 치 를 할 수 있 도록 해 야 합 니 다.
1.지정 한 컨트롤 가 져 오기

public <T extends View> T getView(int id){
  T t = (T) mViews.get(id);
  if(t == null){
    t = itemView.findViewById(id);
    mViews.put(id,t);
  }
  return t;
}
Viewholder 에 getView 방법 을 쓰 고 컨트롤 id 를 통 해 지정 한 컨트롤 을 가 져 옵 니 다.
2.TextView 컨트롤 입력 데이터

public ViewHolder setText(int id,CharSequence text){
  View view = getView(id);
  if(view instanceof View){
    ((TextView)view).setText(text);
  }
  return this;
}
3.ImageView 입력 이미지

public ViewHolder setImg(int id,int resId){
  View view = getView(id);
  if(view instanceof View){
    ((ImageView)view).setImageResource(resId);
  }else
    view.setBackgroundResource(resId);
  return this;
}
4.체크 상자 선택 상 태 를 입력

public ViewHolder setCheckable(int id,boolean checkable){
  View view = getView(id);
  if(view instanceof View){
    ((CheckBox)view).setChecked(checkable);
  }
  return this;
}
자,우선 우리 어댑터 에 완전히 썼 으 니 효 과 를 봅 시다.

private void initTools() {
  ListView mLv = (ListView) findViewById(R.id.mlv);
  adapter = new MyBaseAdapter<Student>(list,R.layout.item_one) {
    @Override
    public void bindView(ViewHolder holder, Student obj) {
      holder.setText(R.id.name,obj.getName())
          .setText(R.id.age,obj.getAge() + "")
          .setText(R.id.sex,obj.getSex())
          .setImg(R.id.head,obj.getImgId())
          .setCheckable(R.id.mc,obj.isOver());
    }
  };
  mLv.setAdapter(adapter);
}

비록 효과 가 좀 추 하지만 기능 은 우리 가 하하 를 실현 했다.여러분 이 믿 지 않 는 다 면 새로운 bean 류 와 새로운 layot 레이아웃 을 만들어 서 시험 해 보 세 요.마찬가지 로 가능 합 니 다.
총결산
이상 은 이 글 의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가 치 를 가지 기 를 바 랍 니 다.여러분 의 저희 에 대한 지지 에 감 사 드 립 니 다.더 많은 내용 을 알 고 싶다 면 아래 링크 를 보 세 요.

좋은 웹페이지 즐겨찾기