Android Programming Course - Kotlin, Jetpack Compose UI, Graph Data Structures & Algorithms
"WEBVTTKind: captionsLanguage: enIn this course, you will learn to create anAndroid app using the jetpack compose UI library.Along the way, you will learn about graphalgorithms and data structures.Ryan MK teaches this course.He is a very experienced developer and instructor.What's up everybody?This is Ryan here, and I would like to welcomeyou to my tutorial series on the graph Sudokuapplication.This is an application I wrote primarily torefine my understanding of graph data structuresand algorithms, and the new UI library onAndroid jetpack compose.In this part of the series, I will OverviewThe main goals and topics of the series anddiscuss a few design decisions which may comeas a surprise to you.I will try to keep the public version of theproject source code up to date.And it will be your responsibility to lookat that source code if something becomes deprecatedor stops working.The format of this series is a code alongstyle, which implies that the best way tolearn is to write the code with me as I explainit.For advanced developers, the full source isavailable for direct learning, but you canwatch the videos to clear up any holes inyour knowledge.I use some fairly advanced features of thekotlin language and the timeless principlesof software architecture, so you might learna thing or two.For beginners, it is very important that youfollow along with me in code but at your ownpace.You might not feel like you're making progressat first, but understand that you will bepracticing the skill of writing code evenif you don't yet understand what you're writing.I will also secretly be teaching you how towrite code which is easy to write, read, fix,improve and test.But instead of asking you to memorize thetimeless principles of software design, youwill learn and use them in practice as webuild this application.There are four general topics that This tutorialwill demonstrate graph data structures andalgorithms jetpack compose clean UI architectures,and kotlin language features.We will explore the topic of directed coloredgraphs and my experiments in writing algorithmsto generate solve and unsolved n sized Sudokupuzzles.We will build the entire user interface usingjetpack compose, which allows us to createour UI entirely in kotlin.As opposed to XML views and styles.I will show you how to wire up a simple appusing principles commonly expounded in solidand clean architectures.However, I teach these topics in my own way,so do not expect a bunch of jargon or overengineering.I will also demonstrate how and when to usebasic and advanced features of this beautifulprogramming language.This part of the video is intended more forintermediate and advanced developers.Understanding this design decision is notrequired to complete the tutorial.Throughout this tutorial, you will noticethat apart from compose and proto data store,I use almost no libraries from Android jetpackIn fact, very few third party libraries ingeneral, by relying on kotlin and Java standardlibraries and the Android SDK, my code becomesmore resistant to deprecations and changesin libraries.This is because the Android SDK, and the standardlibraries tend to change less frequently thanthird party libraries, such as those you seean Android jetpack.It also means that some things which librarieslike jetpack viewmodel, jetpack, navigationor help might handle must be hand writtenby us.I actually like that, but you might have adifferent value system.And my goal here is not to discourage youfrom learning these tools if you're interestedin them.With that being said, you might be surprisedat how easy it is to write your own viewmodelnavigation or dependency injection code withoutthem in a small app like this one.This application uses Model View whateverarchitecture, which is my way of saying thatI don't follow anyone else's style.Having studied this topic for many years,I let the project requirements in my understandingof the principles of good software designguide my architecture.In this case, I find that compose is madefor an MVVM based approach, but I added apresentation logic class for a specific reason.This reason is called passive view or humbleobject.Instead of having the view or the view modelmanage the control flow of each screen, Ipulled that logic into a separate class.This class is super easy to write and testbecause it has no third party dependencies.And it prevents my view model from becomingan ugly God object.You should try it sometime.I designed this architecture simply by applyingthe single most important principle of softwarearchitecture, separation of concerns.That's it for this part of the series.Now we begin coding.The domain package represents two things,the most general pieces of information, suchas data classes, constants, and enough Whichthe program must virtually represent.Also, the most general things this programmust do, which the program represents usingfunctions and interfaces.In essence, it is the foundation of any newprogram I rate and I use a repeatable processto design my domain package or module.For a clear and simple introduction to thatprocess.Check out this video on my channel, how todesign information systems and applications.That video is a recording of a talk I gaveto some software engineers in Egypt aboutthat particular topic.Anyways, most of the code in this packageis simple, but it does include a design pattern,which I will introduce now.This package contains several interfaces,which are used to employ the repository designpattern.This pattern is also known as the facade pattern.And the general goal of the pattern is simplerthan its technical definition.The technical definition of the facade orrepository pattern is to hide the detailsof a subsystem, in this case, data storagemechanisms behind an abstraction, in thiscase, an interface.Let's look at a practical example.To make sense out of that definition, ourpresentation logic classes will hold referencesto these repository interfaces, instead ofthe classes which implement the interfaces.This gives several benefits to our presentationlogic classes.They can be built independently of each otherwithout causing a compiler error, they canbe tested with a fake implementation of theinterface without requiring us to change anycode within the presentation logic class.Also, if we decide to use a different implementationof the interface, such as switching from filestorage to a room database, we can also dothat without requiring any changes to thepresentation logic class.These benefits are a result of building softwaresystems, which are loosely coupled.And the repository or facade pattern is aneasy way to promote loose coupling.In fact, interfaces in general tend to promoteloose coupling.Now don't feel the need to use this patterneverywhere.A good general rule is to use them in significantarchitectural boundaries.In this case, I'm using them as a boundarybetween the front end and the back end ofthis application.To start things off, right click on the domainpackage, go to New kotlin file and createa file called difficulty.And that's going to be an enum class.enum classes in kotlin, and Java and variousother languages are useful for creating arestricted set of values.As we'll see later on, you can use sealedclasses in kotlin to create a restricted setof types.In any case, the main benefit outside of justcreating that set of restricted values isthat enums can greatly improve the legibilityof your program.As we'll see in a moment, let's add in ourenum entries.quite obviously, this enum will representthe difficulty of a given Sudoku puzzle.However, we need to add one more thing beforemoving on, we will actually be using somevalues for each of these entries in the algorithmsto basically dictate the difficulty of theSudoku puzzle.So in order to add a value to an enum in kotlin,we need to give it a property or some properties.As you can see, our entries are now read,so obviously, we need to give them some doubles.And that's everything we need to do here.Right click on the main package, go to Newkotlin file for class.And we're going to create a data class calledsettings.settings is our first data model, as I liketo call it or a plain old kotlin object.And as we'll see in a moment, it will containboth the difficulty and the boundary, whichis the size of the Sudoku puzzle.So a four by four Sudoku puzzle will havea boundary of four, a nine by nine will havea boundary of nine.The data keyword when put ahead of a classkeyword basically adds or generates a coupleof helper methods, such as equals hash codeor copy.We'll definitely be making use of copy lateron maybe not in this class, but in some ofthem and others.certain point, we will also make use of thegenerated hash code function.Anyways, this is a really simple class, we'rejust going to add two properties to it.And that's it.Right click on the domain package, go to Newkotlin class or file.And this time, we're going to create a classcalled user statistics.And that's going to be a data class.Now, the purpose of this class is to representthe user's shortest slash best times for solvingany particular difficulty or size of Sudokupuzzle.So we're basically just going to add a wholebunch of properties that are pretty much thesame.Now, one thing you can do in IntelliJ IDEA,or Android Studio is you can just click thereand then hit Ctrl D, however many times youneed and that will copy to a new line.That's basically it for this class.Now, you might be wondering, why are we usinglong here, we're actually storing the timeit takes for the user to complete a particulargame in milliseconds.So that's why we want the long integer value.Again, right click on the domain package,go to New kotlin filer class, and this isgoing to be a data class named Sudoku note.Now, this is where things start to get a littlemore complicated and interesting with ourdata models.So what I'm doing here is I'm representingan individual node in a graph data structure,we're going to talk a lot more about graphdata structures later on when we get to thepart of the tutorial dedicated to it.But just to give you an idea, so we are actuallygoing to be building a directed colored graph.And an important thing here to note is thatin this particular case, this term color reallyjust refers to a number, it's just a valuewe associate in some kind of node.And again, to give you a preview ahead, whenI say graph data structure, a better namefor it would be a network data structure,because that's essentially what it is.It's a collection of nodes, and edges, whichare essentially like lines between the nodesrelationships between the nodes.Anyways, this particular node structure inour data structure is going to have a coloror a value, which is just an integer fromone through nine or one to four, also, including00 represents like an empty Sudoku tile, butthat's more concern of the front end.These notes will also include an X and Y coordinate,so the top left will be x zero y zero, thebottom right will be x eight, y eight, andwe're going to be using Zero Based indexing.So instead of starting from x one to x nine,we just basically subtract that by one.So that's it for that preamble, let's getstarted writing the code.So we'll start with the x and y values.Next, we will add the color which will bea variable because it can change throughoutthe course of execution.Then we will add a Boolean called read onlyand I'll explain what that is after we writeit.Now, the purpose of the read only Booleanhere is quite simple.When we essentially generate and then unsolveda Sudoku puzzle, which is another way of sayingwe create a new Sudoku puzzle then removea certain number of clues to make the gameactually playable and fun.Some of those numbers on the Sudoku boardor in the Sudoku graph data structure willbe read only those are like the given cluesthat the user is not supposed to be able tochange themselves.As we'll see later on.This will also affect the user interface becausewe will draw the read only Sudoku nodes ortiles differently than the ones which theuser can edit.Now, we're not quite done yet, we need tooverride the hash code function which wasprovided by the data class keyword as I discussedearlier, and then we also need to add a functionto get a hash code.Okay, so hash code will have a default implementation,which is based on the values provided up herein the different properties, we're actuallyjust going to do something different.So we're going to type get hash, like that.And this is actually a function that we aregoing to create also, we'll add in two parametershere for x and y.Okay, we're now going to add the get hashfunction, and it's going to be top level,which means it sits outside the brackets ofour Sudoku node class.Okay, let's just implement this function,and then I'll explain what we're doing here.Okay, so let me start by explaining what exactlya hash code or hash value is.So it's essentially some kind of generatedkey or unique identifier based on some kindof algorithm.In this case, I have a very simple algorithm,all I do is multiply the x value by 100.And I leave the y value alone.And I basically just combine those two valuestogether into an integer.Now, the reason why I multiply x by 100, isif I didn't do that in a nine by nine Sudokupuzzle, there would be certain edge caseswhere the even though the X and Y value aretechnically different, the resulting hashcode would not be unique for several differentnodes.Simply put, I'm multiplying by 100 to makethe hash codes unique for every individualtile in the Sudoku puzzle.As for why we're using hash code, in general,I'll try and keep it fairly straightforward.Basically, we're going to be storing eachnode in the graph in a linked hash map.So the hash values will represent the keyfor that hash map.A hash map has key value pairs, in case you'renot aware it, we'll be seeing that in a moment.But this turns out to be really useful becauseour user interface as well will be representingthings in that kind of X and Y coordinatestyle.So just take my word for it.Hash codes are pretty handy in situationswhere you have a large number of elements,and you don't necessarily want to have tomaintain a reference for every individualelement.Instead, we can just retrieve a referenceby getting a hash code.Oh, and before we go, we need to add one morething here, we're going to make this thingimplement serializable.Now essentially, what this does is it allowsus to read and write our Sudoku nodes andalso the whole puzzle to a file.Since we're only going to be storing one puzzleat a time, I didn't really want to use somethinglike a database, it kind of just made moresense to use the file system, and serializableand makes it easier to do that essentially.Okay, we have one final data model to createin this particular package again, right clickNew kotlin file our class, this one's goingto be called Sudoku puzzle.And again, it's going to be a data class.A good way to think of data models, as I liketo call them is that they are virtual representationsof a real world object, in this case, a Sudokupuzzle.The way that I initially designed this classis by asking critical questions about whatconstitutes a Sudoku puzzle.Things like the boundaries, so are there fourtiles per row or column or are there ninetiles for example, we have the difficulty.And most importantly, we have the graph datastructure itself.There's also the elapsed time which the userhas taken to solve a particular puzzle.So let's go ahead and add those propertiesin and then I'll explain some of them theones that need to be explained afterwards.Also, before I forget, let's add in the serializableimplementation here.Okay, so you're probably wondering what buildnew Sudoku is.So what we'll be doing is we're actually goingto be calling a large series of top levelfunctions, which will form all of our differentalgorithms, which are necessary to build andgenerate a new Sudoku puzzle, based on a givensize, which is what boundary represents anda given difficulty.Also, if you're wondering about what's goingon with the linked hash map, which is fullof linked lists, that's kind of a way of representingan adjacency list.Again, I'm going to go into those detailson graph data structures and different waysyou can represent them, or at least how Irepresent them in this particular applicationlater when we get to that particular packageand topic.But for the time being understand this representsour virtual Sudoku puzzle, the last thingwe're going to do is just add in a small littlemethod, which just makes it a little moreobvious and legible how to get ahold of thegraph itself, at least in my opinion.And we're going to use single expression syntax.So I'm just going to type equals graph.Let's create a new interface called I gamerepository.I like to use this naming convention of puttinga capital I in front of the interfaces.And then as we'll see later on, in the persistencepackage, I will add a suffix of I MPL, whichstands for implementation to naturally theclasses which implement this interface.When designing a small to medium scale application,one thing you can do is you can actually conceptuallythink of the functions in your repositoryinterfaces.As use cases themselves, the things we'regoing to be writing here are going to be calledlike save game update game update node, whichis very similar if you're doing like a userstories in the use cases type applicationdesign.So I just wanted to throw that in there.In a more complicated application, where Ineeded to do more coordination of multipledifferent data sources and repositories, Iprobably would have like an interactor, ora use case, as it's commonly talked about,between Martin Fowler or Robert Martin, UncleBob.But in this particular case, in simpler applications,generally speaking, the use case as a classitself, is typically an unnecessary extralayer of abstraction.So with here, we're just going with our presenter,or view model or whatever, talking directlyto a repository.And that is a sufficient amount of abstractionfor an application of this size.Now, how an interface works is that it's verysimilar to a class except as we'll see, ina moment, we're not actually allowed to implementor give a body to the functions that we'llbe writing, we just write what are commonlycalled either abstract functions or functionsstubs.Now there's two important points here.Firstly, the suspend keyword is applied there,because these functions will actually be calledfrom co routine scopes, which exists in thelogic class or the presenter that will bereferencing this particular interface.So that's all we need to do to establish concurrencyfor now.Now, in case you're not familiar, what I'musing here is what's known as a function type.And so what we'll do is we will be actuallypassing in a reference to two functions whichexist in the logic class the presentationlogic will pass those functions in.And then in the repository implementationsthe things which implement this particularinterface, that is how they will call backwith some kind of result, either a successfulresult or a failure.Now you might be wondering, why do we haveunit and then it returns unit which is whatthat arrow means, in this particular case?This is something we kind of have to do inorder for the kotlin compiler to understandexactly what we're telling it to do.So this would be kind of equivalent to passingin void or like basically nothing into thisparticular function, and then returning nothingfrom that particular function.But what it will do is it will signal somethinglike an oncomplete if you have any experiencewith RX Java, where basically we just wantto resume the application successfully whenthis function is called.But this particular function does not actuallyneed to return anything.Later on, we'll see some examples of whenwe actually need to return a value throughour on success function type.Again, you might be wondering what is thedifference between saving a game and updatinga game?Well, essentially, in the update game function,we're going to be wholesale writing an entireSudoku puzzle, which includes an elapsed time,although there are some situations where allwe really need to do is simply update theelapsed time of the game, such as when theuser navigates away from the application.So what I'm doing here is I'm creating sortof specialized functions depending on whatwe want to achieve from the user's point ofview.Now I'm going to demonstrate when we actuallywant to return a value from these particularfunction types.Okay, so for onsuccess, what we're effectivelysaying here is that this particular functionmust be called with some kind of Boolean value,obviously, either true or false when it'scalled in the implementation of this particularsuspending function.Now, basically, what we're doing here is whenthe user updates a single node or tile ina Sudoku puzzle, there's a possibility thatthat might be the final tile in the puzzle.And in that particular case, assuming thepuzzle is correct, and the user has inputted,the final tile, that would signal that thegain is complete.So it might be a little bit confusing here.But onsuccess does not necessarily mean thatthe game itself has been completed.So that's why I'm differentiating there.Okay, now, in this particular case, what we'redoing is when the user returns to an activegame, we obviously want to get a current game.And there is actually an edge case where theuser completes the game, navigates away fromthe application, and then restarts the application.And so that's why we're still passing in thatis complete flag.Here we're going to return obviously, a settingsobject.Let's create another interface.And it's going to be called I gain, data storage.And that's obviously an interface.Now, before we write the interface itself,we're going to do something a little bit different.We are going to create a result wrapper orWell, let's just say it's inspired by an eithermon ad from functional programmers, but noone really cares what functional programmersthink or talk about anyways.Seal classes are truly one of my favoritesimple features of the kotlin programminglanguage.It allows us to create In a restricted setof types, and those types can contain particularvalues, and visca.What this will do And as we'll see in a momentis it allows us to return an object from aparticular function have I gained data storage,and this particular object is capable of representingmultiple different states.So like I showed you before in AI game repository,here, we're representing an error state anda success state as two separate function references.In this example, we're going to be representingboth of those states through a single object.Now, one final point, before we move on, ifyou have, for example, some kind of situationwhere you want to represent just a successcase, so equivalent to just returning unitin onsuccess, what you can do is you can actuallyjust use an object so you could say like objecton complete, etc.But we don't actually do the that in thisapplication.So you don't need to add that in.Now, let's finish offthe interface.Create another interface called I settingsstorage.Now, we're also going to use result wrappershere.So I'm actually going to just copy and pastethis over.And we're just going to rename a few things.Okay, and now we can write the interface.One more interface to go for this package.This one is going to be called pi statisticsif I can spell it repository, and obviously,it's going to be an interface.Now one final point, again, is record is goingto actually affect something in the user interfacebased on whether or not a statistic that getsupdated is a record ie the shortest possibletime of completion for a particular boundaryor size of Sudoku puzzle, and a particulardifficulty.The common package contains code which isreused in a variety of different classes andfunctions.In this part of the tutorial, we will learnabout many different kotlin language features,which are designed for sharing code in anintelligent and efficient way.Topics covered include extension functionsand problem These abstract classes, the openclosed principle, object, Singleton, and coroutine dispatchers.Before we write the code, let's talk aboutthe open closed principle.The OCP is a relatively confusing concept,but I will try to explain it in the clearestway i can to give you my own verbal definition,which we'll break down later.Any commonly reused software entity, whichis expected to change should have a fixedpublic interface, and a way to change itsimplementation.In order for that particular definition tomake sense, there's a couple things that Ineed to unpack.Firstly, when I say software entity, I'm generallyspeaking about a class or a function, butit could be a few other things.So let's examine what I mean by public interfaceand why I argue that it should be fixed ifit's commonly reused.By public interface, I am not speaking ofa Java or kotlin interface specifically, instead,I mean any publicly visible aspect of a classor a function.Since this is an Android tutorial, let ustake the example of the activity class.An activity fits my requirement of being commonlyreused and expected to change over time.So it is a perfect case to think about theOCP.Every subclass of activity must include theonCreate function, which is a part of thepublic interface, which it makes availableto classes which reference it.The reason why we want this public interfacenot to change is very simple.Suppose that the Android platform developerssuddenly decided to deprecate and remove savedinstance, state bundles from all lifecyclefunctions.Because this public interface is used by prettymuch every Android program around this platformupdate would break everyone's code.What I mean specifically is that all activitysubclasses in all code bases, which have notremoved this parameter would not be able tocompile.So this is why I'm talking specifically aboutcommonly reused software entities like activity,and why it is important that their publicinterfaces change as little as possible.Since we've established why fixed public interfacesare really important.The next question is simple.How do we then provide a mechanism or wayfor the implementation of the public interfaceto change?Well, it turns out the kotlin gives you manyoptions to solve this problem.Rather than explain them all, verbally, Iwill teach you how to use them in code.As we build this application, right clickon the common package, and go to new Colinfiler class.And this is actually going to be an abstractclass which they don't give an option forhere.So what we're going to do is type in baselogic, we will add in the abstract keyword.Unfortunately, I don't have the time to explainthe difference between an abstract class andinterface in plain old inheritance.In this particular course, this is somethingI go into and explained very clearly in myother video courses.But what I will do is explain why we're usingan abstract class here instead of an interface.The reason why we would want to use an abstractclass is for situations when we want to sharebehavior.So for example, we'll be writing a functionstub or abstract function, which I want tobe shared across any class, which inheritsfrom base logic.And I also want to share a variable, but thisparticular variable will have to be protectedas opposed to public.And if we were to try and do this using aninterface, then necessarily that particularvalue would be public, we're also going touse a generic type.So I'll show you how to do that.So the syntax for a generic type is to justuse angle brackets.And then you could take quite literally whateveryou wanted between those angle brackets.But my suggestion to you is to not use somethingwhich is already used, hence why I'm usingthis all capitals event.Now, if it doesn't make sense what we're doinghere, it will make more sense when we writethe classes which inherit from base logic.Let's go ahead and finish this off.To briefly explain the intent of this abstractclass.Basically, I'm saying that I want a set ofclasses, the ones which will inherit frombase logic, all of which will have this functionon event.In other words, these classes will handleevents from the user interface.And then as we'll see, we're going to usethis job object which comes from the coroutinesAPI as a way to Cancel child co routines.And also to make each of these logic classesas its own co routine scope.I'll explain that when we get to that particularpart of the tutorial, right click on the commonpackage and create a new kotlin file, whichis just going to be a plain old file, andit's going to be called extensions.gotlands extension functions and extensionproperties are among my favorite featuresof the language as a whole.Without getting too technical here, extensionsallow you to employ the open closed principle,which states that software entities shouldbe open for extension, but closed for modification.If that doesn't make sense, don't worry aboutit is kind of a confusing definition.But it allows us to add new functionalityto existing source code without having tomodify the original source code.Now, this particular file extensions.kt iskind of like a replacement for static utilitiesthat we might have used in Java or somethinglike that.It's really just a place where you stick utilitycode which is used across the application.Let's write our first extension function tosee how this works.The purpose of this particular extension function,obviously it will be used within activitiesis really just syntactic sugar, its way tomake it so that I don't have to type out toastdot make text and supply this message toastdot length long and dot show.Instead, in the activity where we'll be usingactivities, I should say where we'll be usingthis particular extension function, we canjust type make toast, give it whatever stringwe want to display, and it's handled likethat.By making it an extension function of theactivity class, I can use it seamlessly inany activity.Let's write another much uglier utility extensionfunction.The purpose of this ugly little function hereis to take the elapsed time of the given puzzlewhich the user is currently working on, andto attempt to convert it into a value basedon minutes and seconds or a string to displaybased on minutes and seconds.Now, if it takes the user longer than an hour,then we end up just displaying like a genericmore than 5959.Now if you think this code is ugly, in kotlin,I challenge you to write it in Java.Now for beginners, this might not make senseintuitively, but it's important to understandwhat this is referring to.This is actually referring to the long object,which we will be calling dot two time on.That might make a little bit more sense whenwe actually get to using this particular extensionfunction.There's only one more extension, we need toadd, and it's actually going to be an extensionproperty this time.So what I'm doing here is I'm hitting alt,enter on this particular red thing, and thenI'm going to hit Add remaining branches.going to hit alt enter, again, to import our,these are obviously string resources.That's one thing, we're not going to be writingby hand.So hopefully, what you've done is you've goneand grabbed the source code for the startingpoint, which includes things like string resources,right click on the common package again, andwe're going to create a new kotlin interface,which is going to be called dispatcher provider.This interface is very small, what we'll dois we'll write the code and then I'll brieflyexplain what it does.Now, unfortunately, I can't briefly explainwhat a co routine context is.But I can't explain the purpose of this particularclass and how we're going to be using theseco routine contexts.So in most situations, most of the work thatwe're going to be doing within co routinesland is going to take place on the main threador the UI thread.Now, with that being said, there are a fewoperations like writing to a file, which wedon't actually want to occur on the main thread.And that would be a situation where we'regoing to provide the IO context.Now, the actual purpose of this particularinterface is really key here.What we're going to be doing is that if wewanted to hypothetically test any class, whichneeds to use these co routine contexts, ina JVM environment, so not an actual runningapplication, then what we could do is we couldreturn a particular kind of CO routine context,which allows us to test in that particularenvironment.I know that's a lot of technical detail, butI can't really make it a whole lot simplerthan that.However, by using this interface here, whenwe want to use our co routines in the productionenvironment, we can provide the real UI mainthread context for the front end, and thenwe can provide a real dispatcher for the IOthread.To make that even simpler, we're really justmaking the code easier to test.Right click on the common package, go to Newkotlin file or class, this time, it's goingto be an object.And hopefully I can spell this right productiondispatcher provider.Again, what we'll do is we'll write the codehere and then I'll explain how it works afterwards.I'm going to hit alt Enter again.And this is where we will return the actualdispatchers that we'll be using in productionas per the name of this particular object.Now there's a number of reasons why I'm usingthe object keyword here.So basically objects in kotlin are in thisparticular case Singleton's.So that basically means that we will onlyever have one of these production dispatcher,a provider software thingies floating aroundin memory space at one particular time.They're also thread safe, which is importantbecause although co routine is not necessarilya thread, our dispatchers dot main and dispatchers.iohas something to do with threading.And the other thing that an object can dois it can actually inherit from an interface.Now we're not actually going to be writingany unit tests in this particular application,which require the dispatchers but just toshow you What you would do if you wanted tounit test some class which needs to use theseco routine context, what you can do is youcan just instead return dispatchers dot unconfined,and then you would return that for both theIO context and the UI context.And then that is what you would use in likea JVM j unit test environment.The persistence package contains classes andfunctions, which have the role of persistingor storing data beyond the lifecycle of anAndroid process.If you don't know what a process is, it simplymeans a program which is running on a device.Practically speaking, we will store the progresswhich the user has made in the current Sudokugame, as well as the settings for that game,and the user's personal records or statistics,as I call them.Here's a quick look at the architecture ofthe persistence package.The game repository in this situation functionsas a back end decision maker for the two datasources, which coordinates the data sourcesthemselves.Just try to carry out CRUD operations, create,read, update, delete, and either report witha success or a failure if an exception isthrown.The general principle here is to keep thingstogether, which makes sense to be kept togetherto separate what doesn't need to be kept together,and to also use an abstraction or an interface.In any place where the implementation mightchange, I might decide to stop using the localfile storage or proto data store.So hiding these details from the repositoryis not over engineering, but rather a calculateddecision.Speaking of data sources or storage mechanisms,we will use two different mechanisms for storingour data.Firstly, we will store the user's preferredGame Settings and their personal statisticsin protro data store data store provides alightweight and efficient way to store thiskind of data using protocol buffers.Protocol Buffers is a serialization languagesimilar to JSON.However, I find it easier to read than JSON.And fortunately, the library we will use alsocomes with its own protobuf compiler thatwill generate some of the boilerplate codewhich we would otherwise need to write ourselves.We also use the device's file storage to storethe progress of the user in the currentlyactive game.Every Android app is given some memory spaceto store files, which is what we will use.This is done by making all of the domain modelsimplement serializable.And using Java as input and output streamsto read and write objects from kotlin language.So in case you aren't following along withthe tutorial, and you haven't downloaded thestarting point repository, what you're goingto want to do is you're going to want to adda directory called pro tau in the main sourceset, the starting point repository shouldalready have that directory.So just go ahead and right click on it, andgo to new file.And this file is going to be called gain underscoresettings, dot proto, and make sure it's alllowercase.Go ahead and type this in the top of the file.So protocol buffers are essentially like aserialization language.It's very similar to JSON.If you want to look more into it, you canabout what the benefits and the pros and consof using something like JSON.But personally, this being the only projectthat I've used Protocol Buffers in so far,I'm quite happy with it.Okay, so let's just add two more lines.And I'll explain some more from there.Okay, so we'll talk a little bit more aboutthis in a moment.But basically, what's going to happen hereis, we're going to define this protocol buffermessage, as it's called, which is kind oflike a data type for lack of a better term.And what we can do is, so this file will beconsumed by something called the protocolbuffer compiler.And in this case, what we're basically tellingit is that we're going to be generating Javafiles.Now in the generated class files.The protocol buffer compiler is going to basicallyadd whatever we put in the Java package asthe package for the generated Java class file.It's just useful to not mix up your namespacesand stuff like that.And as for the second option, here, Java,multiple files.If you don't have that turned on, then whatcan happen is that basically, the generatedJava files will all be in one single file.We don't really want that, although I'm notsure if it's absolutely integral to gettingthis application to work.Like I say, we're going to go through thispretty practically and I'm not an expert inprotocol buffers.Okay, now, we're going to do Line a messagewhich is kind of like one of the main datatypes for lack of a better term in this particularlanguage.Okay, so let's talk about what we just didhere.So we've defined a message, which in ProtocolBuffers is kind of like a data type or a collectionof fields.And we've done two things.So within the game settings message, we havea 32 bit integers, like a kind of a smallerinteger to represent the boundary of a Sudokupuzzle.So when I say boundary, I mean like a fourby four Sudoku puzzle will have a boundaryof four, a nine by nine Sudoku puzzle willhave a boundary of nine, obviously.And the other thing we did here is we definedan enum in protocol buffers.Now when you're creating these enums, you'llneed like a default value unknown.And then you've got the other values thatthe enum can potentially be.Also notice how in boundary and difficultythe fields above the enum I'm giving it defaultvalues, naturally, those will be like thevalues that the protocol buffer gets pre loadedwith, like the first time you access it.Now, the important thing to understand hereis that assuming you've added the supportfor Protocol Buffers into your build Gradleconfiguration, the proto buffer compiler isgoing to actually generate some Java filesor classes out of this particular message.Okay, so what I'm doing here is I've openedup the completed project, and I'm just havinga look at the file which was generated bythe protocol buffer compiler.And all I really want you to notice here isthat when you're using proto data store, what'sgoing to happen is it's actually going togenerate a Java class for you.Obviously, you can see we have our gain settingsin camel case, which is what we defined asour message.And then we also have that enum defined below.So what does this actually do for us, basically,this is going to allow us to serialize orbasically translate from Java into the protocolbuffer language and vice versa.And it also means that we don't actually haveto create our own plain old Java object inorder to do that.The library is going to generate that forus.But we can still use it in our code, whichwe'll do in a moment, we're going to add onemore proto file.So go ahead and open up the protobuf directory,right click again, go to file.And this one's going to be called user statisticsdot Proto.Alright, so I've just copied and pasted thefirst three lines from the other protocolbecause we'll be reusing them.And we are going to create another messagehere.Now when I say statistics, this is kind oflike my way of talking about the user's personalrecords.So what are the shortest times to completionthat a user has made in solving a particularsize and difficulty in a particular Sudokupuzzle?It's pretty straightforward.So let's just write it out.And there you have it.Now, you might be wondering why I'm using64 bit integers here.So these actual values are going to be storedin milliseconds, which is why I do want the64 bit integer storage there instead of the32 bit integer.I'm not actually 100% sure if that's necessary,but I did that just to be safe, and realistically,it's not really going to eat up that muchextra memory.Okay, so that's it for our protocol bufferfiles.Now, we're going to have to create some protocolbuffer data stores, which is how we're actuallygoing to create and access our protocol buffers.Go ahead and right click on the persistencepackage, go to New kotlin file or class andthis is just going to be a file called datastores.Okay, so before proceeding, you're going towant to go to build and make project.Now the build will probably fail, but allwe really wanted to do is to generate theappropriate Java class out of the protocolbuffer.But if for some reason that doesn't work foryou, just follow along, and eventually itwill work.Okay, so for each protocol buffer based datasource, we're going to need to provide a wayto get ahold of it or create it from context,then the other thing we'll need is a serializer.Go ahead and import everything.And there's two things we need to add intothe delegate here.Okay, so don't worry that it's showing upred will actually write this serializer.Next, so I just wanted to explain what's goingon here.So we're creating a data store object, andit takes the protocol buffer generated Javaclass, which is called Game Settings.And essentially, what this does is it createsa reference which which we can use to eitherstore or retrieve our protocol buffer.Now, you might be wondering what game underscoresetting.pb is, and why it has a differentfile extension than our proto files, to thebest of my understanding game underscore settings.PB is something that's generated after thefact by the compiler, whereas the profileis something we write for the compiler toconsume.But in case I'm wrong on that, then feel freeto flame me on Twitter.The other thing we'll need is a serializer,which takes care of serialization quite obviously.After that, you can just click here, hit altinsert, override methods, and we only needthe methods from the serializer interface.So again, let's read the code and then I'llexplain what I need to explain after the fact.Okay, so I'm going to keep the details herepretty light.So obviously, when we create our data store,it's given the game setting serializer here.And what the serializer does is it helps usto read and write from input streams.So in other words, we're going to be obviouslyreading from a protocol buffer file, and thenthat's going to be serialized, or rather Dserialized into Java, and vice versa.So basically, what the Android team has donefor us here is they've made it a lot easierto handle things like error handling and dealingwith input streams.Because if you've ever worked with input streamsin Java, then you can tell there's, you know,you're probably familiar with a lot of boilerplatecode to do with that.So basically, we do a little bit of boilerplatework here.And it translates to a very simple API, whenwe actually want to read and write with thisparticular tool in the back end, which we'llbe doing in a moment.Okay, now, obviously, we need to write anotherdata store and also serializer for the otherdata type.So this is going to be one of those rare scenarioswhere I do actually just copy and paste becausethere's absolutely nothing new, we're justgoing to change a couple of the words.So this would be one of the points where Iencourage you to have the complete sourcecode open on the side and then that way, youcan do a little bit of copy paste action,like I'm going to do now.And that is our data stores file complete.Now obviously, if you had a whole bunch ofthese, you'd probably want to use separatefiles, but since I only have Have the twoI just decided to stick them in the same file,right click on the persistence package andgo to New kotlin class.This one's going to be called local game storageample.So firstly, we're going to make a constantwhich will represent the name of the textfile that we will be reading and writing thegame data to.Next, we'll create the constructor.So you might be wondering where file storagedirectory comes from.When we create the build logic of this application,which is kind of like my inversion of controldependency injection type stuff, what's goingto happen is we're going to call this onefunction to the Android system, which willreturn us the specific directory from thesystem where we can read and write thingslike files.Let's go ahead and implement the interface.Now, I'm going to try to get through thisrelatively quickly.But one thing I want to explain is that you'llnotice I'm making fairly extensive usage ofhelper functions.The reason for that is just to avoid writingredundant code.Also, as with the other implementations, we'regoing to be using the width context co routinebuilder to do this kind of IO work off ofthe main thread.So what we'll do is we'll call a helper functioncalled update game data, and we'll pass itin the game data.And if that operation happens to be successful,then we'll actually just return the same gameobject that was passed in because it shouldbe consistent.Okay, now we can create the helper.So here, we're going to throw the exceptionso that it'll actually get picked up by thecatch block in the functions that we'll becalling this helper.Now, we're going to be using input and outputstreams, which are part of the Java standardlibrary in order to rate our data to and fromthe file.If you're wondering kind of what this wordstream means, ultimately, what we're actuallydoing kind of at the low level, is we're goingto take our game or Sudoku puzzle object,and we're going to serialize it into basicallya stream or a very long sequence of textualcharacters.And that's what we'll actually be readingand writing from the file.Okay, so two points, you always want to closeyour streams.Also, you might be wondering, how is it thatwe can say dot write object and pass in ourSudoku puzzle, but let's just check the parametershere.So I'm going to hit Ctrl p within the parameterbrackets, and as you can see, it accepts anytype.Now the important thing is that if our differentclasses like Sudoku puzzle and Sudoku nodedid not extend serializable than we wouldn'tbe able to do this without errors.So for update node, it's a little bit different,we're just updating one individual node.So how this is going to work is we're goingto get the old data and then we're just goingto update that individual node.And then we will rewrite the result back tostorage.So get game will be another helper, we write,and what I'm going to do is I'm actually goingto write that one right away.Otherwise, the autocomplete and error handlingstuff will be all over the place.Okay, that's what we need to do there.Now, just a quick reminder here, when we saycolor, and really, whenever anyone talks abouta color in a graph data structure, they'rereally just talking about a number.So in this case, the number represents theactual value placed in a particular Sudokusquare.So it'll be like something from one throughnine, or one through four, depending on theboundary of the Sudokuwill also update the elapsed time.After it's updated, we will write that resultto storage hopefully.And just to keep the front end synchronizedwith everything else, then we will returnthat same game object.Now it has just come to my attention thatI have forgotten to add a particular integercalled color to this particular function whenI wrote it, so let's just go ahead and fixthat now.There we go.And I managed to save the easiest for last.And that's it for this file.Right click on the persistence package, goto New kotlin class, this one's going to becalled game repository info.So in case you jumped ahead, and you aren'tactually familiar with the repository pattern,I actually already explained that in parttwo of this series where I built the domainpackage.In any case, let me just reiterate, reiteratewhat the purpose of this particular classes,it's basically like a bridge and decisionmaker for the backend.Now sometimes you'll have multiple differentrepositories or datasets.In the back end, and it might be a good ideato keep them separate.The reason why I didn't in this particularcase is because the game storage and the settingsstorage are actually inextricably linked.They are by nature closely related.So based on that, and the fact that this isn'tactually a very large application, I choseto put them together within this repository.And then how it will work is that the repositorywill coordinate these two different data sources.Let's start with the constructor and the repositoryinterface.Okay, so as you can see, we have our workcut out for us.So what I'm going to do is I'm going to tryto write the code relatively quickly.And after it's written, I'll explain whatit does.So there shouldn't be anything new in thisparticular function, except for the fact thatwe're making an assignment statement withina control statement, Val current game resultequals etc.We're allowed to do that because kotlin isa beautiful and idiomatic language.This one's actually pretty simple.You know, for the life of me, I don't understandwhy it keeps putting on air on top.I'll explain this function in a moment.So puzzle is complete is actually a functionwhich exists in the computation logic package,which we'll be writing later on, of course,and all it does is exactly what it says.But it will return either a true or a falsebased on whether the puzzle is complete ornot.Hence is complete.Okay, so what I've done here is I've copiedand pasted in the plain language use casewhich describes this particular function.Now, as you can see, it's pretty complicatedto give a basic explanation of what's goingon.And why did this when we request the currentgame, ie when the application starts up, there'sa number of different things that could happen.So for starters, the user could have a currentlyactive game and they just want to retrieveit.It could be the first run of the application,so no game currently exists in storage.And then there are different situations whereerrors could occur along the way.This is something that happens when you'recoordinating multiple different data sources.Now I have my own system of tracking thesedifferent event streams, I use basically lettersand numbers to denote steps and differentpotential event streams.But whatever you do, my suggestion to youis to write this down in plain language firstand then go ahead writing the code.That's what I did this comment above you seehere, I wrote that before I wrote the code.Anyways, let's get started.Okay, so for our first Event Stream, we attemptto retrieve the current game, and that returnedsuccessfully.And then we also want to know whether thecurrent game is complete or not.We can just get rid of oncomplete.And here we go again.So this is obviously the case where the userhas first loaded the application and we wantto create a brand new game.And Looks like I'll have to do this manuallythis time.The autocomplete is not helping me here.But in fairness, we haven't written that functionyet.Okay, I'm just gonna double check that I wrotethat correctly.Now, before I want to move on, I want to explainone thing about my perspective on softwarearchitecture.While sometimes in a simpler application,we can do something like have the presentercoordinate different repositories or backend data sources.In this particular case, there was enoughcomplicated back end logic that I wanted tohave also a decision maker class, which happenedto be this game repository imple on the backend, and part of the purpose of this classis to take care of the logic of coordinatingthese different back end data sources, sothat I can keep the presentation logic classdoing what it's supposed to do, managing presentationlogic, and then I have this class dealingwith this messy kind of almost business logictype stuff here.Anyways, we're not done yet.Okay, so it just occurred to me that I havemissed a function in the interface of a gamerepository.So let's just go ahead and add that in.So what I'm going to do is I'm just goingto copy update game, paste it down below.And what we're going to call this is createnew game.And it's going to take in a settings objectand that's it.So that's actually a helper function thatI created mostly for legibility, let's justgo ahead and add that in right now.Just another quick note here, you'll noticethat I like incredibly long and descriptivenames of everything that's going on.This is largely because I don't have a greatmemory for fine details.So by making these things super long and descriptive,I don't actually have to remember them, Ican just read my code and pretty much understandwhat it does.Even in these complicated situations wherewe have all these different event streamsand interactions occurring, okay, only twomore short functions to go.And that's it for our back end.In the top level of the UI package, we havefour small files, which we will use to createand apply styles, colors, fonts, and so on.One of those files is the global theme forour application.And I will show you how to create both a lightand dark theme for the app in only a few extralines of code.Stay tuned for the end of this section, asI will do a live demo of the different themes.Right click on the UI package and create anew kotlin file, which is going to be calledcolor dot Katie.This file will essentially be a replacementfor colors dot XML, if you're used to workingwith the old resources system, which was basedin XML, let's create a color object.Make sure you import the Compose color class.Okay, so before we proceed, the most importantthing to understand here is how to read theseparticular values.So the first two characters here 0x.This basically tells the compiler, which isthe program that will be reading this codethat this is in fact a hexadecimal number.The second two digits here indicates the alphavalue as a percentage.Alpha is another way of saying transparencyor how opaque something is.The remaining three pairs are the red, blue,and green or RGB values, again in a hexadecimalpercentage, and that's pretty much all thereis to know about these different color values.I've copied and pasted over the rest of thevalues because there's absolutely no pointin either was typing all this out.But also keep in mind that they have somepredefined values such as flack, for example,which you can also make use of right clickon the UI package, and we're going to createanother new kotlin file.And this one's going to be called shape.So in the old view system, when you wantedto do something like creating a backgroundwith rounded corners, or a button or widgetor something like that, you had to createusually something inside of the drawable folder,which was XML based.Again, since this is compose, we can justgo ahead and do that in kotlin instead.And we'll just use some default parameters.Now, this might be your first time seeingthe.dp extension, let's just take a quicklook at the source code.So as you can see, you can basically justappend it to an integer double and variouskinds of numbers.The important thing to understand here isthat this basically tells the Compose frameworkthat we want to use density independent pixels.If you want a more profound explanation ofwhat exactly those are, I strongly suggestyou look into it because it's a little bitcomplicated.Suffice it to say that the idea here is toallow the framework to create values for heightsand widths and things like that would workacross a variety of different screen sizesand form factors.Right click on the UI package, and we're goingto create another kotlin file, this one isgoing to be called type.Now in case you're wondering, when we saytype, we're not really talking about a typesystem, or anything to do with type theory,it has to do with type Pog, Rafi or text andhow this text is styled or presented.So again, this is very much the kind of thingthat we used to do and styles dot XML, we'rebasically going to create a bunch of differenttext styles, which will use throughout theapplication.And then we'll kind of see how to wrap thoseup in a typography object.And then we'll see how to add that typographyobject to our sort of global compose theme.First, let's create a text style.Sometimes we have a situation where we wantto keep a bunch of default values, but wemight want one or two values, which are actuallypassed in as a parameter to create the textstyle object.So I'll show you another way to create thesetext styles using function.Just gonna do some quick copy paste here.And then we can override the color.So again, what I'm going to do for the restof these textiles now that we've seen everythingthere is to see here is I'm going to copyand paste them over.But there is one more thing that's new thatwe need to create in this particular file.Okay, as you can see, we've got a couple differenttextiles here.So the last thing we need to do is createa typography object.So basically, what that's going to mean isthat we're going to assign some of the textstyles that we've created below, which areused in common things like the body text ofa particular feature of the application, buttons,titles, that kind of thing.If that doesn't make sense.Let's just write the code.Make sure you select compose dot material,not kotlin dot txt.Okay, we're just gonna do To more.All right, and the only other thing we needto do is set up our graph Sudoku theme.Right click on the UI package, and we've got,you guessed it another kotlin file.And it's going to be called graph Sudoku themed.So one of the handy little features of jetpackcompose is that it is incredibly easy to createa theme for light and dark modes.As someone who uses generally speaking, darkmode almost always actually really appreciatethis particular feature of compose.The first step in that process is to createtwo different color palettes.Let's start with the light color palette.So some of these properties should probablybe familiar to most Android developers likehaving a color primary.That's how we used to do it also in the oldXML system with colors, or at least that wasa common naming convention.Now, one thing I want to point out here isthat there's a degree to which some of thesemore obscure ones like primary variant surfaceon primary and so forth, I'm really just usingthose because it's convenient, they don'tnecessarily have to mean anything in particular.But the important thing to understand hereis that if there's any different color betweena light theme and a dark theme, we do wantto define it somewhere in here, and then useit appropriate in the composable, which we'llbe learning to do later on.Okay, that was actually supposed to be uppercasethere by convention.And also notice that I've copy pasted overthe dark color palette, because again, there'snothing new going on there.The next step, however, is very important,we're going to create our theme, and it'sactually going to be really, really easy.Here's a little shortcut I learned from afriend, if you want to create a composablefunction really quickly start typing comp,and then hit enter, just saves you a littlebit of time.Now this theme is going to have two parametershere.So before we write the body of this function,I just wanted to discuss these two parameters.So as you can see, we're actually making afunction call is system in dark theme, what'sgoing to happen is this system call will returna Boolean, which will tell us whether theuser has specified if the app is supposedto be in dark mode or light mode.And then the content represents everythingthat will be wrapped inside of this theme.What's important to understand here is thateverything that we put inside of this composable,ie the content will have access to all thesedifferent colors, styles and typography informationfrom within the theme itself.The actual utility of this will make a lotmore sense when we actually write the composable.Just to finish things off, we're going tocreate a material theme composable.And we won't need the lambda expression.So there you have it, it only took a few minutesto create like the color resources and stylesand typography information necessary to renderboth a dark color palette and a light colorpalette for different modes.What I'm going to do is show you a quick demoof what this actually looks like in an application.Here I'm going to be starting the applicationin the light theme.Then I'm going to navigate to the operatingsystem settings and set it to a preferreddark mode.And upon returning we see immediately thatthe application now is using the dark theme.We're now ready to start building our userinterface.The UI components package contains reusableelements of the user interface.Since this is a very small app, the only twosuch elements are a toolbar, and a loadingscreen.One of the great features of compose is thatwe can make our components reusable in differentways.Firstly, if a component needs to be positionedaccording to where it fits in different parentcomposable, or parent screens, we can passin a modifier instead of creating a modifierwithin the child composable.This is worth experimenting with in case youhaven't already.Secondly, it is possible to pass in composableas arguments, which also allows reuse andextension of functionality.In this app, we want different toolbar iconsfor the two different UI screens.And we can achieve this by passing in theicon compostables.From those parent UI screens, you'll see lateron how we can specify and handle differenticons and different click events.Using the same toolbar will also create thisreusable loading screen and later, I willshow you how to animate it, right click onthe UI package and go to new package.And this one's going to be called components.Just a brief explanation here, I've adoptedthis particular convention from the composedsamples repository.So what will go into this particular folderare composable, which will end up being reusableacross a variety of different UI elementsand different screens.In this case, we're going to be creating areusable toolbar, and also a reusable loadingscreen, right click on the components folder,and go to New kotlin file, and this one'sgoing to be called app toolbar.Let's create our functions stub, what I'mgoing to do is I'm going to type co MP andthen the autocomplete will create a composablefunction.This one's going to be called app toolbar.First, let's write the parameter list andI'll explain it a little bit.Make sure you select the compose.ui modifier.Let's start by talking a little bit aboutmodifiers.So modifiers are basically how you can createmost of these styles size and position kindof data for a particular composable.Now there's kind of two different main waysto do this.We could of course, create this modifier anduse it within this widget.But that would be for a situation when thewidget itself is going to be deciding thatkind of information.Since we're using a reusable component here,an app toolbar, which we plan to use in multipledifferent places.In this particular situation, we're goingto pass the modifier into this function, whichis a way of basically saying that the parentcomposable will actually decide where to positionand how to size this particular UI element.The title is pretty self explanatory, butwhat is a little more complicated is the icon.And again, that will be dictated by somethingin the parent composable.That's how I actually make this thing reusableand allow it to handle different icons ordifferent actions when it's clicked.After we finish off this particular composable,I'll show you a quick preview of the actualicon that we'll be using.So hopefully that will make a little bit moresense.The first thing we want to do is overridethe top app bar composable.Let's just pause a moment and talk about differentcolors.So one way to solve this problem would beto hard code some kind of color in here.But in the previous section of this tutorial,we went through the trouble of setting upboth a light and dark theme.So what we're doing here is we're actuallygoing to be using a color which is based onthe theme.Remember in the graph Sudoku theme composable,there was a call to a function which was hissystem and dark theme or something like that.And that's actually going to dictate whichcolor palette we select.So by using material theme colors dot primary,it will automatically inherit the appropriatecolor based on whether we're in light anddark mode.And that would be one reason to avoid hardcoding something in here.In this case, we have a color which will bethe same regardless of whether it's lightor dark mode.So we're just going to add in a text composablewhich is effectively eight Extra view.But if you wanted to add something like alogo for the application in front or afterthe title text, and what you could do is youcould add in a row here and then just addin both the icon and then the text composable.And then you'd be ready to go.Go ahead and import that.This is probably pretty self explanatory.But when we want to inherit style data forparticular fonts and stuff like that, thenthis is how we can do it.Again, this is something super handy.And you only see this in kotlin, certainlynot Java.So what we're doing here is we're explicitlyasking is the application currently in lightmode, and then we're picking a text colorbased on that.This is really just an alternative way ofhanding this conditional UI logic withouthaving to assign something to a theme specifically.Next, we'll deal with alignment.And that's it for the texts composable inour toolbar.So action bar is probably something that willbe more familiar to the older Android developers.But basically think of this is like the iconswithin the toolbar.Generally, they're used for very importantactions in the user interface, like navigatingto a new feature, indicating that you're donedoing something.And note importantly, that this particularlambda function is of type row scope.So basically, what that means is, if you haveseveral action buttons, you can place themwithin these two brackets here, and they willautomatically be lined up like a row.Now all we need to do is just type icon andthen add in the parentheses here.And this is because we're actually going tobe passing this icon in from the parent composable.As I said, moments ago, I just wanted to giveyou a sneak preview of the icon itself.We're not going to be writing it yet, butwe will do so later on.The important thing to understand here isthat we're deciding about how to handle onclick and what this thing actually looks likein the parent composable, we're not actuallydoing it within the toolbar.And by pulling that responsibility out ofthe toolbar, that's how we get the reusabilitythat we want.Right click on the components package, goto New kotlin file, and this one's going tobe called loading screen.Let's create our loading screen composable.The first thing we'll need isa surface.So you might be wondering, why are we usinga surface here in particular, in this case,I really just want like a space surface ofthe UI, which has a particular color and specificdimensions.Here I've set Phil max height to a fractionof point eight F, which is basically sayingI want it to take up most of the width, orsorry, most of the height of the user interface.But I might want some space for somethinglike a an ad banner or something of that nature.Anyways, I basically want an icon or an imagewhich is stacked on top of a progress barwhich will be stacked on top of some kindof like text.So for that kind of situation, obviously we'regoing to want to use a column.Obviously, we'll be centering things.Go ahead and import that.Now I'm noticing it's not improperly importingour I think there's something within the Composelibraries, which basically mimics our so letme just fix those imports before we proceed.As you can see here, I've just copy and pastedit in the our import.And now we're good to go.That's our logo.Here's your progress bar.Okay, so you might be wondering about thispainter thing.So basically, in the alpha version of compose,we had to specify whether it was a vectorasset or a bitmap asset and stuff like that.So we can just use this generic painter resourcething and point it to basically anything inour drawable.And it will actually figure out whether it'sa bitmap or a vector asset.Also, I wanted to point out the copy functionhere.Suppose you have a color and you want to slightlychange the alpha value or you have one ofthese textile objects and you want to makesome kind of change to it.The copy function is super handy for doingthat.In this part of the tutorial, we will createthe event sealed class view model and presenterfor the act of game feature.Before we do that, let us look at a few designdecisions involved in this architecture.The purpose of our presentation logic class,which I call logic, for short, is exactlyas the name implies, it handles the work ofcoordinating the container view model andbackend repositories.If notified of a non stop event, it will alsocancel all co routines, it does not possessany Android platform code, which makes itloosely coupled and very easy to test.I might also consider reusing it for a desktopversion of this app.But we'll see.The purpose of the view model is also to doexactly what the name implies, it is a virtualrepresentation of the user interface, whichthe view observes.In simpler terms, it is a model of the view,it exposes function types, which is a verysimple and easy standing for the observerpattern.In situations where we don't require multipleobservers.Each time our logic class updates the viewmodel, the view model will automatically publishthe new data to the view.Another design decision with this view modelis that it does not extend jetpack view model.There are several reasons for this decision,some of them simple, and some of them quitetechnical.The simple reason is that using jetpack viewmodel creates tight coupling with the Androidplatform.And it has its own set of boilerplate codeand dependencies, which I'm not a huge fanof.In short, it doesn't solve more problems thanit creates in this particular application.And I wanted to practice creating view modelswhich might be usable for kotlin desktop orkotlin.j s.The technical reason why is that in this application,we simply don't need to persist the data acrossactivity instances or process death in orderto have a good user experience.Instead, we just make a fairly cheap callto the Android file system and reload thedata from there if such events occur.Now, before you apply that reasoning in everysituation, understand that reloading datafrom a file system works fine in this application,but should not be considered a suitable replacementfor unsaved instance state in every applicationyou write.If you like the models in save state handle,go right ahead and use it.We also employ the strategy pattern to cleanup the interface which our logic class exposesto the container in the view.Each subclass of the sealed class representsan action that can occur in the view or container.Rather than having a function for every UIevent.We have one function that accepts a singleobject that can represent multiple differentpaths of execution.That's the strategy pattern.Right click On the UI package, and go to newpackage called active game, right click onthis new package, go to New kotlin file orclass, and we're going to create an interface,and it's going to be called active game container.This word container is a technical term.The way I'm using it here is to kind of signifysomething which contains a large portion ofan application or an entire application.In my opinion, a container doesn't usuallydeal much with the business kind of logicof the application.It basically just wires things together andbuilds things and kind of serves as an entrypoint.In the next part of this tutorial, I'll explainwhat we'll actually be using as a container.But by using an interface here, I'm basicallystating quite explicitly that I might changemy mind about what we use as a container.Anyways, it only contains two abstract functions.Right click on the active game package again,and we're going to create a sealed class thistime.And it's going to be called active game event.So as I explained in the above comment, theactive game event sealed class representsevery kind of user interaction of a givenfeature, in this case, the active game feature.This is a very common pattern that I use andwe'll see how it works with our base logicabstract class which we created in the commonpackage.Okay, we are now going to create our viewmodel.Firstly, let's create a small little classhere which will be like a virtual representationof a single tile in a Sudoku puzzle.So obviously, x&y represent the x&y coordinatesof the particular Sudoku tile value will representwhat we talked about in graph data structuresas the color again, it's literally just anumber, I don't know why we need to call ita color.Now it has focused indicates that the userhas clicked on a particular tile, after whichthey can click on one of the input buttonsto change that particular number.And finally, a read only tile you can thinkof as a tile, which is like a given clue inthe puzzle.So therefore, the user is not allowed to actuallychange any read only tiles.So before we start reading this view model,I just wanted to mention a couple of thingshere.As discussed in the introduction for thisparticular section, I didn't actually wantto use any of the jetpack libraries to achievea publisher subscriber relationship betweenthe view model and the view.Now, it turns out that that publisher, subscriberrelationship or pattern is actually quiteeasy to implement.But in this case, I actually found it simplerto just use kotlin function types to achievewhat I would call a poor person's publisher,subscriber pattern or observer pattern.So this really means something simple in practice,although it might look kind of complicatedfor those who aren't really familiar withworking with function types.Our view model will possess these nullablefunction type references.As we'll see in a moment, what we can do iseach time we update the view model from thepresentation logic class, we can then updatethe view by extension by invoking these functiontypes from within the view model.Now, the reason why we're using notables hereis from within the view model.I can never be 100% certain if there is actuallyanything listening.But with that being said, I feel like if Iplayed around with this particular class fora couple of hours, I could probably streamlinea little bit and maybe make some of theseinternal variables private or something likethat.So really what I'm saying here is Feel freeto take this general idea of having a viewmodel, which isn't tightly coupled to Androidjetpack, but also feel free to experimentwith it and see if you can optimize it.So with that out of the way, let's createsome function types.So all of these function types will be prefixedwith sub to ensure good legibility.Active game screen state is actually somethingwe will create in the next part of this tutorial.So just go ahead and leave it glowing redhere.Okay, let me just briefly explain these differentfunction types.So the board state is basically a virtualrepresentation of the Sudoku board.Obviously, the content state basically justmeans three different states.So either we're loading the data, the userhas a currently active game that they're solving,or the user has completed a particular game,we will use this to animate between differentstates in the user interface.Now, timer state has to do with the countup timer, which basically records how longit takes for the user to complete a givenSudoku game.So just to hopefully clear up any confusionhere, timer state will be the actual longvalue in milliseconds representing the timeand then sub timer state is the way that weactually update the user interface after weupdate the new timer state.Let's finish off the rest of these variables.These are quite obviously default values.Next, we'll write a function to initializethis view model.Okay, so let's just pause for a moment.What we're doing here is we're taking thestate of the data as it existed in storage,we're giving it to the view model, and thenwhat we're doing is we're building the viewmodels own virtual representation of thatstate.Now, the view models internal representationswill have things like has focus, which areconcerned specifically of the user interfaceand not necessarily something that I wouldinclude in the original domain model.Also, in case you're wondering, the key valueis basically created from hashing the x valueand the y value.This is something that we covered very earlyon in this tutorial, in case you've jumpedahead.Again, active gain screen state is somethingthat we will create in the Compose part ofthe tutorial.Here, we're binding that data to the viewmodel.And then we will invoke our function typesto update the view assuming it's listening.And that's it for our init function.Now, we just have a few more functions, whichwill be called by our presenter to do variousthings with the state of the view model.So here, we're just updating an individualtile.So what we're doing here is when the userhits a particular tile, that's going to senda message into the presenter, which will havea particular x and y coordinate, and thenthe presenter will call this particular function.And so what it will do is it will look forthe tile which the user clicked on based onthat X and Y value, and set that one to hasfocus equals true.And then for every other tile, we want toset it to false.Otherwise, we could have a situation wherethe user has selected multiple different tiles,which is not something our application issupposed to be allowed to Do and this wouldbe the situation where our back end has determinedthat the current puzzle is complete.Right click on the active game package.And let's create a new kotlin class, whichis going to be called active game logic.Okay, so before we proceed, this is definitelyone of those situations where I strongly suggesthaving the complete source code open on theside while you follow along here.Obviously, I'm going to do my best not tomake any mistakes, but it's possible thatI will make a mistake.Active game logic represents the presentationlogic of this particular feature of the application.As we'll see, it coordinates between the containerthe view model, and then by extension, theview, as well as the back end of the application.Let's start with the constructor.Okay, so just a bit of review before we moveon, for the time being the container willactually be an activity.But there's a possibility in the future, Imight move to using fragments as containersinstead, at this point, I don't really wantto, but we'll just see if that makes sensein the future.But this is the entire reason why I have includedan interface here so that I can change what'sbehind the interface very easily.The view model is pretty clear, we just wroteit.Game repo is where we store the game data.So that includes the game settings as wellas the current progress of the users gamestats.repple is where we store the records for theshortest times to completion of each differentdifficulty and size of puzzle.And if you're wondering what the dispatcheris go back and watch the common package whenwe created that we created this dispatcherprovider and I basically explained what thepurpose of it is there.Base logic is also something that we createdin the common package.And we'll see the function that we inheritfrom that class in a moment.Okay, let's start for a moment about co routines.So one way to think about scopes, whetherwe're talking about co routine scope, or daggeror whatever, is to really just consider thatit's about a life cycle.Now, you're probably wondering, why are wenot making something like a view model ora fragment or an activity, our life cycleclass?Well, in case you haven't noticed by now,I don't like any kind of tight coupling tothe Android platform, if I can avoid it.There's a number of other reasons.But one of the main ones is that because thisclass contains all of the presentation logic,in a sense, it's the head decision maker forthis feature of the application, then, inmy opinion, it makes sense to make it responsiblefor cancellation of any co routines, whichhappened to be currently running as far asthis on event function, which we inherit frombase logic.Well, basically, this is an implementationof the strategy pattern.I won't give you a long and technical explanationhere.It's actually a very simple pattern.But basically, it provides sort of like asingular entry point into this particularclass.So instead of having like a single function,for every event, we have one function, whichtakes in an argument, our active game event,which is capable of representing all the differentevents, and I just find that really cleansup the interfaces between different classes,interfaces is used in the general sense inthat statement.Okay, first, let's implement our co routinecontext.Remember, jobtracker exists in base logic,but we also need to initialize it Okay, nowbefore we proceed, there's something reallyimportant we need to implement which is ako routine timer.As I mentioned before, the active game Screendoes have a count up timer.Now some of you are probably going to be wondering,why didn't I use the Java timer class or theandroids count up timer or whatever it's called.Basically, I did try using those things.And they presented different application breakingproblems.And it turned out to be easiest just to createthis kind of CO routine timer.Okay, so this requires a little bit of explanation,obviously.So we'll notice two different keywords here,which might be unfamiliar to some of you,we have the inline and cross inline keywords.So whenever you see the inline keyword, theeasiest way to understand that is to understandthat it just means copy, paste.And if you want to know what that means incode, then I suggest you decompile some ofyour kotlin code, which uses the inline modifier,and you'll see how the inline function isactually copy and pasted into the call site.Now we have something else going on here,which is a cross inline function type.So before I explain what the cross inlineaction is, let's talk about what this functionactually does.So here we have a pretty standard spin lock,while true.So it's a loop that's going to just endlesslyexecute, it's going to invoke that functiontype, and then it's going to delay for 1000milliseconds.Now, there's a couple different things goingon here.Number one, you have to understand that wewill be delaying this ko routine, but it'snot actually going to block the thread thatit's on, which is of course a big win.Now the other thing that's going on here isaction is going to be a lambda expressionthat we will pass into this particular function.Really the only thing crossing line does isit basically makes it so that in the lambdafunction, which we will pass into this functionhere, we're not allowed to write a returnstatement in that function.So in the most general sense here, what we'redoing is we're taking a preventative step,to avoid a situation where we might accidentallyreturn from within the lamda that we passin here causing unexpected behavior.Now, you're probably wondering, since we havethis endless loop going on, how do we actuallystop this particular core routine?Well, what we're going to do is we're goingto create a job.Let's just do that now.And what we'll do soon is we will actuallyassign this job variable to our start co routinetimer, and that will allow us to cancel it.Let's just write another quick extension functionto do with this timer business and then I'llexplain what it does.In experimenting with the user interface,how to make the timer the least janky or mostaccurate that it could be it turned out thatsubtracting one from the value each time wewrite it to the back end created a more consistenttimer.But one particular edge case is if the valueequals zero, then obviously we don't wantto subtract one from it.Otherwise the timer will say negative oneat first and that just doesn't look very good.Okay, so with all that done, we can get toimplementing the rest of the presentationlogic Okay, so when the user hits an inputbutton, we can have two different situationsthat could occur.In one situation, the user has already selecteda tile, which would become the focus tile.Or it might be that they just hit an inputbutton without actually focusing a tile, inwhich case, we don't really want to do anything.Okay, so if you're wondering about the detailsof game repo, you can go back to the partof the tutorial where we actually build it.Basically, we're going to be creating a lambdato represent the success case, and then anotherlambda to represent like an error exceptioncase, to make that a little bit more legible.I'll just add in a comment here.Okay, so if you're again, wondering how weactually cancel the timer, this is exactlyhow we do it, we cancel the job object.Now we'll write this other function in a moment.Basically, if it's a new record, then we wantto render the user interface slightly differentlythan if it wasn't a record.But before we do that, let's finish off theerror case.So in order to actually know if it's record,we actually need to pass the value back intothe stats repo just to check on that.So I'm going to be honest, the error handlingin this application is not the best, neitheris it really the worst show error Well, forthe time being just actually show a toastmessage explaining that some error occur.Okay, just a quick fix.This is actually supposed to be elapsed timenot timer state.Next, we have on new game clicked.You'll notice a recurring theme here, whichis at any time we want to perform concurrentoperations.So anytime we're working with the back end,we're going to wrap that into a launch coroutine.There's a lot of different ways to work withCO routines.This is just one of the most simple straightforwardways to do it.In my opinion.Okay, sowhat we're doing here is first we're askingthe view model has the user completed thecurrent game, if they haven't, we actuallywant to store the progress the user has madein their current game, when they hit on newgame clicked, because maybe they hit it byaccident, or they want to be able to go backand finish the game or some reason like that.That's right The update with time function.Again, we have success and error cases.Hopefully, that's pretty clear at this point.Next, we'll implement that function.Next, we'll write the cancel stuff function.So basically, the cancel stuff function essentiallycancels every ko routine.Next, we'll write on start.I forgot tomention earlier, the reason why we had anunderscore in one of the functions for iscomplete.It's just kind of a convention for a lambdaargument or parameter, which doesn't actuallyend up getting used.In this case, we're going to use it.Okay, so obviously, this is where we startthe coroutine timer, and we only want to dothat when on start is called.Now, again, I feel like I could have handledthis a little bit better, it kind of goesagainst my rules to consider standard flowthe application as an exception.But basically, what we're going to do hereis in the event that we ask the storage fora current game, and it doesn't actually retrieveanything, generally speaking, this situationis going to occur when the user has run theapplication for the first time, and hence,there wouldn't actually be any data stored.So in that particular case, we would wantto do this.Now, we could also end up here because ofsome kind of legitimate exception, but inthat particular case, I still think navigatingto the new game feature is still actuallya good way to handle that good but maybe notthe best.Next we have on stop.Okay, so onstop is actually tied to the lifecycleof the Android activity or fragment that it'sbound to.So when this function is called, that basicallymeans that we want to save the user's currentprogress and then kind of shut everythingdown.Finally, we have on tile focus.So this would be when a user actually selectsa particular Sudoku tile.Now this function is incredibly complicated,so brace yourself.Okay, I lied.That's actually everything we need to do.In this part of the tutorial, we will createthe user interface for the active game feature.Before proceeding I strongly suggest you watchmy video entitled How to Understand jetpackcompose a beginner's guide to composable andread composition.We will be writing many composable and settingup re composition as well.But that video is made for people who arejust getting started with compose.It explains what a composable is, what readcomposition is and how to avoid doing readcomposition the wrong way.And believe me, it is fairly easy to screwup read composition if you aren't aware ofhow it works.I will link to this video in the pinned commentbelow.This video is full of a ton of information,so please take a look at the timestamps inthe description box below.Topics include basic widgets, such as text,text, button, image, icon, spacer, and dividerlayouts, such as box column row box with constraintsand my favorite constraint layout.Simple transition animations to animate betweena loading screen, active game and a completegame.I also show you how to communicate with ourpresentation logic and our view model usingfunction types and lambda expressions.Before we write the composed code, though,I show you how to set up an activity as acontainer for composable.The process for doing this is almost identicalfor fragments if you prefer them, I also showyou how to write a very simple dependencyinjection extension function, which hidesthe backend details from the front end.Right click on the active game package andgo to new activity and choose an empty activity.And make sure you uncheck generate a layoutfile.And this activity will be called active gameactivity.It will be the launcher activity.Now in case you're wondering why we're usingthis wizard instead of just creating a classfile.The reason is simply that by using the wizardit will add an entry into the manifest sowe don't have to do that.Just to briefly recap the purpose of thisactivity here is as a feature specific container.Let's start by creating a reference to ouractive game logic class.Next, let's implement the active game containerinterface.Click on the red and hit alt enter.For show error, we will use the extensionfunction that we created way earlier on inthis tutorial.Go ahead and import.Also in case you're wondering, this is singleexpression syntax here it basically just replacesthe brackets and return statement with justan equal sign.Next one implement on new game click.Now obviously we haven't created new gameactivity yet so that will show up as red untilwe do.We also need to override two more lifecyclemethods.Here will tell the logic class that everythingis ready to goAnd then we'll also override on stop.And that will obviously signal the logic classthat it's time to cancel things and tear stuffdown.Finally, we just need to add a few lines toon create.First of all, create the view model.Now, this is a really important part, whatwe're going to do next is we're basicallygoing to anchor our composable that we'llbe creating in the next part of this tutorial,to the activity here.This is also something you can call insideof a fragment.Go ahead and import that.Naturally, we're gonna wrap everything inour compose theme.Now, this is a very critically important thingto understand and a very important pattern.So when we create active game screen, we'regoing to pass in a function type, which willserve as our event handler, which is basicallymy way of saying that is the way in whichwe will forward the events, the onClick eventsand stuff like that, that occur in the composableto our presentation logic class.So make sure you pay attention to what I'msaying here, because this is a really importantpart, even if you don't use presenters wood,or whatever.Function types are an excellent way to handleon click events, especially if you combinethem with the strategy pattern, which we discussedin the previous section.Okay, now, if you've never seen a functionreference, I believe it's called basicallywhat we're doing here is we are pointing tothe on event function of the logic class.This really is a function reference.So hopefully, you can understand what I'mtalking about here.We'll also pass in the view model.Now lastly, we actually need to build ourlogic class.So what we'll do is we will write that codein an extension function, but what we cando first is just read it here.And that's everything we need to do in ouractivity.Right click on active game, go to new package,and this package will be called build logic.Right click on that package and go to Newkotlin file or classes is going to be a file.And it's going to be called build active gamelogic.If you've been watching my channel, or livestreams for some time, you'll know that Italk a lot about dependency injection servicelocators.And one of the things I say all the time isthat in a small application, you really don'tneed to use di container, like hilt, dagger,whatever, you can use it.But what I always advise for beginners isto write the code that these things generatefor you, yourself first, so that you understandwhat these frameworks are doing for you.So that's exactly what we're going to do.We're going to write the kind of thing thatthese frameworks generate for you.And in a small application, it's actuallyvery simple code to write.And, of course, it's going to return activegame logic.Okay, let's pause for just one moment here.So in case you're wondering how we get thepath to the storage directory that we canuse for this application, you can call contextdot files dir dot path.Finally, our dispatcher.And that's all we need to do.Right click on the active game feature, andcreate new kotlin file called active gamescreen.First, let's create an enum.This enum represents different states, whichthis feature of the user interface can possess.The actual state is held in the view model,but we will see how we can update our composableUI by binding to the view models functiontypes we created in the previous part of thistutorial.Active game screen represents the root composable.In this hierarchy of composable, it has theresponsibility of setting up the core elementsof the UI, and also animating between them.event handler function type reference is howwe call back to the presentation logic.When the user interacts with the application,it must be passed down to any composable,which has such interactions, we also passin the view model, which is how we actuallygive the data to our UI.In very simple language, whenever we havesome kind of data or state, which may changeat runtime, we want to wrap that data in aremember delegate.This tells the Compose library under the hood,to watch for changes and to redraw the UIif a change occurs.Now mutable transition state is used specificallyfor animations here, so don't use this everywhere.We will see a more general purpose exampleof a remembered state later on.Remember, delegate prepares compose for updates,but we also need a way to actually updatethe value.We do this by binding a lambda expressionto one of the function types which our viewmodel possesses.When one of those functions is invoked inthe view model, the program automaticallyjumps to and executes this code within ourcomposable.This is what actually triggers the re composition.We have a remembered transition state anda way to update that state from the view model.Now we need to set up the transition animationsthemselves.This is where you can get as creative as youlike.In this app.Each content state has its own composableassociated with it.We animate between them simply by changingthe alpha value or transparency.Now it was truly up as red a moment ago, theway I fixed that was to manually import theCompose runtime.So the transition spec tells compose detailsabout what the animation should look like.Essentially, this means we don't have to writeour own mathematical instructions, which isgreat for someone like me who sucks at arithmetic.One option for compose is to use the scaffoldcomposable as a skeleton for your UI.I personally prefer to do this myself, sinceit's not really that difficult, and it doesn'thide anything from me.First, we have our app toolbar.Let's go ahead and create that new game icon.These icons come from the Compose materiallibrary, I highly recommend you use it.This is how we actually trigger an on clickevent.As explained in a previous part of the tutorial,by creating our toolbar icon here and passingit into the app toolbar composable, we makethe app toolbar reusable.Below the toolbar we have the main contentof this screen, which can have three differentstates.Each time a re composition occurs, this onestatement will be executed again.The act of alpha value will change when thetransition animation occurs, thus fading outthe previous content state and fading in thenew one.Obviously, we will create these in a moment.And that's it for our route composable themost complex part of our UI comes from anactive Sudoku game.A nine by nine puzzle has 81 different textscomposable, which is a large number of widgets.The way I went about writing this composablewas to think of each part of the Sudoku gameas a particular layer or element.Be sure to avoid writing God composable bymaking usage of helper functions, which breakdown the UI into the smallest reasonable parts.box with constraints is kind of like a composablewrapper, which gives us information aboutthe height, width and other measurements,we can use that information within its lambdaexpression.We need to know the screen width in orderto determine how wide and tall the Sudokuboard should be.Here we asked for the max width of this constraintlayout.Here we ask for the max width of this layoutcomposable.But we need that value to be in density independentpixels, and it needs to be relative to thedensity of the current screen as well.That's where the two dp extension functioncomes in.And it uses the local density to determinethat value.The margin of the board also needs to changebased on the screen density.I arrived at these values simply by testingthe app on various densities using the emulator.Next, we will write a constraint layout, whichis a totally awesome way to manage dynamiclayouts.Now in order to constrain composable to eachother, we need a way for them to referenceeach other.This is equivalent to setting IDs for XMLviews.First, we create these references and youwill see how to bind them later on.Let's create a layout container for the puzzleboard.Okay, so this is really important see howwe're passing in that reference in the constrainas parameter there.This is how we actually associate a particularcomposable with a particular reference.This box composable will be associated withthe name board.Next we'll create the Sudoku board itself.Again, the boundary is like the size of thepuzzle.So it's either a four by four puzzle or anine by nine puzzle.So boundary would either be four or nine.This is supposed to say size.So the offset here is used to evenly distributethe screen real estate for each Sudoku, tileand grid line.Here's a way to make a mutable state whichis not associated with some kind of transitionanimation.So this is the more general purpose approach.So the first argument here view model dotboard state can be thought of as the initialvalue, never equal policy ensures that evenminor changes in the state like has focusactually triggers a re composition.Again, this is how we actually update thevalue once the view model is updated.As you can see, here, again, I'm making usageof lots of helper functions to break thingsdown.Here we render the text fields which representtiles in the puzzle, they can either be readonly or mutable, thus, meaning that we needto render them slightly differently.So here, we're saying if the user sets a particulartile to a value of zero, we actually justwant to render it as an empty tile.The main idea here is that we're using thex and y values of each individual tile alongwith the offset in order to evenly positioneach tileSo when the user selects a tile, it's goingto become focused and we want to render thattile obviously a little bit different thanan unfocused tile.Now we'll render the read only squares.Next we'll create the board grid.So Sq RT is an extension, which is actuallydefined in the computation logic.In retrospect, I probably should have definedthat in the common package, but it's prettyobvious what it does.So this function here, we'll draw the gridlines that separate the Sudoku puzzles.To make it more obvious to the user whichsub grids are which we draw different bordersto separate the four by four or nine by ninesub grids.This is why we're using modulo here.So this will draw both the vertical and thehorizontal lines.Okay, so we're jumping back into the gamecontent composable to finish it off.below our Sudoku board, we have some differenticons to indicate the difficulty of the puzzle.Next we need a layout container for the countup timer that's great, the timer texts composable.Nowthe default value, it's just empty.Okay, we're back in the game content composable.The last thing we need to do is just add alayout container for the input buttons.Now we're about to hard code some values inhere and that is kind of bad practice.But the reason is that the Compose team deprecatedflow row, which I'm still upset about, andit worked perfectly for this situation, andI've been too lazy to implement flow myself.Hey, at least I'm being honest.In case you're wondering, 0.4 and five dotdot nine will emit a range inclusive of thosevalues.Let's create that composable a spacer is prettyself explanatory, it just takes up some spacein the layout.Next we have the buttons themselves.This text button wrapper allows us to stylea nice looking button instead of just addingon click on a text composable.Alright, that's it for gain content.Now we need to do the game complete contentscreen, which is obviously when a user finishesa game.So this is basically just two images stackedon top of each other, but we're only goingto render one of them if it is actually anew record that the user made.So since we don't actually create the emojievents icon, we can change the color of itusing this color filter thing.Pretty handy.Next, we have to text composable.And that's it.Congratulations.In this part of the tutorial, we will examinethe topic of graph data structures, mostlywith respect to solving Sudoku.Unlike the rest of this tutorial, which ispresented in a code along format, This lessonwill be different.Instead of rewriting all the code, we willlook at the basics of a graph data structure.How I modeled a Sudoku puzzle as a graph datastructure, how I created, tested and improvedmy algorithms to the point where they couldgenerate 100 puzzles in roughly 400 milliseconds.before I proceed, I suggest you read my articleon Free Code Camp, which explains the fundamentalsof software engineering in a clear and accessibleway.That article explains these topics assumingonly that you have some basic coding skills.Let's start by asking a question, what aregraph data structures?The simplest verbal explanation I can thinkof is that they are a family of data structures,which are useful for modeling a bunch of thingswhich are connected in some way.To connect that definition with somethingvisual, you can imagine that the bunch ofthings are a series of nodes or points, andthe connections between them are a seriesof edges, which you can think of as linesconnecting the points.So whenever I say the phrase graph data structure,a better term for most people to understandthis topic is a network data structure.In fact, that is exactly how they are usedin apps like Facebook to represent users andfriends.Google Maps to represent city addresses inthe roads connecting them or Sudoku puzzlesto represent tiles which have relationshipsto each other.According to the game's rules.Pictures and words are fine, but the codeis more important.How do we tell a computer system to virtuallyrepresent a Sudoku puzzle?This process is more concrete than you mightthink, though, it helps to be an expert inthe programming language you're using.In principle, the process is to take all ofthe information you know about the problemyou're solving, ie the problem domain, andstart writing code which describes it.First, we represent a single tile in a Sudokupuzzle with the class Sudoku node.It has a value x and y coordinates and a Booleanto establish whether it can be edited or notby the user.Read Only true would indicate a node whichis a given clue at the start of a new Sudokugame.Now this term color really just means a valuefrom zero to the boundary of the puzzle.So a nine by nine puzzle would have the colorszero to nine.To be honest, I don't like using the termcolor as it confused my hyper literal brain.But please understand that it really is justa number value.And the term color is actually irrelevantin this problem domain.Where the word came from is that this kindof data structure was used to solve a problemthat involved coloring different countrieson a map using a fixed set of colors.We could have just as easily associated thesenumbers with different kinds of sandwiches,but to the computer, it is the same thing.In any case, if you hear me say color, justremember it's a value, it's a number, notliterally a color.Now the data structure itself must includeevery element, as well as the connectionsor relationships between every element.There is no single way to do this, but I arrivedat using a linked hash map datatype from thekotlin standard library.This data type preserves the ordering of itselements, and allows me to find a specificelement based on a hash code.The hash code itself comes from this simplehashing function which generates a uniquekey based on the x and y values of a node.The linked lists themselves represent boththe root node at a given x&y location as wellas any other node which happens to be in thesame row column or sub grid of that root node.The root node will always be the first nodein the list known as the head element.But other than that, we don't care about theordering of the rest of the So after I figuredout how to model a Sudoku game in this way,the next step was to start writing the algorithmsto manipulate my chosen data structure.The first algorithm I wrote was called buildnodes.Its job was to build the skeleton of our datastructure.By adding an element for every tile in thepuzzle.A square size in Sudoku will have n squaredtiles or elements.So the first thing I did was write a unittest to check for that condition.Here we see the first example of the processI used to write these algorithms.I tried to solve the problem one step at atime and to verify the correctness of eachstep as I went.Next, I knew that I needed to create the edgesor relationships between different tiles basedon the rules of the game, nodes would sharea column may not have the same value or colornodes would share a row may not have the samevalue, nodes would share the same sub gridmay not have the same value.Now, we haven't actually added any valuesyet, but we can still build the edges of thegraph using these rules.After looking at a picture of a four by four,nine by nine in 16.By 16 Sudoku puzzle, I was able to determinethat every tile will have the same numberof edges as any other tile, and those numbershappened to be 821 and 40, respectively.At first, the test was failing.But I figured out that a node can be for example,in the same column and subgrid.So I needed in my algorithm to be smarterabout avoiding those kinds of repeats.The previous two algorithms were childsplay.Whereas now we get into some more difficultproblems.The seed colors algorithm caused me huge problemsand took many days to get working properly.The purpose of this algorithm was to providesome initial values, ie seed values to makethe next step in the algorithm easier.At first, I tried to do this by distributingthe values diagonally, which is a relativelysafe way to avoid breaking the rules.But this approach led me to an uneven distributionof initial values.I thought this was a problem and eventuallycame up with a new algorithm that would makehorizontal and vertical passes of the entirepuzzle, allocating numbers in such a way thatwas guaranteed not to break the rules andprovide an even distribution.While I'm proud of this algorithm in a certainway, on a certain level, it's also disgustinglycomplicated and proved pretty difficult totest, I settled on ensuring that it wasn'tcreating an invalid puzzle, and it was allocatinga number of values roughly equal to A quarterof the total number of tiles.If I allocated too many tiles, it would causeproblems though, so I had to include somehard coded edge cases, which I didn't reallylike.Perhaps most important algorithm in this seriesof algorithms is the solver algorithm.The solver algorithm takes in our seated graphand attempts to solve the puzzle from there.Now I had already written a few other solveralgorithms that didn't use graph data structures.So I was curious to see if using a graph wouldactually make this process easier.In some ways it did, but it was still overallquite difficult to write a high performancesolver for n sized Sudoku puzzles.Every algorithm for generating a Sudoku puzzlethat I'm aware of makes usage of three things.brute force random number assignment, checkingif these new assignments create an invalidpuzzle.backtracking when an invalid puzzle is created,or the algorithm is simply not able to allocateany new values without actually breaking therules of the game.The problem with brute force random numberassignment is that it scales very poorly asthe size of the puzzle grows, randomly generatinga four by four Sudoku puzzle is quite easythat way.But even a nine by nine puzzle can take along time if you just use random numbers andbacktracking.There's no way the app would be any good ifthe user had to sit and wait for five minutesjust for the app to generate a new puzzle.As is often the case, the solution to thisproblem came from figuring out the right questionto ask, How do I tell the computer to makesmart decisions about assigning values insteadof just purely random decisions.In the end, I settled on giving the algorithma nice value, which is inspired by nice valuesin CPU scheduling.In principle, the algorithm will select anempty tile and look at the number of possiblevalues we can assign to that tile with respectto the rules of the game.This is done by looking at the rest of theelements in the linked list for that tile,and seeing how many of them are already coloredthat is given a value in a nine by nine puzzleif eight other tiles in the list already havea unique value than the tile we have currentlyselected, can only have one possible correctvalue.If seven tiles are already colored, we havea 50% chance of guessing the correct numberwhich is still pretty good odds.So the nice value represents how picky thealgorithm is in deciding whether or not toassign a value.The nice value itself is adjusted constantlywith the basic idea being two things.If the algorithm has looked at many elementsand could not find a sufficiently safe guess,we increment the nice value, thus allowingthe algorithm to make riskier guesses.If the algorithm assigns a value, it becomespickier again by decrementing the nice value.The other important part of this algorithmis the multistage backtracking.This part was very difficult to figure out,and it required trying a lot of differentapproaches.In order to work smoothly for four, nine and16 boundary puzzles, I settled on using threestages of backtracking.In the first stage, when the algorithm getsstuck, we remove half of the values we haveallocated to the puzzle.In the second stage, we remove all valueswe have allocated to the puzzle, but we keepthe same seated values.In the final stage, we remove all values andgenerate a new seed then reset the algorithmto start from scratch.After playing around with both the nice valuesand the conditions for each stage of backtracking,something magical happened, I made one smallchange to the nice value adjustment.And suddenly, as you can see from my benchmarktests, the algorithm was generating 101 nineby nine Sudoku puzzles in roughly 400 millisecondsinstead of over four minutes.At first, I didn't trust what I was seeing.But after removing the change I had just made,we were right back two minutes instead ofmilliseconds.The key takeaway is that every time I madea small change to the algorithm, I rerun thebenchmarks to see what changed.Tests are absolutely critical when you arewriting new algorithms, as they tell you boththe correctness and efficiency of your code.I was super excited to have a working Sudokusolver that was crushing my benchmarks, butthere was still one more algorithmic dragonto slay.As you can guess a solved Sudoku puzzle isnot actually useful to a person looking tosolve a Sudoku game, which happens to be ourentire user base.Having generated a complete and valid puzzle,the next thing to do was to remove a certainamount of values to make the game playableagain.At first, I thought the difficulty of a Sudokupuzzle was largely dependent on how many initialclues are given to the user.That idea is true at the extremes of a completepuzzle or an empty puzzle, but not so truein the middle.What I mean is that you can definitely havea Sudoku puzzle with 33 given clues that iseasy to solve without guessing and have apuzzle with 38 given clues that is impossibleto solve without guessing.So I suddenly realized that I was going toneed to invent some way of establishing thedifficulty of a Sudoku puzzle in a consistentway.Now, I knew that there must be some way todo this mathematically.But the truth is that mathematics is not anatural way for me to solve problems.I was great at calculus, but only for thereason that I could visualize the graphs whichthe equations described.Instead of trying to model this problem inmathematical terms, I visualize the thingsthat I actually do in order to solve variousdifficulties of Sudoku puzzles.I then figured out how to tell the computerto employ these different strategies to attemptto solve a puzzle without making any randomguesses.This led to creating three kinds of strategieswhich dictate the difficulty of a given puzzle.In the basic solving strategy, a puzzle canbe solved simply by going through each squareand asking if there is only one possible valuethat can be placed in that square based onthe rules of the game.In the advanced strategy, we still use thebasic strategy, but we also look for a situationwhere a node has two possible values, we thenlook for another empty node, which has anedge to the original node that also has thesame possible two values.Finally, we test assigning both values toboth nodes.Three things can occur when this happens ifboth result in a valid Sudoku puzzle.This doesn't actually help much because it'spossible to make valid assignments that stillresult in an invalid puzzle later on.If both result in an invalid puzzle, thisis obviously not a good situation.Finally, if one configuration is valid, butthe other isn't, then logically, the validconfiguration is correct.The final solving strategy basically meansthat the puzzle cannot be solved in a purelylogical way, ie you must make guesses to solveit, or it requires some kind of advanced strategy,which I'm not aware of.I'm not an expert in Sudoku, but I'm betterthan the average player.So either way, I would consider that to bea hard puzzle.\n"