<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: David</title>
    <description>The latest articles on Forem by David (@davidsprogrammingadventures).</description>
    <link>https://forem.com/davidsprogrammingadventures</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F149866%2Fe8949f38-2fd8-4670-a3c4-424545679d5c.jpg</url>
      <title>Forem: David</title>
      <link>https://forem.com/davidsprogrammingadventures</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/davidsprogrammingadventures"/>
    <language>en</language>
    <item>
      <title>Quick Example of Abstract Classes in TypeScript</title>
      <dc:creator>David</dc:creator>
      <pubDate>Fri, 15 Sep 2023 04:00:36 +0000</pubDate>
      <link>https://forem.com/davidsprogrammingadventures/quick-example-of-abstract-classes-in-typescript-c06</link>
      <guid>https://forem.com/davidsprogrammingadventures/quick-example-of-abstract-classes-in-typescript-c06</guid>
      <description>&lt;p&gt;&lt;strong&gt;In this example we abstract a Card class so we can have Playing cards or Joker Cards&lt;br&gt;
If we were to go further we could create a Game class that accepted one or more of the Card types depending on the game, blackjack, poker, war, etc…&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Interfaces are not required for abstract classes, but can be useful for setting up a root blueprint&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface ICard {
  value: number;
  getValue: ()=&amp;gt;number;
  compareTo: (o: ICard) =&amp;gt; boolean;
  toString: () =&amp;gt; string;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abstract class can instantiate its own methods and variables or declare them as required for classes that extend from it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abstract class Card implements ICard {
  value: number;
  constructor(value: number){
    this.value = value;
  }
  getValue(){
    return this.value;
  }
  compareTo(o: Card){
    return this.getValue() &amp;gt; o.getValue();
  }


  // abstract keyword is used to tell classes that extend this class
  // that they have to implement this method
  abstract toString(): string;
}

// Enum is just for setting the type in the next class PlayingCard
enum SUIT {
  Diamonds,
  Clubs,
  Spades,
  Hearts,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Extending an abstract class means we only have to implement the methods of Card that are marked abstract after that we can customize the methods to fit our needs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class PlayingCard extends Card {
  suit: SUIT;

  constructor(value: number, suit: string){
    // since we are extending an abstract class we need to instantiate the   
    // Card class in the constructor with super();
    super(value);
    this.suit = this.convertStringToSuit(suit);
  }

  private convertStringToSuit(suit: string){
    switch(suit){
      case "Diamonds":
        return SUIT.Diamonds;
      case "Clubs":
        return SUIT.Clubs;
      case "Spades":
        return SUIT.Spades;
      case "Hearts":
        return SUIT.Hearts;
      default:
        throw new Error();
    }
  }

  private convertSuitToString(){
    switch(this.suit){
      case SUIT.Diamonds:
        return "Diamonds";
      case SUIT.Clubs:
        return "Clubs";
      case SUIT.Spades:
        return "Spades";
      case SUIT.Hearts:
        return "Hearts";
      default:
        return "";
    }
  }

  toString(): string {
    return String(this.getValue()) + " of " + this.convertSuitToString();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A new class based on Card class that has a unchanging value, but its own color method
class JokerCard extends Card {
  color: string;
  constructor(color: string){
    super(14);
    this.color = color;
  }

  toString(): string {
    return String(this.value) + " " + this.color;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instantiating and using both of the classes example&lt;/p&gt;

&lt;p&gt;Card is the Abstract class so now we can technically store multiple types of Card objects into a single array&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const cards: Card[] = [];
cards.push(new PlayingCard(1, "Diamonds"));
cards.push(new JokerCard("Black"))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Due to shared Logic between the abstract class Card and PlayingCard and JokerCard the compareTo method is available for comparing the playingcard and JokerCard class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log(cards[0].compareTo(cards[1])); 
// returns false as 1 is not greater then 14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The toString method is also allowed no matter which class object as both were required to implement it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log(cards[0].toString()) 
// prints "1 of Diamonds"
console.log(cards[1].toString()) 
// prints "14 Black"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’ve also implemented this in an online editor to see the working example and edit it goto &lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgJIGE5QCbIN4BQyxyAbnADYCuEAXMiFQLYBG0A3ESQOYRgBqlGvQAUASgC8APkasOXYggD2TAA5YIAFSWidaTDjHJpyFkqUUIcEJxLIwSgMpgoobqKMmAzi7ecAvgQEcCw+UIhgyAgUcF5eyAa4wGqWTBDg8RhYuIR25NR0DMxsULYkyiBhVAgOUCL5wkVyUGK5diRgABbAXgB0DSgSZEIQZcSBCsi8AiPibe3IUHxUUCD23X0DY8gTdspqGtoieomtk3ZLYCtrXT2904IF4shSyEr3fI804tu7JCFhCL2Jy+EDccT0MJ+AgTdLMZCOACqqE0+EmABFgHAmEoQNgvAAaSboaihIl2RzqbAQQmTAASVigYFpgWisXiAAUYgBPNyJZAQAAekDx8X582QXiowDA9CRKM4kwqVRqSjqA3oshKBMl0tlktB3DOC2IUtU0HqIzE2zstz6UplxnWdwqpGgYGcrjB2kcepEDrA1smf2Iqlc5EgUVxbqZnrcPr9AchhuNJq8AHcZQhOv69amTeVYigAESY7G4-HF2jnAskS7XBHIzS9Ms40U2k0IIvIYskqihKs12uLZarRso3p90IdhZdrwlylwaleQfDhb1sfy5uL5cz9pzksMrDM1dri6jtZb3pHplePd2anwKgUWVD2tdKBKdMMCDfgCiUCfnUQYFoEdghsgYbABGKCuu6voyj6hpzG+GZZjmdq9AG+a1ge47Nq2FZeNWZ7nlcY6llibaVvehbzvhk6ksRb4Fhuay9kxxa0Yo3ZXjuNIkaRxBsT2-ErtxUS8U216MsyglCSJxY3ieEmPnAz6vkJwkXj2XFvmBJAQQ4cZghCBpetwaKsTpJngphDyzGIRgANQ9m8MBua5mFwbGepIRZPzBjCQRsnEyAAFJKAA1tA-JCiK+IJNkVnlBYarJhZ2zKi41S1CIygUOl5luDhdhmhaACMAAsIEmt5aVQE6BVqr8QS2iCAViBlbgpeuNnIZhAwuW5xbIF5Gy9M1pRBRM2WSTgxFJTgADaAC6TprZwXYLb0qhUF4OYgL+yBcnAvJgokIgVTqlHlqKxZOVt2R9HtB0iEd36RTFUCXcWABCMQIFFD1iAQyoWBAvSFeC234stAAMq1BuDlhQ0oMPPQjq2TSo6hLEcsNeMtFVI8juJeBDaMYwtWO9MZyFOWD5OU9D+WYyTdMdW44ig8QQA"&gt;Card abstractions&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Thoughts about IOS and Android Native development</title>
      <dc:creator>David</dc:creator>
      <pubDate>Fri, 04 Feb 2022 10:07:34 +0000</pubDate>
      <link>https://forem.com/davidsprogrammingadventures/thoughts-about-ios-and-android-native-development-4pi0</link>
      <guid>https://forem.com/davidsprogrammingadventures/thoughts-about-ios-and-android-native-development-4pi0</guid>
      <description>&lt;p&gt;In Oct of 2019 I passed the Google Android Developer Certification Test. I was super excited at the time as it would help open doors to many high paying Android jobs, so I kept constantly building apps to boost my portfolio.&lt;/p&gt;

&lt;p&gt;The first job offer I accepted however was not in Android, it was with React and while I tried hard to keep building Android apps when I had free time, It slowed down greatly.&lt;/p&gt;

&lt;p&gt;Then in 2021 a local non profit business came to me with an interesting proposition for an app they wanted. This app would require me to design layouts, implement a backend, and finally after all this time work in Android again. There was a catch though I also had to build an IOS version for their Iphone clients. So the following list is a few of my thoughts regarding Android and IOS and the possibility of a multiplatform tool.&lt;/p&gt;

&lt;h4&gt;
  
  
  Update(11-29-2022) System Design Note
&lt;/h4&gt;

&lt;p&gt;This project uses a 2 layer distributed architecture with client side caching, remote Authentication and document based persistent datastore Firebase allowing for Horizontal scaling and growth. &lt;br&gt;
Built to handle 3000 concurrent users or approximately 200 unique teams per Geographical region.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiplatform thoughts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Kotlin multiplatform appears great on the surface, but that is only if you are using it like a backend service for fetching, storing and sending data. As soon as I tried to use libraries designed to supoort either Android or IOS native there were lots of road blocks and a large lacking of documentation for implementing them with kotlins multiplatform.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;React native and flutter would have been an ok choice, but they do have a lot less control of what you can do with the apps and occassionally you need native platform level depth quality and they just didn't have it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Native Platforms for Android and IOS thoughts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  SwiftUI/IOS
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Love this language and documentation, its object oriented and has a plethora of examples making it very easy to find what you need most of the time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Probably should have refreshed myself with the kotlin/android side of phone apps before jumping into IOS. The biggest reason being patterns and principles can be applied accross platforms when the platforms are similar and your knowledge is up to date.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SwiftUI doesn't always let you know when and why a library feature was deprecated, so supporting multiple software versions of IOS can become tricky. Especially if they haven't updated official tutorials from apple regarding that libraries usage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I really like the swiftui preview, but during minor errors like syntax and not seeing it update can be frustrating since they can hide the errors even after hitting rebuild.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not having a local db for IPhone like Android can, was surprising. Swifts struct and Observable pattern is great when you get used to it, but coming from the Android side of things it felt like magic for a while for persisting data between pages.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Android/Kotlin
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I chose Kotlin as it was becoming more popular and compiles down into Java, I can say I am fairly impressed at how much simplier it was then using pure Java.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After having a fairly good time with swiftui, I became frustrated with some of Androids methods, especially the build dependencies needed to use jet pack libraries, which I thought would be part of the Android ecosystem by now.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libraries are becoming a pain to deal with, there is a major repo that is forcing everyone to convert their artifacts to a new location because they are shutting down, and since the most popular libraries haven't migrated for some tools its hard to find replacements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation regarding patterns, I like the MVVM pattern and learned it from Google's tutorials and as I was implementing, my app kept kept getting more complicated so I tried out other patterns like repository pattern alongside of MVVM. the biggest issue with some of the new patterns is they are limiting, if I use the repository pattern to handle network calls and update my local DB it becomes difficult to notify my user when an error has occurred. Of course you can pass down fragment application context to the repository in order to populate toasts, but at that point I might as well just be doing the network call closer to the fragment in the View Model. So in summary the patterns can be useful, but tutorials should be more in-depth with real world practices to overcome the limits of said pattern.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Bonus Firebase/Firestore, Google Analytics, and Google Admobs
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Firebase is a really nice site that allows you to see your backend services easily.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Firebase authentication and library helpers is well documented for both IOS and Android making it quick to implement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Firestore takes a minute to learn, but after getting used to a document storage instead of pure sql is and the helpers it provides for protecting your DB, it is something I would recommend all phone app developer to use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Google analytics sounds great but does almost nothing for helping find real time crashes, apparently you have to sign up for crashalytics seperately and may not even be worth it without the custom log statements from google analytics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Admob is an interesting service, I liked how easy it was to implement in a central location on SwiftUI/IOS but I didn't like how on Android I was re-typing my admob unique key in multiple places.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Thank you for reading
&lt;/h2&gt;

&lt;p&gt;I appreciate you taking the time to read, these are just some of my thoughts I wanted to write out as I am coming up to the completion of my current project and it felt nice to get them off my chest. &lt;/p&gt;

</description>
      <category>ios</category>
      <category>kotlin</category>
      <category>swiftui</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>A great blog post about senior programmer roadblocks</title>
      <dc:creator>David</dc:creator>
      <pubDate>Fri, 04 Feb 2022 09:24:21 +0000</pubDate>
      <link>https://forem.com/davidsprogrammingadventures/a-great-blog-post-about-senior-programmer-roadblocks-52mo</link>
      <guid>https://forem.com/davidsprogrammingadventures/a-great-blog-post-about-senior-programmer-roadblocks-52mo</guid>
      <description>&lt;p&gt;&lt;a href="https://levelup.gitconnected.com/this-is-why-most-programmers-fail-to-become-senior-developer-143bc8c1342d"&gt;https://levelup.gitconnected.com/this-is-why-most-programmers-fail-to-become-senior-developer-143bc8c1342d&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Mediator Pattern Self Created Documentation</title>
      <dc:creator>David</dc:creator>
      <pubDate>Mon, 18 Jan 2021 04:32:58 +0000</pubDate>
      <link>https://forem.com/davidsprogrammingadventures/mediator-pattern-documentation-2jb1</link>
      <guid>https://forem.com/davidsprogrammingadventures/mediator-pattern-documentation-2jb1</guid>
      <description>&lt;h1&gt;
  
  
  About Mediator
&lt;/h1&gt;

&lt;p&gt;Mediator is a UI/UX pattern for building components and interacting with Api Calls, by using the Mediator pattern the UI/UX can maintain a micro-service architecture for easier testing and reusability.&lt;/p&gt;




&lt;h4&gt;
  
  
  Graph Representation of Data Flow
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x9ExYqnI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uhfd4wdatndz6ywqvhbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x9ExYqnI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uhfd4wdatndz6ywqvhbp.png" alt="Alt Text" width="497" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example we have both the GRPC Api and a mock Api which imitates the GRPCApi. This allows us to test our components and logic without having to repeatedly hit the backend methods by simply calling the MockApi instead.&lt;/p&gt;




&lt;h4&gt;
  
  
  ApiMediator Example
&lt;/h4&gt;

&lt;p&gt;The ApiMediator is where we define our class definition and functions. Below is an example implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AnimalMediatorExample&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnimalApi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;animal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AsyncActionRunner&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;changedAnimalsCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ObservableValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnimalApi&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;getBigCat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AsyncAction&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getBigCat&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// returns Promise.resolve({name:"lion", legs: 4});&lt;/span&gt;
      &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// optional method&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;changedAnimalsCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;changedAnimalsCount&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;getSmallCat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AsyncAction&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getSmallCat&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// returns Promise.resolve({name:"bobcat", legs: 4});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;changedAnimalsCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;changedAnimalsCount&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;AsyncAction&lt;/code&gt;s: extend the functionality of &lt;code&gt;Promise&lt;/code&gt;, they are able to retry and cancel the execution.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AsyncActionRunner&lt;/code&gt;: extends &lt;code&gt;ObservableValue&lt;/code&gt; to handle only Asynchronous Values.&lt;br&gt;
To do this it executes &lt;code&gt;AsyncAction&lt;/code&gt;s and notifies any party of the status of that action. &lt;code&gt;AsyncActionRunner&lt;/code&gt; stores the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;status: "initial" | "pending" |  "success" | "error" | "disabled"&lt;/li&gt;
&lt;li&gt;value: &lt;code&gt;{ name: string, legs: number } // From AnimalMediatorExample&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;error: any&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These properties can be updated indefinitely, and can be subscribed to in the the components.&lt;br&gt;
For more information on &lt;code&gt;Observables&lt;/code&gt; and &lt;code&gt;Subjects&lt;/code&gt; see &lt;a href="https://rxjs-dev.firebaseapp.com/guide/observable"&gt;RxJs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;note: AsyncActionRunner does trigger component re-renders every time it updates.&lt;/em&gt;&lt;/p&gt;


&lt;h4&gt;
  
  
  ApiProvider Example
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AnimalMediatorExample&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./AnimalMediatorExample&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MockApi&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./MockApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IApi&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./IApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AnimalContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AnimalMediatorExample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MockApi&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;api&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;IApi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AnimalProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mediator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AnimalMediatorExample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AnimalMediatorExample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MockApi&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;mediator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mediator&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnimalContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mediator&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/AnimalContext.Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;AnimalProvider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the &lt;code&gt;AnimalProvider&lt;/code&gt; we create a Context that can be passed to any children components, this is similar to instantiating the class &lt;code&gt;AnimalMediatorExample&lt;/code&gt; and saving it to a local const so that we can access the properties and functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React Example Usage for &lt;code&gt;AnimalProvider&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AnimalProvider&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./AnimalProvider&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CatComponent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./CatComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AnimalProviderWrapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnimalProvider&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;//or can pass in as a prop an Api to override the MockApi &amp;lt;AnimalProvider api={AnimalApi}&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CatComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/AnimalProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would ensure that &lt;code&gt;&amp;lt;CatComponent /&amp;gt;&lt;/code&gt; has access to the AnimalMediator context.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://reactjs.org/docs/context.html"&gt;More information on React Context can be found here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Functional Components Using Mediators Data from Context Provider Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAsyncValue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@operator/shared/utils/mediator/hooks/useAsyncValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AnimalContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./AnimalProvider.tsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CatComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mediatorContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AnimalContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bobCat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAsyncValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mediatorContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getSmallCat&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;//useAsyncValue returns the value insde of the promise { name: 'bobcat', legs: 4 }&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;I&lt;/span&gt; &lt;span class="nx"&gt;Have&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;pet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;bobCat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;note: useAsyncValue is a custom hook built to retrieve the value inside of a Promise&lt;/em&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Notes on writing Tests for components
&lt;/h4&gt;

&lt;p&gt;Jest will occasionally throw a strange error with our new mediator pattern, the error details are usually not very clear but a few things that can help clear up where the problem is coming from is by wrapping the test component in a context and ensuring it is provided a mockapi.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;getSmallCat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;mockImplementation&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}]),&lt;/span&gt;
  &lt;span class="na"&gt;getBigCat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;mockImplementation&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}]),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Should Display Animal Component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnimalProvider&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mockApi&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CatComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/AnimalProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Mediator Principles
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Single Responsibility Principle
&lt;/h3&gt;

&lt;p&gt;Mediators should have one responsibility and do it well.&lt;/p&gt;

&lt;h3&gt;
  
  
  YAGNI -You aint gonna need it
&lt;/h3&gt;

&lt;p&gt;Mediators don't need a bunch of type converters to pass the data to the component. I've noticed adding to many converters and methods clutters up the simplicity of the mediator pattern.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>react</category>
    </item>
    <item>
      <title>Rich Dad Poor Dad Lessons Learned Notes Part 4 (final)</title>
      <dc:creator>David</dc:creator>
      <pubDate>Thu, 26 Sep 2019 22:55:55 +0000</pubDate>
      <link>https://forem.com/davidsprogrammingadventures/rich-dad-poor-dad-lessons-learned-notes-part-4-final-fj2</link>
      <guid>https://forem.com/davidsprogrammingadventures/rich-dad-poor-dad-lessons-learned-notes-part-4-final-fj2</guid>
      <description>&lt;p&gt;⦁ Intelligent people hire and are around more intelligent people then them.&lt;br&gt;
⦁ Learn to sell, just because you have a masters in writing doesn't mean your books will be the best selling. To do that you also need to learn how to sell.&lt;br&gt;
⦁ Learning a little about a lot helps you make better decisions about what is important and what is not.&lt;br&gt;
⦁ When you want to earn more money take a long look at your life and look into getting a second skill. Education is more valuable in the long run.&lt;br&gt;
⦁ Life is liking going to the gym, the most painful part is the decision to go.&lt;br&gt;
⦁ Skills do not neccessarily transfer from industry to industry.&lt;br&gt;
⦁ Rule of thumb for highly speccialized careers can be highly specialized then unionized, because unions protect highly specialized people.&lt;br&gt;
⦁ Taking a course in sales and direct marketing can increase your value in any career, profession, or life goal acomplishments.&lt;br&gt;
⦁ Being able to sell yourself/skills is the base of success.&lt;br&gt;
⦁ The better you can handle communication and fear of rejection the better your life is.&lt;br&gt;
⦁ To recieve money you have to give money.&lt;br&gt;
⦁ When you want to become rich faster think like a texan, win big or lose big, but still keep going.&lt;br&gt;
⦁ One of the greatest reasons for failure is lack of taking risks.&lt;br&gt;
⦁ You can always turn a financial lose into a financial win.&lt;br&gt;
⦁ Dont be buried by your failures, become inspired by them.&lt;br&gt;
⦁ If you have little money and you want to be rich you have to be focused and make progress untill you can become balanced.&lt;br&gt;
⦁ Building assets takes guts, patience, and passion.&lt;br&gt;
⦁ Never say "I cant afford it" always ask "How can I afford it". This makes the human mind stronger.&lt;br&gt;
⦁ Guilt is worse then greed, cause guilt robs the body of its soul.&lt;br&gt;
⦁ Pay yourself first, and then pay everyone else. This forces you to work harder to make sure you have enough.&lt;br&gt;
⦁ Forcing yourself to think about making money, builds strength in your mind about finances.&lt;br&gt;
⦁ There's gold everywhere, most people are not trained to see it.&lt;br&gt;
⦁ Don't listen to poor or frightened people, as they can always tell you why something wont work, but not everything they say is true.&lt;br&gt;
⦁ Always listen to both sides of the debate, but make your decisions logically and without emotion.&lt;br&gt;
⦁ Wise investors don't buy when things are popular, they get in early.&lt;br&gt;
⦁ First learn the formula then put in the effort to use that formula. Knowledge without practice does nothing.&lt;br&gt;
⦁ It's also now what you know that matters, but how fast you can learn something new.&lt;br&gt;
⦁ Self discipline and fortitude is important to now let the world pull you around.&lt;br&gt;
⦁ Don't dip into savings our liquidate stock to pay for consumar debt. Use the pressure to inspire you to make more money.&lt;br&gt;
⦁ Savings are only used to create more money, not to pay bills.&lt;br&gt;
⦁ Pay people well, cause real professionals service will make you money.&lt;br&gt;
⦁ A broker is your eyes and ears in the market, they are there everyday so you don't have too.&lt;br&gt;
⦁ There is a tremendous difference between a broker who just sells and and a broker who practices what they do. Always ask if they own large amounts of what ever they sell themselves.&lt;br&gt;
⦁ Reward the people who are smater then you, a board of directors helps everyone make more.&lt;br&gt;
⦁ Look at your assets extras after you get your money back.&lt;br&gt;
⦁ Find heroes, look up to people who already have and do what you want. Learn from your heroes.&lt;br&gt;
⦁ Teach and you shall recieve. If you want something you first need to give.&lt;br&gt;
⦁ Stop doing what you're used to and look for something new, then take action.&lt;br&gt;
⦁ The game of buying of selling is fun, just make offers cause someone may accept.&lt;br&gt;
⦁ Profits are made in the buying not the selling.&lt;br&gt;
⦁ Don't play it safe, play it smart.&lt;br&gt;
⦁ If you know what you're doing investing is not risky, its just common sense.&lt;/p&gt;

</description>
      <category>devjournal</category>
    </item>
    <item>
      <title>Rich Dad Poor Dad Lessons Learned Notes Part 3</title>
      <dc:creator>David</dc:creator>
      <pubDate>Mon, 23 Sep 2019 22:57:20 +0000</pubDate>
      <link>https://forem.com/davidsprogrammingadventures/rich-dad-poor-dad-lessons-learned-notes-part-3-410g</link>
      <guid>https://forem.com/davidsprogrammingadventures/rich-dad-poor-dad-lessons-learned-notes-part-3-410g</guid>
      <description>&lt;p&gt;⦁ The majority of taxes aren't payed by the rich, they are paid by the poor and middle class&lt;br&gt;
⦁ Taxes were made popular by the government telling the poor that the taxes were for the rich.&lt;br&gt;
⦁ The government is respected and gets power based on its size. A rich man gets respect and power by paying less and keeping more income, aka not having tons of employees.&lt;br&gt;
⦁ A corporation is merely a document in a clerks office that creates a body without a soul and protects the rich.&lt;br&gt;
⦁ Average Americans today work 5-6 months just to cover their taxes.&lt;br&gt;
⦁ The tax man is the biggest bully and will always take more if you let him.&lt;br&gt;
⦁ It is expensive to not know the law, (I personally saved 1500$ after filing taxes by looking up a clause that I had missed and then fixed by amending my return.)&lt;br&gt;
⦁ Corporations get taxed after they spend everything they can, basically money left over is what a corporation gets taxed on.&lt;br&gt;
⦁ Rich use vehicles like corporations and trusts that protect their assets.&lt;br&gt;
⦁ If you own any assets find out the benefits of setting up a corporation. (Personal corporations exists.)&lt;br&gt;
⦁ Don't resist change, sometimes its the old ideas that are the biggest liability.&lt;br&gt;
⦁ Never wait for the right opportunity, push to make the right opportunity happen&lt;br&gt;
⦁ Knowledge is important, those who fail to recognize an oportunity lose.&lt;br&gt;
⦁ If you don't have enough money for an oportunity, how can you still win from it, is financial intelligence.&lt;br&gt;
⦁ You create your own luck.&lt;br&gt;
⦁ Money is not real, money is what we agree it is, those who realize it can make more then those who don't.&lt;br&gt;
⦁ Millions get made without money at all, because just by an agreement between two people, money can be transfered/made.(example buy sell stocks using broker.)&lt;br&gt;
⦁ Humans are designed to learn by making mistakes, so while you should be carefull while getting rich, dont be afraid of losing or failure.&lt;br&gt;
⦁ 2 types of investors the ones who buy a prepackage component and the ones who put things together to build an investment.&lt;br&gt;
⦁ Huge wins come from those who can put investments together successfully.&lt;br&gt;
⦁ Find opportunities that others missed builds your financial intelligence.&lt;br&gt;
⦁ Learn how to raise money without a bank.&lt;br&gt;
⦁ Its what you know, not what you buy.&lt;/p&gt;

</description>
      <category>devjournal</category>
    </item>
    <item>
      <title>Rich Dad Poor Dad Lessons Learned Notes Part 2</title>
      <dc:creator>David</dc:creator>
      <pubDate>Mon, 23 Sep 2019 03:06:18 +0000</pubDate>
      <link>https://forem.com/davidsprogrammingadventures/rich-dad-poor-dad-lessons-learned-notes-part-2-4gnn</link>
      <guid>https://forem.com/davidsprogrammingadventures/rich-dad-poor-dad-lessons-learned-notes-part-2-4gnn</guid>
      <description>&lt;p&gt;⦁ Money is an illusion, the government can make money by printing it, but rich people can make money by creating other things/jobs.&lt;br&gt;
⦁ Being rich is not about how much money you make, its about how much money you keep and how many generations you keep it for.&lt;br&gt;
⦁ To be rich you must be financially literate.&lt;br&gt;
⦁ Accounting may be super boring but to be rich long term the lessons it teaches are important.&lt;br&gt;
⦁ you must understand the difference between an asset and a liability.&lt;br&gt;
⦁ The difference between an asset and a liability iis not words but what the numbers are telling you.&lt;br&gt;
⦁ An increase in cash doen't make you rich if you just increase your spending.&lt;br&gt;
⦁ A good mindset can be the one who always pushes to do things that others don't think possible.&lt;br&gt;
⦁ Owning a home is a liability not an asset.&lt;br&gt;
⦁ The greatest losses are those from missed oportunities.&lt;br&gt;
⦁ Start an investment portfolio as early as possible.&lt;br&gt;
⦁ You'll never be rich if your only source of income is your paycheck.&lt;br&gt;
⦁ Wealth is how much money your money is making.&lt;br&gt;
⦁ Always reinvest your excess cash into the assests.&lt;br&gt;
⦁ Mind your own business. Basically when you work all your lives for a job, you're actually working for your boss, the company, the government, and the bank before you work for yourself.&lt;br&gt;
⦁ Buy real assets not personal effects that lose value as soon as you get home.&lt;br&gt;
⦁ Keep expenses low, reduce liabilities, and build a solid asset base.&lt;br&gt;
⦁ Start collecting assets by using something you love. ( I love tech, so tech stocks will be more valuable to me then other things.)&lt;br&gt;
⦁ Once a dollar goes into your asset columb it becomes your employee, and you should never let it out.&lt;br&gt;
⦁ The rich buy luxuries last while the poor and middle class buy luxuries first.&lt;br&gt;
⦁ Buying a luxury on credit often causes people to regret a luxury because the cost becomes a burden.&lt;/p&gt;

</description>
      <category>devjournal</category>
    </item>
    <item>
      <title>Rich Dad Poor Dad Chapter 1 Lesson Notes:</title>
      <dc:creator>David</dc:creator>
      <pubDate>Sun, 22 Sep 2019 05:05:12 +0000</pubDate>
      <link>https://forem.com/davidsprogrammingadventures/rich-dad-poor-dad-chapter-1-lesson-notes-5fkp</link>
      <guid>https://forem.com/davidsprogrammingadventures/rich-dad-poor-dad-chapter-1-lesson-notes-5fkp</guid>
      <description>&lt;p&gt;⦁ Learn as much about money as possible especially how to make money work for me.&lt;br&gt;
⦁ Money is one form of power but financial education is more powerfull&lt;br&gt;
⦁ The Rich don't work for money, they have money work for them, poor and middle class work for money.&lt;br&gt;
⦁ Just because an idea fails doesn't mean you should give up. Basically never give up and allways think of new ways to make money work for you.&lt;br&gt;
⦁ When you get fed up and angry because life is pushing you around, don't just get angry at your boss or coworkers or job, push back at life which is the one controlling everything.&lt;br&gt;
⦁ When you blame someone else saying my boss or job is the problem you don't learn anything. You have to admit you're the problem in order to solve it.&lt;br&gt;
⦁ To solve the problems life throws at you, you need to use your mind. think of new possibilities, options, ways to grow.&lt;br&gt;
⦁ Every person has a week and needy part of their soul/person that can be bought. So to overcome life's troubles one must conquer that momentary glory.&lt;br&gt;
⦁ Most peoples price come from fear and greed.&lt;br&gt;
⦁ Don't fear not having money, think logically and overcome that life problem.&lt;br&gt;
⦁ While working to becoming rich never fear losing money. All things can be brought back but when you fear loss you get stuck.&lt;br&gt;
⦁ When stuck with fear for finding money, ask your self will a job be the solution to this fear in the long run?&lt;br&gt;
⦁ Master the power of money instead of being afraid of it.&lt;br&gt;
⦁ Self inflicted fear and ignorance keep people trapped and poor.&lt;br&gt;
⦁ By not giving into emotions you give yourself time to think and solve problems more easily.&lt;br&gt;
⦁ Never exploring your dreams because of fear is cruel.&lt;/p&gt;

</description>
      <category>devjournal</category>
    </item>
    <item>
      <title>LiveData Examples</title>
      <dc:creator>David</dc:creator>
      <pubDate>Sat, 30 Mar 2019 08:54:52 +0000</pubDate>
      <link>https://forem.com/davidsprogrammingadventures/livedata-examples-3cej</link>
      <guid>https://forem.com/davidsprogrammingadventures/livedata-examples-3cej</guid>
      <description>&lt;p&gt;So in Google Codelabs tutorial, Live observers are mentioned for passing data from the database to your activity. You are shown how to do 1 version of LiveData, which is to wrap a list in a LiveData&amp;lt;&amp;gt;, but what are some other methods and options out there? Well here I list a few examples, I have found through out the web.&lt;/p&gt;

&lt;h3&gt;
  
  
  First example
&lt;/h3&gt;

&lt;p&gt;Is a simple Livedata that wraps around a list or item, it only changes when the database is changed in a separate manner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmlw94m3cm8rdtsuwiuri.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmlw94m3cm8rdtsuwiuri.JPG" title="default dao livedata list" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gets passed through the repository if you have it and then on to the view model:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvdhjkpoz50tscohv2nc3.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvdhjkpoz50tscohv2nc3.JPG" title="view model class live data" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;then the viewmodel gets initialized in your activity class so you can create the observer and pass its data to your data holder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzvyq6q4p4ddwqyv9m92l.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzvyq6q4p4ddwqyv9m92l.JPG" title="live data observer listexample" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Second Example
&lt;/h3&gt;

&lt;p&gt;Passing in parameters to the LiveData&lt;/p&gt;

&lt;p&gt;modify the dao&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftu63h5xpo50l5gthdg96.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftu63h5xpo50l5gthdg96.JPG" title="dao query with param" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and at the ViewModel you need to use a second LiveData known as MutableLiveData.&lt;br&gt;
This MutableLiveData will be used for passing in a query term to the original LiveData from the activity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh20jisukla3oazm2y6kg.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh20jisukla3oazm2y6kg.JPG" title="search term in view model" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only change this causes in the activity code is an extra call to set the search_term&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmaw5wse4ydligx5w2adx.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmaw5wse4ydligx5w2adx.JPG" title="activity search term enter" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Third Example
&lt;/h3&gt;

&lt;p&gt;Passing in LiveData to a PagedList. Uses android architecture Room to create a Datasource.factory method from sql.&lt;br&gt;
This method is a great way to populate PagedLists, I only learned a bit about it because I mistook it for a pageAdapter when I was first learning Android.&lt;/p&gt;

&lt;p&gt;First modify your DAO to use a datasource.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7mruvkbgle0y827tpbjr.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7mruvkbgle0y827tpbjr.JPG" title="Datasource dao example" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Viewmodel class you set up your paged list to interact with the LiveData.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fajlq76uqwj8opnv8580h.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fajlq76uqwj8opnv8580h.JPG" title="view model paged list and datasource" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally you set an observer and pass in your factory data to an adapter from the pagedList, this is basically the same as example 1s.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fp0u36nolohorr9y8e61u.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fp0u36nolohorr9y8e61u.JPG" title="submit words to adapter example datafactory" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;While example 1 and 2 will generally work as is, example 3 tends to be harder to implement depending on your data , but for now this is the simplest example I could write up. without any extras that are usually associated with the PagedList.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>java</category>
      <category>google</category>
    </item>
    <item>
      <title>My First Published App (part 2)</title>
      <dc:creator>David</dc:creator>
      <pubDate>Sat, 30 Mar 2019 07:01:19 +0000</pubDate>
      <link>https://forem.com/davidsprogrammingadventures/my-first-published-app-part-2-3bgg</link>
      <guid>https://forem.com/davidsprogrammingadventures/my-first-published-app-part-2-3bgg</guid>
      <description>&lt;h2&gt;
  
  
  about
&lt;/h2&gt;

&lt;p&gt;For those reading this and not having read part 1, this is just a compilation of my personal experiences programming and publishing my first app. While eventually I would like to get good enough at writing to write tutorials, for now I am just practicing using my recent experiences. Thank you all for your time.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coding
&lt;/h1&gt;

&lt;p&gt;My app &lt;em&gt;OWL Flashcards level 1 en - cn&lt;/em&gt; uses a total of 6 screens, in this part I will be going over some of the screens and explaining how I built it and some improvements I made along the way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Title Screen
&lt;/h3&gt;

&lt;p&gt;The title screen is composed of text views, image views, and a button for going to the next screen. They are all inside a linear layout(vertical or horizontal depending on the orientation) and that linear layout is wrapped in a scroll view inside of a constraint view. &lt;/p&gt;

&lt;p&gt;I initially set up the scroll view to try and work around creating multiple screen layouts for different orientations and dimensions... it did not work. I eventually went and created a separate layout for every needed dimension, but as I was writing this, noticed I forgot to clean up the old scroll views... oops.&lt;/p&gt;

&lt;p&gt;The title screen is not the parent activity to any other screens, because I only wanted it to appear briefly while the user enters the app, this screen was designed to introduce basic info about the app when ever it was first started and after that it was not necessary. The only significant programming I did on the title screen was that the very first time the app was started a pop up custom alert and toast message would be displayed.&lt;/p&gt;

&lt;p&gt;The custom alert dialog was for entering a users name and saving it into the default shared preferences, so that for every following time onCreate() is called for the activity a &lt;em&gt;welcome back, 'display name'&lt;/em&gt; custom toast was shown.&lt;/p&gt;

&lt;p&gt;The alert init code:&lt;br&gt;
AlertDialog.Builder alert = new AlertDialog.Builder(this);&lt;br&gt;
            final EditText edittext = new EditText(this);&lt;br&gt;
            alert.setMessage(R.string.set_display_name_alert_message);&lt;br&gt;
            alert.setTitle(R.string.welcome_to_owl_flash_cards_alert_title);&lt;br&gt;
            edittext.setText(mPreferences.getString(SettingsActivity.KEY_PREF_EDIT_USER_NAME, ""));&lt;br&gt;
            alert.setView(edittext);&lt;/p&gt;

&lt;p&gt;It creates an edit text and if a user name was already in the default shared preferences, it displays that username so that it can be overwritten. After that it sets only the positive alert button.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;alert.setPositiveButton(R.string.alert_dialog_ok_button, new DialogInterface.OnClickListener()&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;inside the positive alert it saves the new user name and sets the get_user_name preferences to false so that the alert doesn't pop up every time.&lt;/p&gt;

&lt;p&gt;This allowed me all the data I would need to populate my greeting message for returning users.&lt;/p&gt;

&lt;p&gt;Toasts are interesting, cause googles guidelines usually say to remove toasts before publishing, so I tried to find an alternative like snackbar for my popup message, but it's color library had trouble with cardviews color library, and I decided I wanted cardviews color library, so I couldn't use snack bar.&lt;/p&gt;

&lt;p&gt;The solution was a simple hack where you generate the toast message, but change its layout. To do this you create an xml layout, inflate it with the layout and a view group.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;View layout = layoutInflater.inflate(R.layout.welcome_custom_toast_message, (ViewGroup) findViewById(R.id.custom_toast_welcome_message));&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;then you can create a new toast, set the gravity(optional), the duration, and pass in your layout.&lt;br&gt;
&lt;em&gt;toast.layout(layout)&lt;/em&gt;&lt;br&gt;
and show it. it is a remarkably easy and simple fix, but I still have to look into why toast messages are generally frowned upon in published apps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Main Screen/Menu Screen
&lt;/h3&gt;

&lt;p&gt;The menu screen consists of 10 buttons, (9 of which lead to the same fragment activity but with different intent data for populating it, and the other 1 leads to its own activity which is essentially a long screen of text.) It also has an options menu to go to the settings activity or the search activity. The main menu is also used as the parent activity for nearly all screens in my app.&lt;/p&gt;

&lt;p&gt;The 9 major buttons were different categories of flash cards for easier reading, the way I handled this was to pass in a public static final int into the intent extras so that when the new activity received the intent it populated itself using the correct data. &lt;strong&gt;I use to have more then one activity handling each button, but after taking my certification test through google, I realized I could simplify the app greatly by using Android ViewModel correctly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Menu screen has two interesting code segments.&lt;br&gt;
&lt;strong&gt;First&lt;/strong&gt; I wanted my buttons to be perfect squares, so that when they scrolled up and down the screen they were nice and uniform. To do this I had to create a &lt;em&gt;ViewTreeObserver&lt;/em&gt; object based off of one of my buttons, then I set a &lt;em&gt;GlobalLayoutListener&lt;/em&gt; for it. Inside the &lt;em&gt;GlobalLayoutListener&lt;/em&gt; I was able to use the buttons &lt;em&gt;getMeasuredWidth()&lt;/em&gt; to get the final width and pass it into my other buttons as the height, so they would become square.&lt;/p&gt;

&lt;p&gt;ex:&lt;br&gt;
ViewTreeObserver buttonSizeObserver = mAnimalButton.getViewTreeObserver();&lt;br&gt;
        buttonSizeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {&lt;br&gt;
            @Override&lt;br&gt;
            public void onGlobalLayout() {&lt;br&gt;
                mAnimalButton.getViewTreeObserver().removeOnGlobalLayoutListener(this);&lt;br&gt;
                int width = mAnimalButton.getMeasuredWidth();&lt;br&gt;
                mAnimalButton.setHeight(width);&lt;/p&gt;

&lt;p&gt;The whole reasoning for it, is when you are in oncreate the button widths are sometimes not set, so if you call the getMeasuredWidth() without the observer the width could be null, causing your buttons to dissapear. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The second&lt;/strong&gt; interesting thing I had to do in this activity, was to init my database. I discovered through testing that the first time the app was installed if you went straight to the flashcard page they would be blank and you would have to either press up or back to go back to the menu and then you could try again. I assumed no user would want to have to go back just to use the app the first time and so the solution was to init the database early so that any prepopulated data was ready for use when the user entered the next screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flashcard Screen
&lt;/h3&gt;

&lt;p&gt;So this screen consisted of 2 text view elements, 1 image view, and 1 image button element. The text views got populated with either the current English or Chinese word and its pronunciation spelling. The image view was one of two images based on what language the text view were in, and the image button was a play button to play the sound of the word from the text view.&lt;/p&gt;

&lt;p&gt;To make each card feel like a flash card I had to set an &lt;em&gt;onClickListener()&lt;/em&gt; to my primary Viewgroup, this allowed me to change the text, and image views/buttons based on a user click/tap. I used a boolean for this to decide which language to use. &lt;/p&gt;

&lt;p&gt;To make it so there was more then 1 card at a time I used a viewPager which was populated in the activity class. The view pager initiated my fragments by calling a static function named newInstance for the fragment, which then in turn called each ones own default constructor and returned the fragment. The static function also took in data passed in from the pager and placed it into a bundle so that the fragments onCreateActivity could parse it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fragments bundle extras, caused me confusion at first because I created a database with multiple tables and tried passing in a unique table each time, this method forced me to have multiple fragments and pageadapters. when I simplified my database to 1 table but with a row for categories I was able to reduce a lot of code redundancy for creating the fragments.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I discovered while building this page that ViewObservers are fun and have multiple options for storing and recalling data in a database. While tutorials might be lacking a bit on them, a few android doc codes have enough details to get many people started. &lt;/p&gt;

&lt;h3&gt;
  
  
  Search Page
&lt;/h3&gt;

&lt;p&gt;Android has a search widget and documentation to try and use it, But I wanted to try my hand at a custom view. So I simply created a layout for a button and edit text field, and attempted to put it into a custom view, got annoyed and put it directly in the search page instead. I've learned since then how to fix my problem I had with the custom view, but that is for a later blog post.&lt;/p&gt;

&lt;p&gt;The search page used an interesting technique with LiveObservers interacting with the viewmodel and database.&lt;/p&gt;

&lt;p&gt;It consisted of initializing a live observer, but also setting a second MutableLiveObserver with the search term. It did this so that the viewmodel class could keep the first LiveObserver as private, and not have to the user interacting with it directly, basically simplifying its job so that it could handle data changes more efficiently. &lt;/p&gt;

&lt;p&gt;ex: &lt;strong&gt;search Activity&lt;/strong&gt;&lt;br&gt;
mViewModel = ViewModelProviders.of(this).get(CardViewModel.class);&lt;br&gt;
final Observer&amp;gt; cardObserver = new Observer&amp;gt;() {&lt;br&gt;
            @Override&lt;br&gt;
            public void onChanged(@Nullable List cards) {}&lt;br&gt;
mViewModel.setSearchTerm(mLastSearchTerm); &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;View Model Class&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;public LiveData&amp;gt; mSearchedCard =&lt;br&gt;
            Transformations.switchMap(mSearchTerm, searchTerm -&amp;gt; {&lt;br&gt;
                return mRepository.findCard(searchTerm);&lt;br&gt;
            });&lt;br&gt;
private MutableLiveData mSearchTerm = new MutableLiveData&amp;lt;&amp;gt;();&lt;/p&gt;

&lt;p&gt;public void setSearchTerm(String term){&lt;br&gt;
        mSearchTerm.setValue(term);&lt;br&gt;
    }&lt;/p&gt;

&lt;p&gt;The reason for the LiveObserver for the search activity was so that the user could search more then once, and that I wouldn't have to use loaders and async tasks to retrieve new results or to store the previous results.&lt;/p&gt;

&lt;p&gt;The concludes the major interesting points for coding my First Published App, Later I might add in a part 3 about the publishing side through google play.&lt;/p&gt;

</description>
      <category>android</category>
      <category>java</category>
      <category>google</category>
    </item>
    <item>
      <title>My First Published App (part 1)</title>
      <dc:creator>David</dc:creator>
      <pubDate>Thu, 28 Mar 2019 02:20:46 +0000</pubDate>
      <link>https://forem.com/davidcf/my-first-published-app-part-1-510k</link>
      <guid>https://forem.com/davidcf/my-first-published-app-part-1-510k</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Hello Everyone, &lt;br&gt;
I just finished publishing my first app into Google Play. I decided to write this to commemorate the experience and to give a few tips on building and publishing. &lt;/p&gt;

&lt;p&gt;This post should not be followed to the 't'. I am only recently certified as an Android App Developer and there are many ways to build your own professional apps. This post is intended for those who want to go through the building and publication process, and feel they want to know others experience to help them get past the nervousness throughout publishing.&lt;/p&gt;

&lt;h2&gt;
  
  
  About
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;OWL Flash Cards Level 1 en-cn&lt;/strong&gt;. &lt;a href="https://github.com/davidfitz314/OWLFlashCardsencnlevel1" rel="noopener noreferrer"&gt;Code Repo&lt;/a&gt;, &lt;a href="https://play.google.com/store/apps/details?id=com.dcfportfolio.owlflashcardsen_cnlevel1&amp;amp;pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1" rel="noopener noreferrer"&gt;App&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Created using Android Studio version 3.3.&lt;br&gt;
Requires a minimum SDK level of 19.&lt;br&gt;
Compiled for SDK level 28. &lt;/p&gt;

&lt;p&gt;Additional Dependencies: Firebase, Support, Arch.Persistence.Room, Arch.Lifecycle, and Expresso for testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting a New Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating the Idea/concept.
&lt;/h3&gt;

&lt;p&gt;Well first I am terrible at speaking Chinese, but I married a girl from China. So after being married for a while I attempted to learn Chinese and I basically hated the way most programs taught you. I wanted a quick way to learn a word or two when I had free time, and the best way to do this seemed to be flashcards. &lt;/p&gt;

&lt;p&gt;For creating your own app idea the best method is usually just, what do you want and then expanding it outwards to help other people too. This can make it helpful for similar minded people to be easily attracted to your app idea.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a look for the Idea.
&lt;/h3&gt;

&lt;p&gt;Many people have heard of flashcards and probably used them, but how do you design an app to appear like them?&lt;/p&gt;

&lt;p&gt;First off you can try reading designers tips and tricks for making beautiful card animations, but that will usually lead to a road block if you do it too early on. The best method I have found is to start smaller: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a single app page and design its layout.

&lt;ul&gt;
&lt;li&gt;this can be done by drawing on paper or using an editor. &lt;/li&gt;
&lt;li&gt;start by placing required items first "title bars, nav bars, etc...&lt;/li&gt;
&lt;li&gt;don't pick colors too early, styling the background and elements may be fun but doing it too early leads to messy code and lots of cleaning later.&lt;/li&gt;
&lt;li&gt;Fill in the rest but don't forget to leave spaces for your own logos and titles.&lt;/li&gt;
&lt;li&gt;Lorem ipsum is a great way to put filler text, until you've organized your layout more.
*remember to draw buttons for apps with more then 1 screen, or look into other options like the navigation drawer.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Reference other apps, does the page you created look like a home page, a menu, the main content, etc...

&lt;ul&gt;
&lt;li&gt;If not a normally used design, think of ways you can either improve your own design by referencing others or go try and explain how to use your design to a friend. If you can't explain it in person there is almost now way users will understand it by only seeing it.&lt;/li&gt;
&lt;li&gt;You don't need to look exactly alike other apps, but people tend to do sloppy designs unless designing is their profession. So use other apps as reference when possible.&lt;/li&gt;
&lt;li&gt;Doing all this helps build validation that you are creating a professional app.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Create a story board for apps with more then 1 page.

&lt;ul&gt;
&lt;li&gt;This way all your designs and pages are in a line so when you jump to functionality you remember who connects to who.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I personally redrew designs and storyboards for about a week straight until I discovered that for now I just needed the most simple of layouts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Android Studio first time build
&lt;/h3&gt;

&lt;p&gt;So Android studio gives you a few basic templates, now if you don't need any extra templates you can use the empty activity layout. But remember to not just jump to this as a default, look at what you did when designing your app, did you push all your buttons for changing screens to a nav drawer, well if so android has a layout already for you. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remember to look at what's available, so you don't have to recreate the wheel later. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building the app layout
&lt;/h2&gt;

&lt;p&gt;Finally we can start coding. This app's prep work took me quite a bit of time, but it was super worth it to be able to start coding and see the layouts I made popup on a phone screen.&lt;/p&gt;

&lt;p&gt;Now for the home screen and menu screen, it was quite simple at first. I needed only a LinearLayout to hold my views which consisted of Textviews, ImageViews, and Buttons, But that was a wrong assumption on my part.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4uaxwdqq8fodss04nc91.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4uaxwdqq8fodss04nc91.png" title="Home Screen" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Linear layouts are great but they are only one direction, so if you want two items in a row you have to add in another layout group. If you add in a second Linear layout to hold the two items you also need to worry about layout weights. Layout weights are great because they can help organize your content for multiple screen dimensions but can cause performance issues when nested inside of each other. This is caused by the computer having to call onmeasure and ondraw multiple times in order to correctly process the dimensions of each item, which slows down all other resources, usually annoying the user greatly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So what did I do then to maintain flexibility for different screen dimensions?&lt;/strong&gt;&lt;br&gt;
For the Title Screen I used a constraint layout as the parent and placed a scrollview inside. The scrollview wrapped around my linear layout allowing my app to go past the boundaries of the phone... and yes I know this is wrong for a title screen, because if parts of your title, or following content goes off bounds, what user will think, &lt;em&gt;'oh i can just scroll to it, its ok'&lt;/em&gt;. None that's who. But when I was testing on multiple device screen I allowed this early mistake, so that I didn't have to build a horizontal orientation at the moment. &lt;/p&gt;

&lt;p&gt;I did later go and build horizontal layouts for my pages, but at first I focused on functionality, and that's ok. If you do decide to focus this way, make sure you implement a //TODO reminder so that you don't forget about something later.&lt;/p&gt;

&lt;h4&gt;
  
  
  Fragment layout building
&lt;/h4&gt;

&lt;p&gt;Fragment layouts are &lt;strong&gt;included&lt;/strong&gt; into a pre-existing layout, so remember your view hierarchy and avoid nested weights, forgetting the parent already had weights, can cause serious performance issues. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fs7ah1use3lu22zmgh41l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fs7ah1use3lu22zmgh41l.png" title="Card Fragment" alt="alt text"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;My app currently uses 2 fragments, one for the settings preference fragment and one for the flashcards themselves. Building the layout was semi straightforward, except that it took me a while to figure out, how to make the card flip over and show the translated side. But more on that in &lt;strong&gt;Part 2&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>androidstudio</category>
      <category>java</category>
      <category>roomdatabase</category>
      <category>fragments</category>
    </item>
  </channel>
</rss>
