上QQ阅读APP看书,第一时间看更新
The ReactiveCalculator class with coroutines
So far, in the ReactiveCalculator program, we were performing everything on the same thread; don't you think we should rather do the things asynchronously? So, let's do it:
class ReactiveCalculator(a:Int, b:Int) { val subjectCalc:
io.reactivex.subjects.Subject<ReactiveCalculator> =
io.reactivex.subjects.PublishSubject.create() var nums:Pair<Int,Int> = Pair(0,0) init{ nums = Pair(a,b) subjectCalc.subscribe({ with(it) { calculateAddition() calculateSubstraction() calculateMultiplication() calculateDivision() } }) subjectCalc.onNext(this) } inline fun calculateAddition():Int { val result = nums.first + nums.second println("Add = $result") return result } inline fun calculateSubstraction():Int { val result = nums.first - nums.second println("Substract = $result") return result } inline fun calculateMultiplication():Int { val result = nums.first * nums.second println("Multiply = $result") return result } inline fun calculateDivision():Double { val result = (nums.first*1.0) / (nums.second*1.0) println("Division = $result") return result } inline fun modifyNumbers (a:Int = nums.first, b:
Int = nums.second) { nums = Pair(a,b) subjectCalc.onNext(this) } suspend fun handleInput(inputLine:String?) {//1 if(!inputLine.equals("exit")) { val pattern: java.util.regex.Pattern =
java.util.regex.Pattern.compile
("([a|b])(?:\\s)?=(?:\\s)?(\\d*)"); var a: Int? = null var b: Int? = null val matcher: java.util.regex.Matcher =
pattern.matcher(inputLine) if (matcher.matches() && matcher.group(1) != null &&
matcher.group(2) != null) { if(matcher.group(1).toLowerCase().equals("a")){ a = matcher.group(2).toInt() } else if(matcher.group(1).toLowerCase().equals("b")){ b = matcher.group(2).toInt() } } when { a != null && b != null -> modifyNumbers(a, b) a != null -> modifyNumbers(a = a) b != null -> modifyNumbers(b = b) else -> println("Invalid Input") } } } } fun main(args: Array<String>) { println("Initial Out put with a = 15, b = 10") var calculator: ReactiveCalculator = ReactiveCalculator(15, 10) println("Enter a = <number> or b = <number> in separate lines\nexit
to exit the program") var line:String? do { line = readLine(); async(CommonPool) {//2 calculator.handleInput(line) } } while (line!= null && !line.toLowerCase().contains("exit")) }
On comment (1), we will declare the handleInput function as suspending, which tells the JVM that this function is supposed to take longer, and the execution of the context calling this function should wait for it to complete. As I already mentioned earlier, suspending functions cannot be called in the main context; so, on comment (2), we created an async block to call the function.