Как перебрать список пользователей в Android RecyclerView и сохранить изменения CheckBox в базе данных Firestore с Kotlin - PullRequest
0 голосов
/ 16 февраля 2019

Я несколько дней пытался найти решение, но не могу найти горячий картофель.

У меня около 200 пользователей в списке посещений спортивного клуба.Флажок должен хранить, какие пользователи присутствуют.Проблема в том, что я могу управлять только одним пользователем.Я очень стараюсь, но безрезультатно. У кого-нибудь есть идеи, как решить эту проблему, пожалуйста?

ОБНОВЛЕНИЕ: Спасибо

@ Санлок Ли

Проблема успешно решена.

Ниже новый код:

класс Пользователь:

    class User(
    val uid: String?,
    val username: String?,
    val profileImageUrl: String?,
    val isSelected: Boolean?
)  {

    constructor() : this("", "", "", false)
}

класс Дом:

class Home : AppCompatActivity() {
val db = FirebaseFirestore.getInstance()
val adapter = PerformListAdapter()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_perform_anwesenheitsliste)

    verifyUserIsLogin()

    _recyclerView_show_anwesenheitsliste.adapter = adapter

    showUsersAndPerformChekBoxes()
}

fun showUsersAndPerformChekBoxes() {
    db.collection("users")
        .get()
        .addOnSuccessListener { documents ->
            val users = documents.map { doc ->
                doc.toObject(User::class.java)
            }
            adapter.submitUsers(users)
        }
}

private fun verifyUserIsLogin() {
    val uid = FirebaseAuth.getInstance().uid
    if (uid == null) {
        val intent = Intent(this, LoginActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK)
        startActivity(intent)
    }
}

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
    when (item?.itemId) {

        R.id.menu_home -> {}
        R.id.menu_sign_out -> {
            FirebaseAuth.getInstance().signOut()
            val intent = Intent(this, RegisterActivity::class.java)
            intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK)
            startActivity(intent)
        }
    }

    return super.onOptionsItemSelected(item)
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.nav_menu_home, menu)
    return super.onCreateOptionsMenu(menu)
}
}

Класс PerformListAdapter:

class PerformListAdapter : RecyclerView.Adapter<PerformListAdapter.CustomViewHolder>() {
    val db = FirebaseFirestore.getInstance()

    var users: List<User> = ArrayList()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {

        val inflater = LayoutInflater.from(parent.context)
        val itemuViewRow = inflater.inflate(R.layout.user_row, parent, false)
        return CustomViewHolder(itemuViewRow)
    }

    override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
        if (users.size > position) {
            holder.bindTo(users[position])
        } else {
            holder.clear()
        }
    }

    override fun getItemCount(): Int {
        return users.size
    }

    fun submitUsers(users: List<User>) {
        this.users = users
        notifyDataSetChanged()
    }

    inner class CustomViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        private val checkBox_select: CheckBox = view.findViewById(R.id._checkBox_select)
        private val textView_anwesenheitsliste_username =
            view.findViewById<TextView>(R.id._textView_anwesenheitsliste_username)

        private val imageView_show_anwesenheitsliste_row =
            view.findViewById<CircleImageView>(R.id._imageView_show_anwesenheitsliste_row)

        private val checkedChangeListener = CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->

            val uid = users[adapterPosition].uid

            if (uid != null) {
                Log.d(TAG, uid)
                if (isChecked) {
                    db.collection("users")
                        .document(uid)
                        .update("selected", true)
                } else {
                    db.collection("users")
                        .document(uid)
                        .update("selected", false)
                }
            }
        }

        fun bindTo(user: User) {
            if (!user.profileImageUrl!!.isEmpty()) {
                Picasso.get().load(user.profileImageUrl)
                    .into(imageView_show_anwesenheitsliste_row)
            }
            textView_anwesenheitsliste_username?.text = user.username
            checkBox_select.setOnCheckedChangeListener(null)
            checkBox_select.isChecked = (user.isSelected == true)
            checkBox_select.setOnCheckedChangeListener(checkedChangeListener)
        }

        fun clear() {
            textView_anwesenheitsliste_username.text = ""
            checkBox_select.setOnCheckedChangeListener(null)
        }
    }
}

1 Ответ

0 голосов
/ 17 февраля 2019

Первое, о чем нужно подумать, нужен ли для этого прослушиватель щелчков.Событие click должно быть поглощено CheckBox, и, следовательно, прослушиватель click, вероятно, не нужен.Кроме того, setOnCheckedChangeListener должен быть установлен один раз для CheckBox, а не для клика и не для User элементов.

Поскольку вы не показали нам GroupAdapter или ViewHolder реализацию, поэтому я просто подошелс одной возможной реализацией:

GroupAdapter.kt

class GroupAdapter: RecyclerView.Adapter<GroupAdapter.ViewHolder>() {

    private val db = FirebaseFirestore.getInstance()
    private var users: List<User> = ArrayList() // Store user list here


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val itemView = inflater.inflate(R.layout.yourViewHolderLayout, parent, false)
        return ViewHolder(itemView)
    }


    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        if (users.size > position)
            holder.bindTo(users[position])
        else
            holder.clear()
    }


    override fun getItemCount() = users.size


    // Update the user list
    fun submitUsers(users: List<User>) {
        this.users = users
        notifyDataSetChanged()
    }


    inner class ViewHolder(view: View): RecyclerView.ViewHolder(view) {
        private val _checkBox_select: CheckBox = view.findViewById(R.id.yourCheckBoxId)
        private val _textView_anwesenheitsliste_username = view.findViewById(R.id.yourTextBoxId)
        private val checkedChangeListener =
            CompoundButton.OnCheckedChangeListener { view, isChecked ->
                val uid = users[adapterPosition].uid

                if (uid != null) {
                    if (isChecked) {
                        db.collection("users").document(uid)
                            .update("isSelected", true)
                    } else {
                        db.collection("users").document(uid)
                            .update("isSelected", false)
                    }
                }
            }


        // bind to user here
        fun bindTo(user: User) {

            if (!user.prfileImageUrl!!.isEmpty()) {
                Picasso.get().load(user.prfileImageUrl)
                    .into(_imageView_show_anwesenheitsliste_row)
            }
            _textView_anwesenheitsliste_username.text = user.username
            _checkBox_select.setOnCheckedChangeListener(null)
            _checkBox_select.isChecked = (user.isSelected == true)
            _checkBox_select.setOnCheckedChangeListener(checkedChangeListener)
        }


        // clear
        fun clear() {
            _textView_anwesenheitsliste_username.text = ""
            _checkBox_select.setOnCheckedChangeListener(null)
        }
    }
}

Тогда вы можете использовать этот адаптер в своей деятельности следующим образом:

val db = FirebaseFirestore.getInstance()
val adapter = GroupAdapter()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_perform_anwesenheitsliste)

     _recyclerView_show_anwesenheitsliste.adapter = adapter

    showUsersAndPerformChekBoxes()
}

private fun showUsersAndPerformChekBoxes() {
    db.collection("users")
        .get()
        .addOnSuccessListener { documents ->
            val users = documents.map { doc -> doc.toObejct(User::Class.java) }
            adapter.submitUsers(users)
        }
}

Вещи могут не работать сразутак как я не тестировал код.

Дальнейшие улучшения

Если вам интересно, подумайте об этих сценариях: что делать, если слишком много пользователей, которых приложение не можетполучить весь список сразу?Что делать, если несколько телефонов используют одно и то же приложение и пытаются обновить список одновременно?Что делать, если есть проблема с сетью?Что произойдет, если пользователь спамит флажок x9999 раз?

Решения для этих проблем не тривиальны, поэтому я не отвечаю здесь, но это хорошая практика, чтобы подумать о крайних случаях и как приложение должно реагировать наэти сценарии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...