From 1d034e617ad5ed5609dcdf1c88a1f6a413695291 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Fri, 22 Jan 2021 12:33:44 +0200 Subject: [PATCH] Use viewholder in adapters --- .../com/tutpro/baresip/AccountListAdapter.kt | 45 +++++++--- .../com/tutpro/baresip/CallListAdapter.kt | 77 ++++++++++------- .../com/tutpro/baresip/ChatListAdapter.kt | 82 ++++++++++++------- .../com/tutpro/baresip/ContactListAdapter.kt | 69 ++++++++++------ .../com/tutpro/baresip/MessageListAdapter.kt | 58 ++++++++----- .../com/tutpro/baresip/UaSpinnerAdapter.kt | 48 +++++++---- 6 files changed, 248 insertions(+), 131 deletions(-) diff --git a/app/src/main/kotlin/com/tutpro/baresip/AccountListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/AccountListAdapter.kt index 67e6fd44..9294d0c8 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AccountListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AccountListAdapter.kt @@ -17,31 +17,49 @@ import java.util.* class AccountListAdapter(private val cxt: Context, private val rows: ArrayList) : ArrayAdapter(cxt, R.layout.account_row, rows) { - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + private val layoutInflater = LayoutInflater.from(context) + + private class ViewHolder(view: View?) { + val aorView = view?.findViewById(R.id.aor) as TextView + val actionView = view?.findViewById(R.id.action) as ImageButton + } + + override fun getView(position: Int, view: View?, parent: ViewGroup): View { + + val viewHolder: ViewHolder + val rowView: View + val ua = UserAgent.uas()[position] + + if (view == null) { + rowView = layoutInflater.inflate(R.layout.account_row, parent, false) + viewHolder = ViewHolder(rowView) + rowView.tag = viewHolder + } else { + rowView = view + viewHolder = rowView.tag as ViewHolder + } + val row = rows[position] - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val rowView = inflater.inflate(R.layout.account_row, parent, false) - val aorView = rowView.findViewById(R.id.aor) as TextView - aorView.text = row.aor.split(":")[0] - aorView.textSize = 20f - aorView.setPadding(6, 6, 0, 6) - aorView.setOnClickListener { + viewHolder.aorView.text = row.aor.split(":")[0] + viewHolder.aorView.textSize = 20f + viewHolder.aorView.setPadding(6, 6, 0, 6) + viewHolder.actionView.setImageResource(row.action) + + viewHolder.aorView.setOnClickListener { val i = Intent(cxt, AccountActivity::class.java) val b = Bundle() b.putString("aor", UserAgent.uas()[position].account.aor) i.putExtras(b) (cxt as Activity).startActivityForResult(i, MainActivity.ACCOUNT_CODE) } - val ua = UserAgent.uas()[position] - val actionView = rowView.findViewById(R.id.action) as ImageButton - actionView.setImageResource(row.action) - actionView.setOnClickListener { + + viewHolder.actionView.setOnClickListener { val titleView = View.inflate(cxt, R.layout.alert_title, null) as TextView titleView.text = cxt.getString(R.string.confirmation) with (AlertDialog.Builder(cxt, R.style.AlertDialog)) { setCustomTitle(titleView) setMessage(String.format(cxt.getString(R.string.delete_account), - aorView.text)) + viewHolder.aorView.text)) setPositiveButton(cxt.getText(R.string.delete)) { dialog, _ -> Api.ua_destroy(ua.uap) CallHistory.clear(ua.account.aor) @@ -58,6 +76,7 @@ class AccountListAdapter(private val cxt: Context, private val rows: ArrayList) : ArrayAdapter(cxt, R.layout.call_row, rows) { - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + private val layoutInflater = LayoutInflater.from(context) + + private class ViewHolder(view: View?) { + val textAvatarView = view?.findViewById(R.id.TextAvatar) as TextView + val cardAvatarView = view?.findViewById(R.id.CardAvatar) as CardView + val cardImageAvatarView = view?.findViewById(R.id.CardImageAvatar) as ImageView + val directionsView = view?.findViewById(R.id.directions) as LinearLayout + val etcView = view?.findViewById(R.id.etc) as TextView + val peerUriView = view?.findViewById(R.id.peer_uri) as TextView + val timeView = view?.findViewById(R.id.time) as TextView + } + + override fun getView(position: Int, view: View?, parent: ViewGroup): View { + + val viewHolder: ViewHolder + val rowView: View + + if (view == null) { + rowView = layoutInflater.inflate(R.layout.call_row, parent, false) + viewHolder = CallListAdapter.ViewHolder(rowView) + rowView.tag = viewHolder + } else { + rowView = view + viewHolder = rowView.tag as ViewHolder + } + val callRow = rows[position] - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val rowView = inflater.inflate(R.layout.call_row, parent, false) - val textAvatarView = rowView.findViewById(R.id.TextAvatar) as TextView - val cardAvatarView = rowView.findViewById(R.id.CardAvatar) as CardView - val cardImageAvatarView = rowView.findViewById(R.id.CardImageAvatar) as ImageView + val contact = ContactsActivity.findContact(callRow.peerUri) if (contact != null) { val avatarImage = contact.avatarImage if (avatarImage != null) { - textAvatarView.visibility = View.GONE - cardAvatarView.visibility = View.VISIBLE - cardImageAvatarView.setImageBitmap(avatarImage) + viewHolder.textAvatarView.visibility = View.GONE + viewHolder.cardAvatarView.visibility = View.VISIBLE + viewHolder.cardImageAvatarView.setImageBitmap(avatarImage) } else { - textAvatarView.visibility = View.VISIBLE - cardAvatarView.visibility = View.GONE - (textAvatarView.background as GradientDrawable).setColor(contact.color) - textAvatarView.text = "${contact.name[0]}" + viewHolder.textAvatarView.visibility = View.VISIBLE + viewHolder.cardAvatarView.visibility = View.GONE + (viewHolder.textAvatarView.background as GradientDrawable).setColor(contact.color) + viewHolder.textAvatarView.text = "${contact.name[0]}" } } else { - textAvatarView.visibility = View.VISIBLE - cardAvatarView.visibility = View.GONE - textAvatarView.setBackgroundResource(R.drawable.person_image) + viewHolder.textAvatarView.visibility = View.VISIBLE + viewHolder.cardAvatarView.visibility = View.GONE + viewHolder.textAvatarView.setBackgroundResource(R.drawable.person_image) } - val directions = rowView.findViewById(R.id.directions) as LinearLayout + var count = 1 for (d in callRow.directions) { if (count > 3) { - val etc = rowView.findViewById(R.id.etc) as TextView - etc.text = "..." + viewHolder.etcView.text = "..." break } val dirView = ImageView(cxt) @@ -56,17 +72,18 @@ class CallListAdapter(private val cxt: Context, private val rows: ArrayList) : ArrayAdapter(ctx, R.layout.message, rows) { - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + private val layoutInflater = LayoutInflater.from(context) + + private class ViewHolder(view: View?) { + val textAvatarView = view?.findViewById(R.id.TextAvatar) as TextView + val cardAvatarView = view?.findViewById(R.id.CardAvatar) as CardView + val cardImageAvatarView = view?.findViewById(R.id.ImageAvatar) as ImageView + val layoutView = view?.findViewById(R.id.chat) as LinearLayout + val peerView = view?.findViewById(R.id.peer) as TextView + val infoView = view?.findViewById(R.id.info) as TextView + val textView = view?.findViewById(R.id.text) as TextView + } + + override fun getView(position: Int, view: View?, parent: ViewGroup): View { + + val viewHolder: ViewHolder + val rowView: View + + if (view == null) { + rowView = layoutInflater.inflate(R.layout.chat_row, parent, false) + viewHolder = ViewHolder(rowView) + rowView.tag = viewHolder + } else { + rowView = view + viewHolder = rowView.tag as ViewHolder + } + val message = rows[position] - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val rowView = inflater.inflate(R.layout.chat_row, parent, false) - val textAvatarView = rowView.findViewById(R.id.TextAvatar) as TextView - val cardAvatarView = rowView.findViewById(R.id.CardAvatar) as CardView - val cardImageAvatarView = rowView.findViewById(R.id.ImageAvatar) as ImageView - val layout = rowView.findViewById(R.id.chat) as LinearLayout + val contact = ContactsActivity.findContact(message.peerUri) val peer: String if (contact != null) { peer = contact.name val avatarImage = contact.avatarImage if (avatarImage != null) { - textAvatarView.visibility = View.GONE - cardAvatarView.visibility = View.VISIBLE - cardImageAvatarView.setImageBitmap(avatarImage) + viewHolder.textAvatarView.visibility = View.GONE + viewHolder.cardAvatarView.visibility = View.VISIBLE + viewHolder.cardImageAvatarView.setImageBitmap(avatarImage) } else { - textAvatarView.visibility = View.VISIBLE - cardAvatarView.visibility = View.GONE - (textAvatarView.background as GradientDrawable).setColor(contact.color) - textAvatarView.text = "${peer[0]}" + viewHolder.textAvatarView.visibility = View.VISIBLE + viewHolder.cardAvatarView.visibility = View.GONE + (viewHolder.textAvatarView.background as GradientDrawable).setColor(contact.color) + viewHolder.textAvatarView.text = "${peer[0]}" } } else { peer = Utils.friendlyUri(message.peerUri, message.aor) - textAvatarView.visibility = View.VISIBLE - cardAvatarView.visibility = View.GONE - textAvatarView.setBackgroundResource(R.drawable.person_image) + viewHolder.textAvatarView.visibility = View.VISIBLE + viewHolder.cardAvatarView.visibility = View.GONE + viewHolder.textAvatarView.setBackgroundResource(R.drawable.person_image) } + if ((message.direction == R.drawable.arrow_down_green) || (message.direction == R.drawable.arrow_down_red)) - layout.setBackgroundResource(R.drawable.message_in_bg) + viewHolder.layoutView.setBackgroundResource(R.drawable.message_in_bg) else - layout.setBackgroundResource(R.drawable.message_out_bg) - val peerView = rowView.findViewById(R.id.peer) as TextView - peerView.setText(peer) - val infoView = rowView.findViewById(R.id.info) as TextView + viewHolder.layoutView.setBackgroundResource(R.drawable.message_out_bg) + + viewHolder.peerView.setText(peer) + val cal = GregorianCalendar() cal.timeInMillis = message.timeStamp val fmt: DateFormat @@ -61,21 +82,22 @@ class ChatListAdapter(private val ctx: Context, private var rows: ArrayList(ctx, R.layout.contact_row, rows) { + private val layoutInflater = LayoutInflater.from(context) private var lastClick: Long = 0 - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + private class ViewHolder(view: View?) { + val textAvatarView = view?.findViewById(R.id.TextAvatar) as TextView + val cardAvatarView = view?.findViewById(R.id.CardAvatar) as CardView + val imageAvatarView = view?.findViewById(R.id.ImageAvatar) as ImageView + val nameView = view?.findViewById(R.id.contactName) as TextView + val actionView = view?.findViewById(R.id.edit) as ImageButton + } + + override fun getView(position: Int, view: View?, parent: ViewGroup): View { + + val viewHolder: ViewHolder + val rowView: View + + if (view == null) { + rowView = layoutInflater.inflate(R.layout.contact_row, parent, false) + viewHolder = ViewHolder(rowView) + rowView.tag = viewHolder + } else { + rowView = view + viewHolder = rowView.tag as ViewHolder + } + val contact = rows[position] - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val rowView = inflater.inflate(R.layout.contact_row, parent, false) - val textAvatarView = rowView.findViewById(R.id.TextAvatar) as TextView - val cardAvatarView = rowView.findViewById(R.id.CardAvatar) as CardView - val imageAvatarView = rowView.findViewById(R.id.ImageAvatar) as ImageView + val avatarImage = contact.avatarImage if (avatarImage != null) { - textAvatarView.visibility = View.GONE - cardAvatarView.visibility = View.VISIBLE - imageAvatarView.visibility = View.VISIBLE - imageAvatarView.setImageBitmap(avatarImage) + viewHolder.textAvatarView.visibility = View.GONE + viewHolder.cardAvatarView.visibility = View.VISIBLE + viewHolder.imageAvatarView.visibility = View.VISIBLE + viewHolder.imageAvatarView.setImageBitmap(avatarImage) } else { - textAvatarView.visibility = View.VISIBLE - cardAvatarView.visibility = View.GONE - imageAvatarView.visibility = View.GONE - (textAvatarView.background as GradientDrawable).setColor(contact.color) + viewHolder.textAvatarView.visibility = View.VISIBLE + viewHolder.cardAvatarView.visibility = View.GONE + viewHolder.imageAvatarView.visibility = View.GONE + (viewHolder.textAvatarView.background as GradientDrawable).setColor(contact.color) if (contact.name.isNotEmpty()) - textAvatarView.text = "${contact.name[0]}" + viewHolder.textAvatarView.text = "${contact.name[0]}" else - textAvatarView.text = "" + viewHolder.textAvatarView.text = "" } - val nameView = rowView.findViewById(R.id.contactName) as TextView - nameView.text = contact.name - nameView.textSize = 20f - nameView.setPadding(6, 6, 0, 6) + + viewHolder.nameView.text = contact.name + viewHolder.nameView.textSize = 20f + viewHolder.nameView.setPadding(6, 6, 0, 6) + if (aor != "") { - nameView.setOnClickListener { _ -> + viewHolder.nameView.setOnClickListener { _ -> val dialogClickListener = DialogInterface.OnClickListener { _, which -> when (which) { DialogInterface.BUTTON_POSITIVE, DialogInterface.BUTTON_NEGATIVE -> { @@ -93,7 +112,8 @@ class ContactListAdapter(private val ctx: Context, private val rows: ArrayList + + viewHolder.nameView.setOnLongClickListener { _ -> val dialogClickListener = DialogInterface.OnClickListener { _, which -> when (which) { DialogInterface.BUTTON_POSITIVE -> { @@ -126,8 +146,8 @@ class ContactListAdapter(private val ctx: Context, private val rows: ArrayList + + viewHolder.actionView.setOnClickListener { _ -> if (SystemClock.elapsedRealtime() - lastClick > 1000) { lastClick = SystemClock.elapsedRealtime() val i = Intent(ctx, ContactActivity::class.java) @@ -138,6 +158,7 @@ class ContactListAdapter(private val ctx: Context, private val rows: ArrayList) : ArrayAdapter(ctx, R.layout.message, rows) { - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + private val layoutInflater = LayoutInflater.from(context) + + private class ViewHolder(view: View?) { + val layoutView = view?.findViewById(R.id.message) as LinearLayout + val infoView = view?.findViewById(R.id.info) as TextView + val textView = view?.findViewById(R.id.text) as TextView + } + + override fun getView(position: Int, view: View?, parent: ViewGroup): View { + + val viewHolder: ViewHolder + val rowView: View + + if (view == null) { + rowView = layoutInflater.inflate(R.layout.message, parent, false) + viewHolder = ViewHolder(rowView) + rowView.tag = viewHolder + } else { + rowView = view + viewHolder = rowView.tag as ViewHolder + } + val message = rows[position] + val up = (message.direction == R.drawable.arrow_up_green) || (message.direction == R.drawable.arrow_up_red) - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val messageView = inflater.inflate(R.layout.message, parent, false) - val layout = messageView.findViewById(R.id.message) as LinearLayout - val lp = layout.layoutParams as LinearLayout.LayoutParams + val lp = viewHolder.layoutView.layoutParams as LinearLayout.LayoutParams val peer: String - if (up) { + peer = if (up) { lp.setMargins(75, 10, 0, 10) - layout.setBackgroundResource(R.drawable.message_out_bg) - peer = ctx.getString(R.string.you) + viewHolder.layoutView.setBackgroundResource(R.drawable.message_out_bg) + ctx.getString(R.string.you) } else { lp.setMargins(0, 10, 75, 10) - layout.setBackgroundResource(R.drawable.message_in_bg) + viewHolder.layoutView.setBackgroundResource(R.drawable.message_in_bg) val contactName = ContactsActivity.contactName(message.peerUri) if (contactName.startsWith("sip:") && (Utils.uriHostPart(message.peerUri) == Utils.uriHostPart(message.aor))) - peer = Utils.uriUserPart(message.peerUri) + Utils.uriUserPart(message.peerUri) else - peer = contactName + contactName } - layout.layoutParams = lp - val infoView = messageView.findViewById(R.id.info) as TextView + viewHolder.layoutView.layoutParams = lp + var info: String val cal = GregorianCalendar() cal.timeInMillis = message.timeStamp @@ -56,14 +75,15 @@ class MessageListAdapter(private val ctx: Context, private val rows: ArrayList, - private val images: ArrayList) : +class UaSpinnerAdapter(cxt: Context, private val uas: ArrayList, + private val images: ArrayList) : ArrayAdapter(cxt, android.R.layout.simple_spinner_item, images) { - override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { - return getImageForPosition(position, parent) + private val layoutInflater = LayoutInflater.from(context) + + private class ViewHolder(view: View?) { + val textView = view?.findViewById(R.id.spinnerText) as TextView + val imageView = view?.findViewById(R.id.spinnerImage) as ImageView } - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - return getImageForPosition(position, parent) + override fun getDropDownView(position: Int, view: View?, parent: ViewGroup): View { + return getImageForPosition(position, view, parent) } - private fun getImageForPosition(position: Int, parent: ViewGroup): View { - val inflater = cxt.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val row = inflater.inflate(R.layout.account_spinner, parent, false) - val textView = row.findViewById(R.id.spinnerText) as TextView - textView.text = uas[position].account.aor.split(":")[1] - textView.textSize = 17f - val imageView = row.findViewById(R.id.spinnerImage) as ImageView - imageView.setImageResource(images[position]) - return row + override fun getView(position: Int, view: View?, parent: ViewGroup): View { + return getImageForPosition(position, view, parent) + } + + private fun getImageForPosition(position: Int, view: View?, parent: ViewGroup): View { + + val viewHolder: ViewHolder + val rowView: View + + if (view == null) { + rowView = layoutInflater.inflate(R.layout.account_spinner, parent, false) + viewHolder = ViewHolder(rowView) + rowView.tag = viewHolder + } else { + rowView = view + viewHolder = rowView.tag as ViewHolder + } + + viewHolder.textView.text = uas[position].account.aor.split(":")[1] + viewHolder.textView.textSize = 17f + viewHolder.imageView.setImageResource(images[position]) + + return rowView } }