Réaction - la méthode de manipulation entraîne Kotlin

Quiconque a utilisé Clean Architecture dans le développement a été confronté au problème du transfert de données entre les couches. L'essence du problème est toujours la même: vous devez renvoyer soit un résultat, soit une erreur. Cela peut être représenté, par exemple, comme ceci:





interface Reaction

data class Success(val data: String) : Reaction
data class Error(message: String) : Reaction
      
      



Selon la tâche, ces réactions peuvent être très différentes, alors combinons-les en une seule classe en utilisant les classes Generics et Sealed .





sealed class Reaction<out T> {
   class Success<out T>(val data: T) : Reaction<T>()
   class Error(val exception: Throwable) : Reaction<Nothing>()
}
      
      



Regardons un exemple de la façon dont il peut être utilisé.





class MyViewModel : ViewModel {
	private val repository: Repository
	
	fun doSomething() {
		viewModelScope.launch(Dispatchers.IO) {
			val result = repository.getData()
			when (result) {
				is Success -> //do something
				is Error -> // show error
			}
		}
	}
}
      
      



. .





class RepositoryImpl(private val dataSource: DataSource) : Repository {
  
	override suspend fun getData(): Reaction<Int> {
		return try {
			Reaction.Success(dataSource.data)
		} catch(e: Exception) {
			Reaction.Error(e)
		}
	}
}

      
      



- , Reaction, try-catch, - . , try-catch .





sealed class Reaction<out T> {

   class Success<out T>(val data: T) : Reaction<T>()
   class Error(val exception: Throwable) : Reaction<Nothing>()

   companion object {
       inline fun <T> on(f: () -> T): Reaction<T> = try {
           Success(f())
       } catch (ex: Exception) {
           Error(ex)
       }
   }
}
      
      



:





class RepositoryImpl(private val dataSource: DataSource) : Repository {

	suspend fun getData(): Reaction<Int> = Reaction.on { dataSource.data }
}
      
      



, 4 .





ViewModel when . , View.





class MyViewModel : ViewModel {
	private val repository: Repository
	private val _onData = MutableLiveData<State>()
	val onData: LiveData<State> = _onData

	fun doSomething() {
		viewModelScope.launch(Dispatchers.IO) {
			val result = repository.getData()
			when (result) {
				is Success -> _onData.postValue(State.Success)
				is Error -> onData.postValue(State.Error(result.message))
			}
		}
	}

	sealed class State {
  	object Progress : State()
  	object Success : State()
  	data class Error(message: String) : State()
	}
}
      
      



RxJava, Coroutines LiveData.

, , ViewModel , , zip, Reaction , LiveData





inline fun <T, R> Result<T>.zip(success: (T) -> R, error: (Exception) -> R): R =
   when (this) {
       is Reaction.Success -> success(this.data)
       is Reaction.Error -> error(this.exception)
   }
      
      



MyViewModel





class MyViewModel : ViewModel {
	private val repository: Repository
	private val _onData = MutableLiveData<State>()
	val onData: LiveData<State> = _onNewDirectory

	fun doSomething() {
		viewModelScope.launch(Dispatchers.IO) {
			repository.getData()
				.zip(
        	{ State.Success }, 
        	{ State.Error(result.message) }
        )
				.let { onData.postValue(it) }
		}
	}

	//...
}
      
      



, ViewModel , . View





:





class MyViewModel : ViewModel {
	//...
	fun doSomething() {
		viewModelScope.launch(Dispatchers.IO) {
			var firstData: Int = 0

			val reaction = repository.getData()
			when (reaction) {
				is Success -> firstData = reaction.data 
				is Error -> {
					onData.postValue(State.Error(reaction.message))
					return@launch
				}
			}

			val nextReaction = repository.getNextData(firstData)
      
			//..
		}		
	}
  
	//...
}
      
      



, callback hell, , Coroutines





class MyViewModel : ViewModel {
  //...
	fun doSomething() {
		viewModelScope.launch(Dispatchers.IO) {
			val firstData = repository.getData()
				.takeOrReturn {
					onData.postValue(State.Error(result.message)
					return@launch
				}
			val nextReaction= repository.getNextData(firstData)
      
			//..
		}		
	}
}
      
      



, :





  • on - Reaction





  • map -





  • flatMap - Reaction





  • doOnSuccess - , Reaction -









Github





3 .





  • Railway Kotlin

    :









    • 1





    :





    • try-catch





    • infix









  • Arrow-KT

    :









    :













    • ,





  • Result (Kotlin)

    :









    :









    • gradle, , Result, Kotlin





Reaction est une bibliothèque légère avec un seuil d'entrée minimal. il se compose de 1 fichier, qui fournit la même puissance que la solution de Kotlin, mais ne contient pas tous ses inconvénients.





Github

https://github.com/taptappub/Reaction/








All Articles