diff --git a/samples/tutorial/Tutorial1.md b/samples/tutorial/Tutorial1.md index 8c74716a73..cb0373ce75 100644 --- a/samples/tutorial/Tutorial1.md +++ b/samples/tutorial/Tutorial1.md @@ -23,7 +23,55 @@ Start by creating a new workflow and screen by creating a new file with the [fil ![New Workflow](images/new-workflow.png) ![Workflow Name](images/workflow-name.png) -Follow the same steps using the `Layout Runner (ViewBinding)` template. +The template does not create everything needed. Manually add objects for `State` and `Output`. We'll define `WelcomeScreen` in a moment: + +```kotlin +object WelcomeWorkflow : StatefulWorkflow() { + + object State + object Output + + override fun initialState( + props: Unit, + snapshot: Snapshot? + ): State = TODO("Initialize state") + + override fun render( + props: Unit, + state: State, + context: RenderContext + ): WelcomeScreen { + TODO("Render") + } + + override fun snapshotState(state: State): Snapshot? = Snapshot.write { + TODO("Save state") + } +} +``` + +Use the `Layout Runner (ViewBinding)` template to create a second file. + +![Layout Runner Name](images/layout-runner-name.png) + +```kotlin +@OptIn(WorkflowUiExperimentalApi::class) +class WelcomeLayoutRunner( + private val binding: WelcomeViewBinding +) : LayoutRunner { + + override fun showRendering( + rendering: WelcomeScreen, + viewEnvironment: ViewEnvironment + ) { + TODO("Update ViewBinding from rendering") + } + + companion object : ViewFactory by bind( + WelcomeViewBinding::inflate, ::WelcomeLayoutRunner + ) +} +``` ### Screens, View Factories, and Layout Runners @@ -31,7 +79,7 @@ Let's start with what a "screen" is, and how it relates to views. "Screen" is just the term we use to refer to a value type that represents the view model for a logical screen. Sometimes we'll even use the terms "screen" and "view model" interchangeably. It has no special type. Typically, a screen will be used as the rendering type for the workflow that is responsible for that screen. A screen is usually a data class, since that's the easiest way to make value type-like classes in Kotlin. -For our welcome screen, we'll define what it needs for a backing view model: +For our welcome screen, we'll create a new class and define what it needs for a backing view model: ```kotlin data class WelcomeScreen( /** The current name that has been entered. */ @@ -43,7 +91,8 @@ data class WelcomeScreen( ) ``` -Then we need to create a `ViewFactory` that knows how to create an Android `View` to draw the actual screen. The easiest way to create a `ViewFactory` is to create a layout runner. A layout runner is a class that has a reference to the view and knows how to update the view given an instance of a screen. In a typical app, every screen will have a layout runner. Layout runners can also work with AndroidX `ViewBinding`s, which we'll use to define the `WelcomeLayoutRunner`. We have a pre-built `WelcomeViewBinding` that you can use. This binding will be autogenerated from layout files in `tutorials-views` when you first build the app. However if you would like to create and lay out the view yourself instead, feel free to do so! +Then we need to create a `ViewFactory` that knows how to create an Android `View` to draw the actual screen. The easiest way to create a `ViewFactory` is to create a layout runner. A layout runner is a class that has a reference to the view and knows how to update the view given an instance of a screen. In a typical app, every screen will have a layout runner. Layout runners can also work with AndroidX `ViewBinding`s, which we'll use to define the `WelcomeLayoutRunner`. We have a pre-built `WelcomeViewBinding` that you can use. This binding will be autogenerated from layout files in `tutorials-views` when you first build the app. If Android Studio does not automatically find the file, you can manually import it `import workflow.tutorial.views.databinding.WelcomeViewBinding +`. However if you would like to create and lay out the view yourself instead, feel free to do so! ```kotlin class WelcomeLayoutRunner( @@ -87,8 +136,6 @@ object WelcomeWorkflow : StatefulWorkflow() // … - object Output - override fun render( renderProps: Unit, renderState: State, @@ -141,7 +188,7 @@ Right now, the workflow isn't handling any of the events from the UI. Let's upda All workflows have a `State` type that represents the internal state of the workflow. This should be all of the data for which *this* workflow is _responsible_. It usually corresponds to the state for the UI. -Let's model the first part of state that we want to track: the login `username`. Update the `State` type to include a username property. We will also need to update `initialState` to give an initial value: +Let's model the first part of state that we want to track: the login `username`. Update the `State` to a `data class` and include a username property. We will also need to update `initialState` to give an initial value: ```kotlin object WelcomeWorkflow : StatefulWorkflow() { diff --git a/samples/tutorial/Tutorial2.md b/samples/tutorial/Tutorial2.md index b09ab1d7bf..6f12fccfa0 100644 --- a/samples/tutorial/Tutorial2.md +++ b/samples/tutorial/Tutorial2.md @@ -304,7 +304,7 @@ Workflows can only communicate with each other through their "properties" as inp Our welcome workflow has a login button that doesn't do anything, and we'll now handle it and let our parent know that we've "logged in" so it can navigate to another screen. -Add an action for `onLogin` and define our `OutputT` type as a new `data class LoggedIn` to be able to message our parent: +Add an action for `onLogin` and change our `OutputT` type from `Output` to a new `data class LoggedIn` to be able to message our parent: ```kotlin diff --git a/samples/tutorial/images/layout-runner-name.png b/samples/tutorial/images/layout-runner-name.png new file mode 100644 index 0000000000..9f7b46921e Binary files /dev/null and b/samples/tutorial/images/layout-runner-name.png differ diff --git a/samples/tutorial/images/workflow-name.png b/samples/tutorial/images/workflow-name.png index 946af512e7..8eda0ad9d6 100644 Binary files a/samples/tutorial/images/workflow-name.png and b/samples/tutorial/images/workflow-name.png differ