2. 2 ••Modern Android Development - Epoxy - Tobias Schürg
The quick and simple way.
ListView and Adapter
list_view.adapter = ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,
mutableListOf()
)
3. 3 ••Modern Android Development - Epoxy - Tobias Schürg
Custom list adapter
class MessageAdapter(private val context: Context) : BaseAdapter() {
private val messages: MutableList<Message> = mutableListOf()
private val dateTimeInstance = DateFormat.getTimeInstance(DateFormat.MEDIUM)
fun update(newMessages: List<Message>) {
messages.clear()
messages.addAll(newMessages)
notifyDataSetChanged()
}
override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View {
val view = LayoutInflater.from(context).inflate(R.layout.chat_item, p2, false)
val message = getItem(p0)
val tvName = view.findViewById<TextView>(R.id.name)
val tvMessage = view.findViewById<TextView>(R.id.message)
val tvTime = view.findViewById<TextView>(R.id.time)
tvName.text = message.name
tvMessage.text = message.message
tvTime.text = dateTimeInstance.format(Date(message.timestamp))
return view
}
override fun getItem(position: Int): Message {
return messages[position]
}
override fun getItemId(position: Int): Long {
return messages[position].timestamp
}
override fun getCount(): Int {
return messages.size
}
}
4. 4 ••Modern Android Development - Epoxy - Tobias Schürg
RecyclerView
• Part of the support libraries
• More advanced and flexible version of a ListView
• Does a lot of optimizations by default
• ViewHolder
• Reuse
• Animations
• Is filled by a LayoutManager (LinearLayoutManager, GridLayoutManager, …)
5. 5 ••Modern Android Development - Epoxy - Tobias Schürg
Custom RecycleView adapter
class MyAdapter(private val myDataset: Array<String>)
: RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
class MyViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyAdapter.MyViewHolder {
val textView = LayoutInflater.from(parent.context)
.inflate(R.layout.my_text_view, parent, false) as TextView
// set the view's size, margins, paddings and layout parameters
return MyViewHolder(textView)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
// replace the contents of the view with that element
holder.textView.text = myDataset[position]
}
override fun getItemCount() = myDataset.size
}
6. 6 ••Modern Android Development - Epoxy - Tobias Schürg
Epoxy
• Open source library by AirBnb
• Simplifies working with RecyclerView
• Avoids boilerplate
• Handles diffing
• “ready-to-run” defaults
9. 9 ••Modern Android Development - Epoxy - Tobias Schürg
Creating models – from view holders
@EpoxyModelClass(layout = R.layout.model_chat_message)
abstract class ChatMessageView : EpoxyModelWithHolder<Holder>() {
@EpoxyAttribute lateinit var name: String
@EpoxyAttribute lateinit var message: String
override fun bind(holder: Holder) {
holder.nameView.text = name
holder.messageView.text = message
}
}
class Holder : EpoxyHolder() {
lateinit var nameView: AppCompatTextView
lateinit var messageView: AppCompatTextView
override fun bindView(itemView: View) {
nameView = itemView.findViewById(R.id.name)
messageView = itemView.findViewById(R.id.message)
}
}
10. 10 ••Modern Android Development - Epoxy - Tobias Schürg
Putting it all together
private val adapter: SimpleEpoxyAdapter = SimpleEpoxyAdapter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
chat_recycler_view.layoutManager = LinearLayoutManager(this)
chat_recycler_view.adapter = adapter
}
override fun onResume() {
super.onResume()
adapter.addModels(createModels())
}
11. 11 ••Modern Android Development - Epoxy - Tobias Schürg
Things to know
- All models need an ID
- model.setId(…)
- Scroll to the end of the RecyclerView with
- chat_recycler_view.scrollToPosition(adapter.itemCount - 1)
- There are @TextProp, @CallbackProp, @ModelProp (for custom views)
- @ModelProp(options = Option.DoNotHash)
- There is also an EpoxyRecyclerView for even less boilerplate