I am using MVI design pattern with Coroutines in my app. But the functions inside viewmodelprovider keep on trigerring which results in issues such as UI keeps refreshing all the time when the app is in foreground and crashing when the app is closed. See my codes below:
Fragment :
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
class PinFragment : Fragment(),
InflatableFragment by InflatableFragmentDelegate(R.layout.fragment_pin) {
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
/*override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_pin, container, false)
}*/
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
tv_otp!!.showSoftInputOnFocus = false
with(ViewModelProvider(this).get(PinViewModel::class.java)){
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
for (model in models){
createShufflePins(intents)
fillPinKeyboard(model)
enterPins(intents)
populateOtpView(model)
}
}
}
iv_back.setOnClickListener {
tv_otp.text = tv_otp.text.toString().dropLast(1)
}
}
private fun enterPins(intents: Channel<PinIntent>) {
tv_one.setOnClickListener {
lifecycleScope.launch {
intents.send(EnterPin(tv_one.text.toString()))
}
}
tv_two.setOnClickListener {
lifecycleScope.launch {
intents.send(EnterPin(tv_one.text.toString()))
}
}
tv_three.setOnClickListener {
lifecycleScope.launch {
intents.send(EnterPin(tv_one.text.toString()))
}
}
tv_four.setOnClickListener {
lifecycleScope.launch {
intents.send(EnterPin(tv_one.text.toString()))
}
}
tv_five.setOnClickListener {
lifecycleScope.launch {
intents.send(EnterPin(tv_one.text.toString()))
}
}
tv_six.setOnClickListener {
lifecycleScope.launch {
intents.send(EnterPin(tv_one.text.toString()))
}
}
tv_seven.setOnClickListener {
lifecycleScope.launch {
intents.send(EnterPin(tv_one.text.toString()))
}
}
tv_eight.setOnClickListener {
lifecycleScope.launch {
intents.send(EnterPin(tv_one.text.toString()))
}
}
tv_nine.setOnClickListener {
lifecycleScope.launch {
intents.send(EnterPin(tv_one.text.toString()))
}
}
tv_zero.setOnClickListener {
lifecycleScope.launch {
intents.send(EnterPin(tv_one.text.toString()))
}
}
}
private fun populateOtpView(pin: PinModel) {
if (pin.typedPin!= null){
val otp = tv_otp.text.toString()+""+pin.typedPin
tv_otp.text = otp
}
}
private fun createShufflePins(intents: Channel<PinIntent>) {
lifecycleScope.launch {
intents.send(
RequestSufflePins("")
)
}
}
private fun fillPinKeyboard(model: PinModel) {
if (model.pinNumbers.isNotEmpty()) {
val pinNumbers = model.pinNumbers
tv_one.text = pinNumbers.elementAt(0)
tv_two.text = pinNumbers.elementAt(1)
tv_three.text = pinNumbers.elementAt(2)
tv_four.text = pinNumbers.elementAt(3)
tv_five.text = pinNumbers.elementAt(4)
tv_six.text = pinNumbers.elementAt(5)
tv_seven.text = pinNumbers.elementAt(6)
tv_eight.text = pinNumbers.elementAt(7)
tv_nine.text = pinNumbers.elementAt(8)
tv_zero.text = pinNumbers.elementAt(9)
}
}
override fun onResume() {
super.onResume()
}
}
ViewModel :
class PinViewModel(
val models: Channel<PinModel> = Channel(1),
val intents: Channel<PinIntent> = Channel(1),
private val coroutineScope: CoroutineScope = CoroutineScope(SupervisorJob()+Dispatchers.IO)
): ViewModel() {
init {
coroutineScope.launch {
models.send(PinModel())
for (intent in intents){
when (intent){
is RequestSufflePins -> requestShufflePins(intent)
is EnterPin -> enterPin(intent)
}
}
}
}
private suspend fun enterPin(intent: EnterPin) {
val typedPin = intent.typedPin
models.send(PinModel(typedPin = typedPin))
}
private suspend fun requestShufflePins(intent: RequestSufflePins) {
val response = getShuffledPins(intent)
models.send(PinModel(response.pinNumbers))
}
private fun getShuffledPins(intent: RequestSufflePins): PinModel {
var pinNumbers = setOf("0","8","6","4","2","1","3","5","7","9")
pinNumbers = pinNumbers.shuffled(Random()).toSet()
return PinModel(pinNumbers = pinNumbers)
}
public override fun onCleared() {
coroutineScope.cancel()
intents.cancel()
models.cancel()
super.onCleared()
}
}
Model Class :
data class PinModel(val pinNumbers: Set<String> = setOf(),val typedPin: String? = null)
Intent Class :
sealed class PinIntent
data class RequestSufflePins(val a: String):PinIntent()
data class EnterPin(val typedPin: String): PinIntent()
Aucun commentaire:
Enregistrer un commentaire