Обновление представления адаптера recyclerView mvvm (воспроизведение звука и обновление представления) - PullRequest
3 голосов
/ 29 марта 2019

У меня есть список записи звука пользователя Пользователь может нажать на список и воспроизвести аудио файл Как правильно обрабатывать MediaPlayer и RecyclerView в Панель поиска , а также в MVVM ? То есть, когда пользователь щелкает, посетитель меняет элемент и обновляет себя, а когда он снова щелкает по элементу, он обновляется сам.

Я сделал это сейчас, но, к сожалению, до самой грязной из возможных форм

код активности:

    class SoundListActivity : BaseActivity(), Observer<List<VoiceEntity>>, VoiceAdapter.OnClickItemListener,
    OnMultiSelectVoiceListener {

    private lateinit var viewModel: VoiceViewModel

    private val adapter = VoiceAdapter()
    private val player = MediaPlayer()
    private var positionPlayItem = -1

    companion object {
        fun start(context: Context) {
            context.startActivity(Intent(context, SoundListActivity::class.java))
        }
    }


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

        viewModel = ViewModelProviders.of(this).get(VoiceViewModel::class.java)
        viewModel.mutableList!!.observe(this, this)

        adapter.onItemClickListener = this
        adapter.listenerMultiSelect = this
        recycler.layoutManager = LinearLayoutManager(this)
        recycler.adapter = adapter

        fabAdd.setOnClickListener {
            stopPlay()
            RecordSoundActivity.start(this)
        }

        toolbar.setIconLeftListener(View.OnClickListener {
            stopPlay()
            finish()
        })
    }

    override fun onChanged(list: List<VoiceEntity>?) {
        this.progressBar.visibility = View.GONE
        this.layoutEmptyState.visibility = View.INVISIBLE
        this.adapter.removeAll()

        if (list == null || list.isEmpty()) {
            layoutEmptyState.visibility = View.VISIBLE
            return
        }
        adapter.addItems(ArrayList(list))
    }

    override fun onClickItem(item: VoiceEntity, position: Int) {
        if (player.isPlaying) {
            player.reset()
        }
        if (item.isPlaying) {
            item.isPlaying = false
            player.reset()
            adapter.notifyDataSetChanged()
            return
        }
        this.positionPlayItem = position

        adapter.items!!.forEach {
            if (it != item) {
                it.isPlaying = false
            }
        }

        player.setDataSource(item.path)
        player.prepare()
        player.start()
        item.isPlaying = true
        adapter.notifyDataSetChanged()

        player.setOnCompletionListener {
            player.reset()
            adapter.notifyItemChanged(position)
            item.isPlaying = false
        }
    }

    private fun stopPlay() {
        if (positionPlayItem == -1) {
            return
        }
        player.reset()
        adapter.items!![positionPlayItem].isPlaying = false
        adapter.notifyItemChanged(positionPlayItem)
    }

    override fun onMultiSelectVoice(items: ArrayList<VoiceEntity>) {
        stopPlay()
        if (items.size == 0) {
            layoutSelectItem.visibility = View.GONE
            return
        }
        txtCounterSelect.text = String.format(getString(R.string.selected_number), items.size.toString())
        setStatusBarColor(R.color.black)
        if (layoutSelectItem.visibility == View.GONE) {
            layoutSelectItem.visibility = View.VISIBLE
        }

        if (items.size > 1) {
            imgShare.visibility = View.GONE
            imgEdit.visibility = View.GONE
        } else {
            imgShare.visibility = View.VISIBLE
            imgEdit.visibility = View.VISIBLE
        }

        imgCancelSelect.setOnClickListener {
            resetData()
        }
        imgEdit.setOnClickListener {
            edit(items.first())
        }
        imgShare.setOnClickListener {
            if (items.isEmpty()) {
                return@setOnClickListener
            }
            shareVoice(this, items[0].path)
        }
        imgDelete.setOnClickListener {

            val alertDialog = AlertDialog.Builder(
                supportFragmentManager,
                getString(R.string.note), getString(R.string.do_you_sure_delete)
            )
            alertDialog.setBtnNegative(getString(R.string.no), View.OnClickListener {
                alertDialog.dialog!!.dismiss()
            })
            alertDialog.setBtnPositive(getString(R.string.yes), View.OnClickListener {

                val ex = Executors.newSingleThreadExecutor()
                items.forEach { item ->
                    viewModel.remove(item)
                    ex.execute { File(item.path).deleteOnExit() }
                }
                items.clear()
                layoutSelectItem.visibility = View.GONE
                setStatusBarColor(R.color.colorPrimaryDark)
                alertDialog.dialog!!.dismissAllowingStateLoss()
            })
            alertDialog.build().show()

        }
    }

    private fun resetData() {
        adapter.itemsSelected.clear()
        adapter.items?.forEach { item ->
            item.statusSelect = false
        }
        adapter.notifyDataSetChanged()
        layoutSelectItem.visibility = View.GONE
        setStatusBarColor(R.color.colorPrimaryDark)
    }

    private fun edit(item: VoiceEntity) {
        val bottomSheet = NameBottomSheet(supportFragmentManager)
        bottomSheet.listener = object : NameBottomSheet.OnTitleListener {
            override fun onTitle(title: String) {
                item.title = title
                viewModel.update(item)
                resetData()
            }
        }
        bottomSheet.item = item
        bottomSheet.show()
    }


    override fun onBackPressed() {
        if (layoutSelectItem.visibility == View.VISIBLE) {
            resetData()
            return
        }
        stopPlay()
        super.onBackPressed()
    }
}

код класса адаптера:

    class VoiceAdapter : AdapterRecyclerView<VoiceEntity>() {

    var onItemClickListener: OnClickItemListener? = null
    var itemsSelected: ArrayList<VoiceEntity> = ArrayList()
    var listenerMultiSelect: OnMultiSelectVoiceListener? = null

    override fun getItemLayout(viewType: Int): Int {
        return R.layout.item_voice
    }

    override fun onBindView(
        viewDataBinding: ViewDataBinding,
        viewHolder: ItemViewHolder,
        position: Int,
        viewType: Int,
        element: VoiceEntity
    ) {
        val binding = viewDataBinding as ItemVoiceBinding
        binding.txtTitle.text = element.title
        binding.txtDate.text = element.date.toAgoTime(context!!)
        binding.icPlay.setImageResource(if (element.isPlaying) R.drawable.ic_pause else R.drawable.ic_play)
        binding.seekBar.max = element.duration / 60


        val colorSelectItem =
            ContextCompat.getColor(binding.rootLayout.context, R.color.color_background_select_item_recycler_view)
        val color = if (element.statusSelect) colorSelectItem else Color.TRANSPARENT

        binding.rootLayout.setBackgroundColor(color)

        if (element.statusSelect) {
            changeColorLight(binding)
        } else {
            changeColorDarker(binding)
        }

        if (element.isPlaying) {
            binding.layoutPlaying.visibility = View.VISIBLE
            binding.lottieLayer.playAnimation()

            //TODO : change handled voice progressBar show
            val t = object : Thread() {
                override fun run() {
                    super.run()
                    for (i in 0..element.duration) {
                        Thread.sleep(60)
                        binding.seekBar.progress = i
                        if (!element.isPlaying) break
                    }
                }
            }
            t.start()

        } else {
            binding.layoutPlaying.visibility = View.GONE
            binding.lottieLayer.cancelAnimation()
        }

        binding.rootLayout.setOnClickListener {
            if (itemsSelected.size > 0) {
                val item = items!![viewHolder.adapterPosition]

                if (itemsSelected.contains(item)) {
                    item.statusSelect = false
                    itemsSelected.remove(item)
                    binding.rootLayout.animatedColorBackgroundSelected(false)
                    listenerMultiSelect?.onMultiSelectVoice(itemsSelected)
                    changeColorDarker(binding)
                    return@setOnClickListener
                }

                item.statusSelect = true
                itemsSelected.add(item)
                binding.rootLayout.animatedColorBackgroundSelected()
                listenerMultiSelect?.onMultiSelectVoice(itemsSelected)
                changeColorLight(binding)
                return@setOnClickListener
            }
            onItemClickListener?.onClickItem(element, position)!!
        }

        binding.rootLayout.setOnLongClickListener {

            val item = items!![viewHolder.adapterPosition]
            if (itemsSelected.contains(item)) {
                item.statusSelect = false
                itemsSelected.remove(item)
                binding.rootLayout.animatedColorBackgroundSelected(false)
                changeColorDarker(binding)
                listenerMultiSelect?.onMultiSelectVoice(itemsSelected)
            }
            item.statusSelect = true
            itemsSelected.add(item)
            binding.rootLayout.animatedColorBackgroundSelected()
            changeColorLight(binding)
            listenerMultiSelect?.onMultiSelectVoice(itemsSelected)
            true
        }

    }

    private fun changeColorLight(binding: ItemVoiceBinding) {
        binding.txtDate.setTextColor(ContextCompat.getColor(binding.root.context, R.color.color_subtitle_light))
        binding.txtTitle.setTextColor(ContextCompat.getColor(binding.root.context, R.color.color_title_light))
    }

    private fun changeColorDarker(binding: ItemVoiceBinding) {
        binding.txtDate.setTextColor(ContextCompat.getColor(binding.root.context, R.color.color_subtitle))
        binding.txtTitle.setTextColor(ContextCompat.getColor(binding.root.context, R.color.color_title))
    }

    interface OnClickItemListener {
        fun onClickItem(item: VoiceEntity, position: Int)
    }

}

github хранилище (проект с открытым исходным кодом)

...