SlideShare a Scribd company logo
1 of 21
Download to read offline
Model View Intent on
Android
Cody Engel
Senior Android Engineer @ Yello
What is Model View Intent?
• Coined by André Staltz, Cycle.js creator
• Split main into multiple parts
• Similar idea to MVP, MVVM, MVC
Why Am I Here?
• Let’s Try Model-View-Intent With Android

goo.gl/3fPSWV
• Flax For Android - Reactive Concept

goo.gl/1JjSpN
• Hello Flax - A Reactive Architecture For
Android

goo.gl/rD2ZVw
The Intent
• Interpret user interactions
• Input: a view which exposes streams of
events
• Output: stream of actions
The Model
• Manage the state of the application
• Input: stream of actions
• Output: stream of state
The View
• Visually represent state from the Model
• Input: stream of state
• Output: stream of events
Model
Intent
MVI Data Flow
View
User Triggers
An Event
Intent Emits
An Action
Model Emits
New
State
View Renders
The State
CODE?
class DrawingActivity : AppCompatActivity() {
val compositeDisposable = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_drawing)
}
override fun onResume() {
super.onResume()
val disposable = DrawingModel(DrawingIntentImpl(drawingView))
.getObservable()
.subscribe {
drawingView.render(it)
}
compositeDisposable.add(disposable)
}
override fun onStop() {
compositeDisposable.clear()
super.onStop()
}
}
onResume
onStop
DrawingModel(DrawingIntentImpl(drawingView))
.getObservable()
.subscribe {
drawingView.render(it)
}
The Model The Intent The View
Called Whenever
State Changes
Where “it” Is The
DrawingState
Emits Drawing State
Changes
interface DrawingIntent {
fun getTouches(): Observable<DrawingPoint>
fun getColorClicks(): Observable<Boolean>
fun getResetClicks(): Observable<Boolean>
}
Emits DrawingPoint
Whenever Touch
Event TriggeredEmits Boolean
Whenever Color Is
ClickedEmits Boolean
Whenever Reset Is
Clicked
class DrawingIntentImpl(private val drawingView: DrawingView): DrawingIntent {
override fun getTouches(): Observable<DrawingPoint> {
return drawingView.getMotionEvents()
.filter { it.action != MotionEvent.ACTION_UP }
.map { DrawingPoint(it.x, it.y, it.size, it.eventTime) }
}
override fun getColorClicks(): Observable<Boolean> = drawingView.getChangeColorClicks().map { true }
override fun getResetClicks(): Observable<Boolean> = drawingView.getResetClicks().map { true }
}
Maps Reset Clicks
To Boolean
Click Events Come
From DrawingView
Maps Motion Events
To DrawingPoint
Only Emit When
MotionEvent Is Not
ACTION_UP
Emits A New
DrawingPoint
Intent Takes A
DrawingView
class DrawingModel(drawingIntent: DrawingIntent) {
private val randomColor = RandomColor()
private val collectedDrawingPoints: ArrayList<DrawingPoint> = ArrayList()
private val defaultColor = "#607D8B"
private var previousState = DrawingState(emptyList(), defaultColor, false)
private val subject: Subject<DrawingState> = ReplaySubject.create()
init {
Observable.merge(
transformTouchesToState(drawingIntent.getTouches()),
transformColorClicksToState(drawingIntent.getColorClicks()),
transformResetClicksToState(drawingIntent.getResetClicks())
).subscribe {
if (previousState != it) {
previousState = it
subject.onNext(it)
}
}
}
fun getObservable(): Observable<DrawingState> = subject
private fun transformColorClicksToState(clicks: Observable<Boolean>): Observable<DrawingState> {
// Transforms Color Clicks Into DrawingState
}
private fun transformResetClicksToState(clicks: Observable<Boolean>): Observable<DrawingState> {
// Transforms Reset Clicks Into DrawingState
}
private fun transformTouchesToState(touches: Observable<DrawingPoint>): Observable<DrawingState> {
// Transforms Touch Events Into DrawingState
}
}
Model Takes A
DrawingIntent
Transform Intent
Actions To State
Transformations
Return DrawingState
Handles Emission Of
New State
Our Activity
Subscribes To This
data class DrawingState(
val drawingPoints: List<DrawingPoint>,
val drawingColor: String,
val redraw: Boolean
)
Collection Of
DrawingPoints To Draw
What Color Our Line
Should Be
Whether Or Not We Need
To Redraw The Drawing
private fun transformColorClicksToState(clicks: Observable<Boolean>): Observable<DrawingState> {
return clicks.map {
DrawingState(collectedDrawingPoints, randomColor.get(previousState.drawingColor), true)
}
}
private fun transformResetClicksToState(clicks: Observable<Boolean>): Observable<DrawingState> {
return clicks.map {
collectedDrawingPoints.clear()
DrawingState(collectedDrawingPoints, defaultColor, true)
}
}
Emits New Drawing State
With Random Color
Emits New DrawingState
With No DrawingPoints
private fun transformTouchesToState(touches: Observable<DrawingPoint>): Observable<DrawingState> {
return touches.map {
var emitState = previousState
collectedDrawingPoints.add(it)
if (collectedDrawingPoints.size >= 2) {
val currentDrawingPoint = collectedDrawingPoints.get(collectedDrawingPoints.size - 1)
val previousDrawingPoint = collectedDrawingPoints.get(collectedDrawingPoints.size - 2)
emitState = previousState.copy(
drawingPoints = listOf(previousDrawingPoint, currentDrawingPoint),
redraw = false
)
}
emitState
}
}
Mutates Our Previous
State To New State
Return Our
emitState
Only Emit New State If
More Than Two
DrawingPoints Exist
interface DrawingView {
fun getMotionEvents(): Observable<MotionEvent>
fun getChangeColorClicks(): Observable<Any>
fun getResetClicks(): Observable<Any>
}
Emits MotionEvent
Whenever User
Touches ScreenEmits Anytime The
User Clicks Change
Color
Emits Anytime The
User Clicks Reset
class DrawingViewImpl(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) :
LinearLayout(context, attrs, defStyleAttr, defStyleRes), DrawingView {
private val paint = Paint()
private val strokeWidth = 10f
private var cachedBitmap: Bitmap? = null
private val changeColorButton: Button
private val resetButton: Button
override fun getMotionEvents(): Observable<MotionEvent> = RxView.touches(this)
override fun getChangeColorClicks(): Observable<Any> = RxView.clicks(changeColorButton)
override fun getResetClicks(): Observable<Any> = RxView.clicks(resetButton)
fun render(drawingState: DrawingState) {
// Renders Our View Based On Drawing State
}
private fun generateDrawingPath(drawingPoints: List<DrawingPoint>): Path {
// Generates The Drawing Path, Called By Render
}
}
Maps To User
Interactions
Renders Our
ViewState
Helper Used To
Generate
Drawing Path
fun render(drawingState: DrawingState) {
if (!isAttachedToWindow) return
if (cachedBitmap == null || drawingState.redraw) {
cachedBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
}
paint.color = Color.parseColor(drawingState.drawingColor)
val drawingCanvas = Canvas(cachedBitmap)
drawingCanvas.drawPath(generateDrawingPath(drawingState.drawingPoints), paint)
background = BitmapDrawable(resources, cachedBitmap)
}
New Bitmap When
We Need To Redraw
Update The Color Of
Our Drawing Line
Draw Our Line Based On
generateDrawingPath
private fun generateDrawingPath(drawingPoints: List<DrawingPoint>): Path {
val drawingPath = Path()
var previousPoint: DrawingPoint? = null
for (currentPoint in drawingPoints) {
previousPoint?.let {
if (currentPoint.time - it.time < 25) {
drawingPath.quadTo(it.x, it.y, currentPoint.x, currentPoint.y)
} else {
drawingPath.moveTo(currentPoint.x, currentPoint.y)
}
} ?: drawingPath.moveTo(currentPoint.x, currentPoint.y)
previousPoint = currentPoint
}
return drawingPath
}
Iterates Over The
DrawingPoints To
Generate A Path
• https://github.com/CodyEngel/MVI
• https://medium.com/@CodyEngel

More Related Content

What's hot

14multithreaded Graphics
14multithreaded Graphics14multithreaded Graphics
14multithreaded GraphicsAdil Jafri
 
MVI - Managing State The Kotlin Way
MVI - Managing State The Kotlin WayMVI - Managing State The Kotlin Way
MVI - Managing State The Kotlin WayZeyad Gasser
 
Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and Firebase
Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and FirebaseGo Beast Mode with Realtime Reactive Interfaces in Angular 2 and Firebase
Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and FirebaseLukas Ruebbelke
 
Introduction to Canvas - Toronto HTML5 User Group
Introduction to Canvas - Toronto HTML5 User GroupIntroduction to Canvas - Toronto HTML5 User Group
Introduction to Canvas - Toronto HTML5 User Groupbernice-chan
 
Introduction to Canvas - Toronto HTML5 User Group
Introduction to Canvas - Toronto HTML5 User GroupIntroduction to Canvas - Toronto HTML5 User Group
Introduction to Canvas - Toronto HTML5 User Groupdreambreeze
 
Awesome State Management for React and Other Virtual-Dom Libraries
Awesome State Management for React and Other Virtual-Dom LibrariesAwesome State Management for React and Other Virtual-Dom Libraries
Awesome State Management for React and Other Virtual-Dom LibrariesFITC
 
The Ring programming language version 1.7 book - Part 59 of 196
The Ring programming language version 1.7 book - Part 59 of 196The Ring programming language version 1.7 book - Part 59 of 196
The Ring programming language version 1.7 book - Part 59 of 196Mahmoud Samir Fayed
 
The Ring programming language version 1.6 book - Part 57 of 189
The Ring programming language version 1.6 book - Part 57 of 189The Ring programming language version 1.6 book - Part 57 of 189
The Ring programming language version 1.6 book - Part 57 of 189Mahmoud Samir Fayed
 

What's hot (9)

14multithreaded Graphics
14multithreaded Graphics14multithreaded Graphics
14multithreaded Graphics
 
MVI - Managing State The Kotlin Way
MVI - Managing State The Kotlin WayMVI - Managing State The Kotlin Way
MVI - Managing State The Kotlin Way
 
Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and Firebase
Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and FirebaseGo Beast Mode with Realtime Reactive Interfaces in Angular 2 and Firebase
Go Beast Mode with Realtime Reactive Interfaces in Angular 2 and Firebase
 
Introduction to Canvas - Toronto HTML5 User Group
Introduction to Canvas - Toronto HTML5 User GroupIntroduction to Canvas - Toronto HTML5 User Group
Introduction to Canvas - Toronto HTML5 User Group
 
Introduction to Canvas - Toronto HTML5 User Group
Introduction to Canvas - Toronto HTML5 User GroupIntroduction to Canvas - Toronto HTML5 User Group
Introduction to Canvas - Toronto HTML5 User Group
 
Awesome State Management for React and Other Virtual-Dom Libraries
Awesome State Management for React and Other Virtual-Dom LibrariesAwesome State Management for React and Other Virtual-Dom Libraries
Awesome State Management for React and Other Virtual-Dom Libraries
 
The Ring programming language version 1.7 book - Part 59 of 196
The Ring programming language version 1.7 book - Part 59 of 196The Ring programming language version 1.7 book - Part 59 of 196
The Ring programming language version 1.7 book - Part 59 of 196
 
Intro to Canva
Intro to CanvaIntro to Canva
Intro to Canva
 
The Ring programming language version 1.6 book - Part 57 of 189
The Ring programming language version 1.6 book - Part 57 of 189The Ring programming language version 1.6 book - Part 57 of 189
The Ring programming language version 1.6 book - Part 57 of 189
 

Similar to Model View Intent on Android

Android Studio (Java)The SimplePaint app (full code given below).docx
Android Studio (Java)The SimplePaint app (full code given below).docxAndroid Studio (Java)The SimplePaint app (full code given below).docx
Android Studio (Java)The SimplePaint app (full code given below).docxamrit47
 
Kotlin Mullets
Kotlin MulletsKotlin Mullets
Kotlin MulletsJames Ward
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in AndroidRobert Cooper
 
MOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentMOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentanistar sung
 
Макс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложенияхМакс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложенияхCocoaHeads
 
Creating custom views
Creating custom viewsCreating custom views
Creating custom viewsMu Chun Wang
 
Events and Listeners in Android
Events and Listeners in AndroidEvents and Listeners in Android
Events and Listeners in Androidma-polimi
 
Game development with Cocos2d
Game development with Cocos2dGame development with Cocos2d
Game development with Cocos2dVinsol
 
Modern Android Architecture
Modern Android ArchitectureModern Android Architecture
Modern Android ArchitectureEric Maxwell
 
Functional programming techniques in real-world microservices
Functional programming techniques in real-world microservicesFunctional programming techniques in real-world microservices
Functional programming techniques in real-world microservicesAndrás Papp
 
Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Korhan Bircan
 
Android Wear Essentials
Android Wear EssentialsAndroid Wear Essentials
Android Wear EssentialsNilhcem
 
BLoC - Be Reactive in flutter
BLoC - Be Reactive in flutterBLoC - Be Reactive in flutter
BLoC - Be Reactive in flutterGiacomo Ranieri
 
This is a C# project . I am expected to create as this image shows. .pdf
This is a C# project . I am expected to create as this image shows. .pdfThis is a C# project . I am expected to create as this image shows. .pdf
This is a C# project . I am expected to create as this image shows. .pdfindiaartz
 
Silverlight as a Gaming Platform
Silverlight as a Gaming PlatformSilverlight as a Gaming Platform
Silverlight as a Gaming Platformgoodfriday
 

Similar to Model View Intent on Android (20)

Android Studio (Java)The SimplePaint app (full code given below).docx
Android Studio (Java)The SimplePaint app (full code given below).docxAndroid Studio (Java)The SimplePaint app (full code given below).docx
Android Studio (Java)The SimplePaint app (full code given below).docx
 
004
004004
004
 
Kotlin Mullets
Kotlin MulletsKotlin Mullets
Kotlin Mullets
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in Android
 
MOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentMOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app development
 
Android 3
Android 3Android 3
Android 3
 
Макс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложенияхМакс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложениях
 
Applications
ApplicationsApplications
Applications
 
Creating custom views
Creating custom viewsCreating custom views
Creating custom views
 
Events and Listeners in Android
Events and Listeners in AndroidEvents and Listeners in Android
Events and Listeners in Android
 
iOS Training Session-3
iOS Training Session-3iOS Training Session-3
iOS Training Session-3
 
Game development with Cocos2d
Game development with Cocos2dGame development with Cocos2d
Game development with Cocos2d
 
Modern Android Architecture
Modern Android ArchitectureModern Android Architecture
Modern Android Architecture
 
Functional programming techniques in real-world microservices
Functional programming techniques in real-world microservicesFunctional programming techniques in real-world microservices
Functional programming techniques in real-world microservices
 
Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)
 
Android Wear Essentials
Android Wear EssentialsAndroid Wear Essentials
Android Wear Essentials
 
BLoC - Be Reactive in flutter
BLoC - Be Reactive in flutterBLoC - Be Reactive in flutter
BLoC - Be Reactive in flutter
 
This is a C# project . I am expected to create as this image shows. .pdf
This is a C# project . I am expected to create as this image shows. .pdfThis is a C# project . I am expected to create as this image shows. .pdf
This is a C# project . I am expected to create as this image shows. .pdf
 
Silverlight as a Gaming Platform
Silverlight as a Gaming PlatformSilverlight as a Gaming Platform
Silverlight as a Gaming Platform
 
React native tour
React native tourReact native tour
React native tour
 

Model View Intent on Android

  • 1. Model View Intent on Android Cody Engel Senior Android Engineer @ Yello
  • 2. What is Model View Intent? • Coined by André Staltz, Cycle.js creator • Split main into multiple parts • Similar idea to MVP, MVVM, MVC
  • 3. Why Am I Here? • Let’s Try Model-View-Intent With Android
 goo.gl/3fPSWV • Flax For Android - Reactive Concept
 goo.gl/1JjSpN • Hello Flax - A Reactive Architecture For Android
 goo.gl/rD2ZVw
  • 4. The Intent • Interpret user interactions • Input: a view which exposes streams of events • Output: stream of actions
  • 5. The Model • Manage the state of the application • Input: stream of actions • Output: stream of state
  • 6. The View • Visually represent state from the Model • Input: stream of state • Output: stream of events
  • 7. Model Intent MVI Data Flow View User Triggers An Event Intent Emits An Action Model Emits New State View Renders The State
  • 9. class DrawingActivity : AppCompatActivity() { val compositeDisposable = CompositeDisposable() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_drawing) } override fun onResume() { super.onResume() val disposable = DrawingModel(DrawingIntentImpl(drawingView)) .getObservable() .subscribe { drawingView.render(it) } compositeDisposable.add(disposable) } override fun onStop() { compositeDisposable.clear() super.onStop() } } onResume onStop
  • 10. DrawingModel(DrawingIntentImpl(drawingView)) .getObservable() .subscribe { drawingView.render(it) } The Model The Intent The View Called Whenever State Changes Where “it” Is The DrawingState Emits Drawing State Changes
  • 11. interface DrawingIntent { fun getTouches(): Observable<DrawingPoint> fun getColorClicks(): Observable<Boolean> fun getResetClicks(): Observable<Boolean> } Emits DrawingPoint Whenever Touch Event TriggeredEmits Boolean Whenever Color Is ClickedEmits Boolean Whenever Reset Is Clicked
  • 12. class DrawingIntentImpl(private val drawingView: DrawingView): DrawingIntent { override fun getTouches(): Observable<DrawingPoint> { return drawingView.getMotionEvents() .filter { it.action != MotionEvent.ACTION_UP } .map { DrawingPoint(it.x, it.y, it.size, it.eventTime) } } override fun getColorClicks(): Observable<Boolean> = drawingView.getChangeColorClicks().map { true } override fun getResetClicks(): Observable<Boolean> = drawingView.getResetClicks().map { true } } Maps Reset Clicks To Boolean Click Events Come From DrawingView Maps Motion Events To DrawingPoint Only Emit When MotionEvent Is Not ACTION_UP Emits A New DrawingPoint Intent Takes A DrawingView
  • 13. class DrawingModel(drawingIntent: DrawingIntent) { private val randomColor = RandomColor() private val collectedDrawingPoints: ArrayList<DrawingPoint> = ArrayList() private val defaultColor = "#607D8B" private var previousState = DrawingState(emptyList(), defaultColor, false) private val subject: Subject<DrawingState> = ReplaySubject.create() init { Observable.merge( transformTouchesToState(drawingIntent.getTouches()), transformColorClicksToState(drawingIntent.getColorClicks()), transformResetClicksToState(drawingIntent.getResetClicks()) ).subscribe { if (previousState != it) { previousState = it subject.onNext(it) } } } fun getObservable(): Observable<DrawingState> = subject private fun transformColorClicksToState(clicks: Observable<Boolean>): Observable<DrawingState> { // Transforms Color Clicks Into DrawingState } private fun transformResetClicksToState(clicks: Observable<Boolean>): Observable<DrawingState> { // Transforms Reset Clicks Into DrawingState } private fun transformTouchesToState(touches: Observable<DrawingPoint>): Observable<DrawingState> { // Transforms Touch Events Into DrawingState } } Model Takes A DrawingIntent Transform Intent Actions To State Transformations Return DrawingState Handles Emission Of New State Our Activity Subscribes To This
  • 14. data class DrawingState( val drawingPoints: List<DrawingPoint>, val drawingColor: String, val redraw: Boolean ) Collection Of DrawingPoints To Draw What Color Our Line Should Be Whether Or Not We Need To Redraw The Drawing
  • 15. private fun transformColorClicksToState(clicks: Observable<Boolean>): Observable<DrawingState> { return clicks.map { DrawingState(collectedDrawingPoints, randomColor.get(previousState.drawingColor), true) } } private fun transformResetClicksToState(clicks: Observable<Boolean>): Observable<DrawingState> { return clicks.map { collectedDrawingPoints.clear() DrawingState(collectedDrawingPoints, defaultColor, true) } } Emits New Drawing State With Random Color Emits New DrawingState With No DrawingPoints
  • 16. private fun transformTouchesToState(touches: Observable<DrawingPoint>): Observable<DrawingState> { return touches.map { var emitState = previousState collectedDrawingPoints.add(it) if (collectedDrawingPoints.size >= 2) { val currentDrawingPoint = collectedDrawingPoints.get(collectedDrawingPoints.size - 1) val previousDrawingPoint = collectedDrawingPoints.get(collectedDrawingPoints.size - 2) emitState = previousState.copy( drawingPoints = listOf(previousDrawingPoint, currentDrawingPoint), redraw = false ) } emitState } } Mutates Our Previous State To New State Return Our emitState Only Emit New State If More Than Two DrawingPoints Exist
  • 17. interface DrawingView { fun getMotionEvents(): Observable<MotionEvent> fun getChangeColorClicks(): Observable<Any> fun getResetClicks(): Observable<Any> } Emits MotionEvent Whenever User Touches ScreenEmits Anytime The User Clicks Change Color Emits Anytime The User Clicks Reset
  • 18. class DrawingViewImpl(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : LinearLayout(context, attrs, defStyleAttr, defStyleRes), DrawingView { private val paint = Paint() private val strokeWidth = 10f private var cachedBitmap: Bitmap? = null private val changeColorButton: Button private val resetButton: Button override fun getMotionEvents(): Observable<MotionEvent> = RxView.touches(this) override fun getChangeColorClicks(): Observable<Any> = RxView.clicks(changeColorButton) override fun getResetClicks(): Observable<Any> = RxView.clicks(resetButton) fun render(drawingState: DrawingState) { // Renders Our View Based On Drawing State } private fun generateDrawingPath(drawingPoints: List<DrawingPoint>): Path { // Generates The Drawing Path, Called By Render } } Maps To User Interactions Renders Our ViewState Helper Used To Generate Drawing Path
  • 19. fun render(drawingState: DrawingState) { if (!isAttachedToWindow) return if (cachedBitmap == null || drawingState.redraw) { cachedBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) } paint.color = Color.parseColor(drawingState.drawingColor) val drawingCanvas = Canvas(cachedBitmap) drawingCanvas.drawPath(generateDrawingPath(drawingState.drawingPoints), paint) background = BitmapDrawable(resources, cachedBitmap) } New Bitmap When We Need To Redraw Update The Color Of Our Drawing Line Draw Our Line Based On generateDrawingPath
  • 20. private fun generateDrawingPath(drawingPoints: List<DrawingPoint>): Path { val drawingPath = Path() var previousPoint: DrawingPoint? = null for (currentPoint in drawingPoints) { previousPoint?.let { if (currentPoint.time - it.time < 25) { drawingPath.quadTo(it.x, it.y, currentPoint.x, currentPoint.y) } else { drawingPath.moveTo(currentPoint.x, currentPoint.y) } } ?: drawingPath.moveTo(currentPoint.x, currentPoint.y) previousPoint = currentPoint } return drawingPath } Iterates Over The DrawingPoints To Generate A Path