viewBinding과 Listview에 대해서 기본적인 것을 안다고 전제하에 글을 작성하겠습니다. viewBinding의 경우 잘 모르시면 viewBinding 제가 작성한 글을 참고해주시기 바랍니다.
viewBinding 글 주소 : https://velog.io/@ilil1/%EA%B0%9C%EB%85%90-%EB%B7%B0-%EB%B0%94%EC%9D%B8%EB%94%A9view-binding
1. MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var adapter : ListviewAdapter
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val list = ArrayList<Model>()
var contact = Model("Add ","00000","https://picsum.photos/200")
for(i: Int in 1..10)
list.add(contact)
adapter = ListviewAdapter(list)
binding.listview.adapter = adapter
}
}
viewBinding을 이용해서 findViewById() 직접 사용을 하지않고 ActivityMainBinding 클래스에 자동으로 캐싱된 레이아웃 id를 접근 해서 binding.listview.adapter 에 list 배열의 값을 파라미터로 넘겨받아 ListviewAdapter(list) 인스턴스를 할당해 줍니다.
실제 viewBinding 되서 xml의 주소를 가지고 클래스가 생성되어 있는 위치 입니다. 안의 코드도 한번 살펴보겠습니다.
public final class ActivityMainBinding implements ViewBinding {
@NonNull
private final LinearLayout rootView;
@NonNull
public final ListView listview;
private ActivityMainBinding(@NonNull LinearLayout rootView, @NonNull ListView listview) {
this.rootView = rootView;
this.listview = listview;
}
@Override
@NonNull
public LinearLayout getRoot() {
return rootView;
}
@NonNull
public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater) {
return inflate(inflater, null, false);
}
@NonNull
public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater,
@Nullable ViewGroup parent, boolean attachToParent) {
View root = inflater.inflate(R.layout.activity_main, parent, false);
if (attachToParent) {
parent.addView(root);
}
return bind(root);
}
@NonNull
public static ActivityMainBinding bind(@NonNull View rootView) {
// The body of this method is generated in a way you would not otherwise write.
// This is done to optimize the compiled bytecode for size and performance.
int id;
missingId: {
id = R.id.listview;
ListView listview = ViewBindings.findChildViewById(rootView, id);
if (listview == null) {
break missingId;
}
return new ActivityMainBinding((LinearLayout) rootView, listview);
}
String missingId = rootView.getResources().getResourceName(id);
throw new NullPointerException("Missing required view with ID: ".concat(missingId));
}
}
위 코드를 좀더 아래에서 자세히 보겠습니다.
int id;
missingId: {
id = R.id.listview;
ListView listview = ViewBindings.findChildViewById(rootView, id);
if (listview == null) {
break missingId;
}
return new ActivityMainBinding((LinearLayout) rootView, listview);
}
id = R.id.listview;
ListView listview = ViewBindings.findChildViewById(rootView, id); 를 보면 findChildViewById(rootView, id); 를 해서 우리가 뷰홀더에서 따로 하던 작업을 여기서 자동으로 해놓는 것을 알 수 있습니다.
2. ListviewAdapter.kt
class ListviewAdapter(
private val items: List<Model>
) : BaseAdapter() {
override fun getCount(): Int = items.size
override fun getItem(position: Int): Any = items[position]
override fun getItemId(position: Int): Long = position.toLong()
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val binding = if (convertView == null) {
val tempBinding = BoardListBinding.inflate(LayoutInflater.from(parent?.context))
tempBinding.root.tag = tempBinding
tempBinding
} else {
convertView.tag
} as BoardListBinding
bind(binding, items[position])
return binding.root
}
private fun bind(binding: BoardListBinding, data: Model) = with(binding) {
thumbnail.clear()
titleText.text = data.title
contentText.text = data.content
thumbnail.load(data.imageurl, 16f)
}
}
위 코드중 getView를 따로 분석해 보겠습니다.
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val binding = if (convertView == null) {
val tempBinding = BoardListBinding.inflate(LayoutInflater.from(parent?.context))
tempBinding.root.tag = tempBinding
tempBinding
} else {
convertView.tag
} as BoardListBinding
bind(binding, items[position])
return binding.root
}
3. Model.kt
data class Model(
val title: String,
val content: String,
val imageurl : String
)
화면에 출력할 Model를 위와 같이(title, content, imageurl) 디자인 해줍니다.
1. MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var adapter : RecyclerAdapter
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val list = ArrayList<Model>()
var contact = Model("Add ","00000","https://picsum.photos/200")
for(i: Int in 1..10)
list.add(contact)
adapter = RecyclerAdapter(list)
binding.recyclerView.adapter = adapter
binding.recyclerView.layoutManager = LinearLayoutManager(this)
}
}
viewBinding을 이용해서 findViewById() 직접 사용을 하지않고 ActivityMainBinding 클래스에 자동으로 캐싱된 레이아웃 id를 접근 해서 binding.recyclerView.adapter 에 list 배열의 값을 파라미터로 넘겨받아 RecyclerAdapter(list) 인스턴스를 할당해 줍니다.
2. RecyclerAdapter.kt
class RecyclerAdapter(private val items: ArrayList<Model>) :
RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
class ViewHolder(val binding: BoardListBinding) : RecyclerView.ViewHolder(binding.root) {
//val title : TextView = itemView.findViewById(R.id.titleText)
//val content : TextView = itemView.findViewById(R.id.contentText)
//val thumbnail : ImageView = itemView.findViewById(R.id.thumbnail)
fun bind(item: Model) {
binding.thumbnail.clear()
binding.titleText.text = item.title
binding.contentText.text = item.content
binding.thumbnail.load(item.imageurl, 16f)
}
}
override fun getItemCount() = items.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerAdapter.ViewHolder {
val binding = BoardListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: RecyclerAdapter.ViewHolder, position: Int) {
val item = items[position]
holder.bind(item)
}
}
val title : TextView = itemView.findViewById(R.id.titleText)
val content : TextView = itemView.findViewById(R.id.contentText)
val thumbnail : ImageView = itemView.findViewById(R.id.thumbnail)이전 리사이클러뷰에서는 위와 같이 findViewById를 직접해줘야 했습니다. 그러나 뷰바인딩 사용시 BoardListBinding 클래스에서 자동으로 해주기 때문에 그러한 과정이 필요가 없이 (binding. ~) 으로 참조해서 값을 정의해주면 됩니다.
3. Model.kt
data class Model(
val title: String,
val content: String,
val imageurl : String
)
화면에 출력할 Model를 위와 같이(title, content, imageurl) 디자인 해줍니다.