반응형
안녕하세요.
오늘은 Android ListView에 VIewHolder 패턴 적용 및 DataBinding을 적용하는것에 설명하도록 하겠습니다.
최근에 기존에 개발된 자바로 된 코드를 리팩토링하는 작업을 주로 진행하고 있는데,
ListView에 ViewHolder 패턴, DataBinding을 적용했는데 잘못된 부분이 있어서 수정하는 작업을 진행했습니다.
혹시 비슷한 어려움을 겪고 계실분들을 위해서 적용한 코드를 설명하려합니다.
우선 기존 코드에서는 getView가 호출될때, 데이터가 늘어나서 스크롤이 생기면, position값에 따라 데이터가 의도하지 않은대로 동작하는 문제가 있었습니다.
ViewHolder의 데이터가 position을 잃어버리는것과 같이 이상동작합니다.
문제는 mHolder로 setTag를 지정했는데도, mHolder에 position을 주어야하는데, position 따로 View 처리를 해줘서 발생한 문제였습니다.
문제가 되는 코드는 아래와 같습니다.
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.databinding.DataBindingUtil;
import java.util.List;
import java.util.Locale;
public class ListAdapter extends BaseAdapter {
private static final String TAG = "ListAdapter";
private static final Integer VIEW_LINE_1 = 0;
private static final Integer VIEW_LINE_2 = 1;
private static final Integer HOLDER_TYPE_A = 0;
private static final Integer HOLDER_TYPE_B = 1;
private DataBinding binding;
private List<Model> mModelList;
public ListAdapter(Context context, List<Model> lists)
{
this.context = context;
this.mModelList = lists;
}
@Override
public int getCount() {
return mModelList.size();
}
@Override
public Model getItem(int position) {
return mModelList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
private class ViewHolder {
private DataBinding binding;
private View baseView = null;
private View mViewLine = null;
public ViewHolder(View view) {
baseView = view;
}
private void setType(Model modelInfo) {
if (modelInfo.getId().equals("")) {
binding.setType(HOLDER_TYPE_A);
} else {
binding.setType(HOLDER_TYPE_B);
}
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder mHolder;
if (convertView == null) {
binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item, parent, false);
convertView = binding.getRoot();
mHolder = new ViewHolder(convertView);
convertView.setTag(mHolder);
} else {
mHolder = (ViewHolder) convertView.getTag();
}
if (position == 0) {
binding.setViewLine(VIEW_LINE_1);
} else {
binding.setViewLine(VIEW_LINE_2);
}
setType(mModelList.get(position));
return convertView;
}
public void refreshAdapter() {
notifyDataSetChanged();
}
}
수정한 코드는 다음과 같습니다.
ViewHolder 생성자에 binding을 파라미터로 넘겨주고, mHolder 내부로 binding처리를 합니다.
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.databinding.DataBindingUtil;
import java.util.List;
import java.util.Locale;
public class ListAdapter extends BaseAdapter {
private static final String TAG = "ListAdapter";
private static final Integer VIEW_LINE_1 = 0;
private static final Integer VIEW_LINE_2 = 1;
private static final Integer HOLDER_TYPE_A = 0;
private static final Integer HOLDER_TYPE_B = 1;
private List<Model> mModelList;
public ListAdapter(Context context, List<Model> lists)
{
this.context = context;
this.mModelList = lists;
}
@Override
public int getCount() {
return mModelList.size();
}
@Override
public Model getItem(int position) {
return mModelList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
private class ViewHolder {
private DataBinding binding;
private View baseView = null;
private View mViewLine = null;
public ViewHolder(View view, DataBinding binding) {
this.baseView = view;
this.binding = binding;
}
private void setType(Model modelInfo) {
if (modelInfo.getId().equals("")) {
binding.setType(HOLDER_TYPE_A);
} else {
binding.setType(HOLDER_TYPE_B);
}
}
private void setViewLine(int position) {
if (position == 0) {
binding.setViewLine(VIEW_LINE_1);
} else {
binding.setViewLine(VIEW_LINE_2);
}
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder mHolder;
DataBinding binding = null;
if (convertView == null) {
binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item, parent, false);
convertView = binding.getRoot();
mHolder = new ViewHolder(convertView, binding);
convertView.setTag(mHolder);
} else {
mHolder = (ViewHolder) convertView.getTag();
}
mHolder.setType(mModelList.get(position));
mHolder.setViewLine(position);
return convertView;
}
public void refreshAdapter() {
notifyDataSetChanged();
}
}
감사합니다.
반응형
'Development > Android' 카테고리의 다른 글
| Caused by: org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all files for configuration ':app:debugRuntimeClasspath'. (0) | 2022.11.17 |
|---|---|
| Android Studio dolphin에서 파이어베이스 추가하기. (0) | 2022.09.25 |
| Android Application 클래스가 호출되지 않는 경우 (0) | 2022.02.03 |
| Android MVVM with Retrofit2 (0) | 2022.01.30 |
| Gson 라이브러리 사용하기 (0) | 2022.01.25 |