<?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: njoee</title>
    <description>The latest articles on Forem by njoee (@noveriojoee).</description>
    <link>https://forem.com/noveriojoee</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%2F785014%2F6b8d99c9-a9e5-429c-9232-f5fc6cdf988d.png</url>
      <title>Forem: njoee</title>
      <link>https://forem.com/noveriojoee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/noveriojoee"/>
    <language>en</language>
    <item>
      <title>Spring &amp; Ribbon In Kubernetes</title>
      <dc:creator>njoee</dc:creator>
      <pubDate>Fri, 28 Apr 2023 12:22:33 +0000</pubDate>
      <link>https://forem.com/noveriojoee/spring-ribbon-in-kubernetes-2325</link>
      <guid>https://forem.com/noveriojoee/spring-ribbon-in-kubernetes-2325</guid>
      <description>&lt;p&gt;Hi, at this moment I was interest to write something about deploying Springboot based microservices to Kubernetes environment.&lt;/p&gt;

&lt;p&gt;So the idea is that I want to have sets of microservices spring boot based, and deployed to kubernetes as the picture bellow:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghf5cxads9bitpl6phsl.jpeg" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghf5cxads9bitpl6phsl.jpeg" alt="The Scenario which We are going to deployed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basically we are going to have 2 microservices&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/noveriojoee/microservice_user" rel="noopener noreferrer"&gt;Github : User_Services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/noveriojoee/microservices_account" rel="noopener noreferrer"&gt;Github : Account_Services&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;strong&gt;client&lt;/strong&gt; can call these methods&lt;br&gt;
-/users/v1/save --&amp;gt; Create User &amp;amp; Account&lt;br&gt;
-/users/v1/all --&amp;gt; Get Users data&lt;br&gt;
-/account/v1/all --&amp;gt; Get Accounts data&lt;br&gt;
-/account/v1/save --&amp;gt; Create Account data&lt;/p&gt;

&lt;p&gt;While user created, user_services will also call account_service to create the account &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ferdjw5648last05bumrt.jpeg" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ferdjw5648last05bumrt.jpeg" alt="Scneario"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;for doing this. the problems will be lay on&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;how user_services can call to account_services while account &amp;gt; service can be deployed on multiple instance and sets.&lt;br&gt;
how can we make N Replicas of account_services and&lt;br&gt;
User_Services can understand which account_services to &lt;br&gt;
consumed&lt;br&gt;
as the image bellow:&lt;/p&gt;
&lt;/blockquote&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn06tnni8ao5m2spd59l4.jpeg" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn06tnni8ao5m2spd59l4.jpeg" alt="Scenario Need Client Load Balancing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;that is where the &lt;a href="https://cloud.spring.io/spring-cloud-static/spring-cloud-kubernetes/2.1.0.RC1/multi/multi__discoveryclient_for_kubernetes.html" rel="noopener noreferrer"&gt;The discovery client&lt;/a&gt; and &lt;a href="https://cloud.spring.io/spring-cloud-static/spring-cloud-kubernetes/2.1.0.RC1/multi/multi__ribbon_discovery_in_kubernetes.html" rel="noopener noreferrer"&gt;The Ribbon Client Load Balancing&lt;/a&gt; come into play.&lt;/p&gt;
&lt;h2&gt;
  
  
  #1 The YAML
&lt;/h2&gt;

&lt;p&gt;Here is the Dependencies you should to take a look.&lt;br&gt;
These are the dependencies for spring cloud kubernetes.&lt;br&gt;
all the microservices must be able to be observe by other services by making the microservices discoverable by client.&lt;br&gt;
to do so you'll need bellow dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-cloud-starter-openfeign&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;4.0.1&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-cloud-starter-kubernetes-ribbon&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-cloud-starter-kubernetes-all&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;also you need this dependencies, for later on used by the ingress for liveProb and healthProb mechanism.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-actuator&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  #2 The Discovery Client &amp;amp; Feign Clients
&lt;/h2&gt;

&lt;p&gt;now, we need to make our microservices discoverable by other microservices. with spring cloud after we put the dependencies above, we can do this in our &lt;code&gt;application.java&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class GIDUsersApplicationServices {

    public static void main(String[] args) {
        SpringApplication.run(GIDUsersApplicationServices.class, args);
    }

    @Bean
    public TimedAspect timedAspect(MeterRegistry registry) {
        return new TimedAspect(registry);
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  #3 The Business Logic
&lt;/h2&gt;

&lt;p&gt;remember in our case we will create account during user creation on user_services. here are the code logic&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Override
    public Resources&amp;lt;UserDTO&amp;gt; saveUser(User requestData) {
        Resources&amp;lt;UserDTO&amp;gt; serviceResult = new Resources&amp;lt;UserDTO&amp;gt;();
        serviceResult.throwResponseWithCode("99", "failed to save user", null);

        UserModel userData = this.userDAO.addUser(requestData.getUserName());

        if (userData != null) {
            AccountCreation requestAccountCreation = new AccountCreation();
            requestAccountCreation.setUserId(userData.getUserId());
            requestAccountCreation.setAmount("10000");

            // ## Call request data to account services
            System.out.println("request data" + requestAccountCreation.toString());
            Resources&amp;lt;AccountDTO&amp;gt; createAccountResult = this.serviceProxy.saveUser(requestAccountCreation);
            System.out.println("response data" + createAccountResult.toString());
            // ## Call request data to account services

            if (!createAccountResult.getResponseCode().equals(ApplicationConstant.GENERAL_SUCCESS_CODE)) {
                return serviceResult.throwResponseWithCode("99", "Failed to save user", null);
            }
            UserDTO user = new UserDTO();
            user.setUser(userData);

            return serviceResult.throwSucceedResponse(user);
        } else {
            UserDTO responseOBject = new UserDTO();
            responseOBject.setErrorModel(new ErrorModel("ini error"));
            return serviceResult.throwResponseWithCode("99", "Failed to save user", responseOBject);
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now lets zoom carefully into this line&lt;br&gt;
&lt;code&gt;this.serviceProxy.saveAccount&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  #4 The FeignClient for saveAccount
&lt;/h2&gt;

&lt;p&gt;now lets take a look into the saveAccount Method bellow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// @FeignClient(value = "account-services", url = "http://34.128.121.224:81/account")
@FeignClient(name = "gid-account-service")
public interface IAccountServicesProxy {

    @RequestMapping(method = RequestMethod.POST, value = "/account/v1/save")
    public Resources&amp;lt;AccountDTO&amp;gt; saveAccount(AccountCreation requestData);

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as you can see, instead of using &lt;br&gt;
&lt;code&gt;@FeignClient(value = "account-services", url = "http://34.128.121.224:81/account")&lt;/code&gt; to point out the account services by its ipAddress&lt;/p&gt;

&lt;p&gt;we can use this&lt;br&gt;
&lt;code&gt;@FeignClient(name = "gid-account-service")&lt;/code&gt; and get the available ipAddress from kubernetes Services.&lt;/p&gt;

&lt;p&gt;as mention &lt;a href="https://cloud.spring.io/spring-cloud-static/spring-cloud-kubernetes/2.1.0.RC1/multi/multi__discoveryclient_for_kubernetes.html" rel="noopener noreferrer"&gt;here in spring cloud, that&lt;/a&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This project provides an implementation of Discovery Client for Kubernetes. This allows you to query Kubernetes endpoints (see services) by name. A service is typically exposed by the Kubernetes API server as a collection of endpoints which represent http, https addresses that a client can access from a Spring Boot application running as a pod&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;now we fetch all the pods ipAddress from the kubernetes services so we don't need to to put the ip address in our code anymore and let the services get the destination ip from kubernetes services. this discovery concept is similar with usage of &lt;a href="https://cloud.spring.io/spring-cloud-netflix/reference/html/" rel="noopener noreferrer"&gt;eureka&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So basically we are no longer need eureka when we use kubernetes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notes : in order to make this possible you have to make sure that the services name in here&lt;/p&gt;

&lt;p&gt;&lt;code&gt;spring.application.name=gid-account-service&lt;/code&gt; same as services &lt;br&gt;
name you put on your k8s-deployment&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IMPORTANT : Makesure your spring.application.name equal with your Kuberenetes Services Name&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment # Kubernetes resource kind we are creating
metadata:
  name: gid-account-service # Required to be the same as spring config services name
  namespace: default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you also need to make sure that you add this on your application properties, in order to enable the services become discoverable and the client load balancing on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring.cloud.kubernetes.discovery.enabled=true
spring.cloud.kubernetes.loadbalancer.mode=service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now we all sets. move to the deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  #5 The Deployment to Kubernetes.
&lt;/h2&gt;

&lt;p&gt;before we go to the deployment process. make sure that you have&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;PostgreeDB Instance Ready to use. since the services need database&lt;/li&gt;
&lt;li&gt;GKE Clusters&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/sdk/gcloud/reference/components/install" rel="noopener noreferrer"&gt;Install gcloud components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl" rel="noopener noreferrer"&gt;Connect to your Clusters&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;now here is the k8s-deployment for user_services&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment # Kubernetes resource kind we are creating
metadata:
  name: gid-user-service
  namespace: bcad-testing-env
spec:
  selector:
    matchLabels:
      app: gid-user-service
  replicas: 2 # Number of replicas that will be created for this deployment
  template:
    metadata:
      labels:
        app: gid-user-service
    spec:
      containers:
        - name: gid-user-service
          image: noveriojoee/user_services:v0.0.6-staging.8 # Image that will be used to containers in the cluster
          imagePullPolicy: IfNotPresent
          # Configure the readiness probe
          livenessProbe:
            initialDelaySeconds: 90
            timeoutSeconds: 30
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 3
            httpGet:
              path: /actuator/health/liveness
              port: 8201
          readinessProbe:
            initialDelaySeconds: 60
            timeoutSeconds: 30
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 3
            httpGet:
              path: /actuator/health/readiness
              port: 8201
          ports:
            - containerPort: 8201 # The port that the container is running on in the cluster


---
#THIS IS SERVICES AS CONSUME BY INGRESS
apiVersion: v1
kind: Service
metadata:
  name: gid-user-service
  namespace: bcad-testing-env
  labels:
    app: gid-user-service
spec:
  selector:
    app: gid-user-service
  ports:
    - port: 8207
      protocol: TCP
      targetPort: 8201
  type: NodePort
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and here is the k8s-deployment for account_services&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment # Kubernetes resource kind we are creating
metadata:
  name: gid-account-service # Required to be the same as spring config services name
  namespace: default
spec:
  selector:
    matchLabels:
      app: gid-account-service
  replicas: 3 # Number of replicas that will be created for this deployment
  template:
    metadata:
      labels:
        app: gid-account-service
    spec:
      containers:
        - name: gid-account-services-pods
          image: noveriojoee/account_services:v0.0.3-staging.5 # Image that will be used to containers in the cluster
          imagePullPolicy: IfNotPresent
          # Configure the readiness probe
          livenessProbe:
            initialDelaySeconds: 90
            timeoutSeconds: 30
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 3
            httpGet:
              path: /actuator/health/liveness
              port: 8202
          readinessProbe:
            initialDelaySeconds: 60
            timeoutSeconds: 30
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 3
            httpGet:
              path: /actuator/health/readiness
              port: 8202
          ports:
            - containerPort: 8202 # The port that the container is running on in the cluster


---
# #THIS IS SERVICES AS CONSUME BY INGRESS
apiVersion: v1
kind: Service
metadata:
  name: gid-account-service
  namespace: default
  labels:
    app: gid-account-service
spec:
  selector:
    app: gid-account-service
  ports:
    - port: 8206
      protocol: TCP
      targetPort: 8202
  type: NodePort
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;by this deployment script we will have 2 sets of user_services and 3 sets of account_services&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;now lets exposed this to public via Ingress as our api gateway&lt;br&gt;
and use &lt;a href="https://cloud.google.com/kubernetes-engine/docs/concepts/ingress" rel="noopener noreferrer"&gt;GCE&lt;/a&gt; as the ingress controller.&lt;br&gt;
&lt;a href="https://medium.com/omnius/kubernetes-ingress-gce-vs-nginx-controllers-1-3-d89d6dd3da73" rel="noopener noreferrer"&gt;read here for GCE vs NGINX Controller&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: gid-user-services-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "gce" #REF -&amp;gt; https://medium.com/@glen.yu/nginx-ingress-or-gke-ingress-d87dd9db504c
    kubernetes.io/ingress.allow-http: "true"
    servers.com/ingress.load-balancer-healthcheck-path: "/actuator/health"
    #kubernetes.io/ingress.global-static-ip-name: gid-public-ip #REF -&amp;gt; Create PUBLIC STATIC IP AND IMPLEMENT TO YOUR INGRESS USING GCLOUDCONTROLLER
spec:
  # defaultBackend:
  #   service:
  #     name: gid-user-service
  #     port:
  #       number: 8207
  rules:
  - http:
      paths:
      - path: /* #&amp;lt;-- can be anything. considered as default
        pathType: ImplementationSpecific
        backend:
          service:
            name: gid-user-service
            port:
              number: 8207
      - path: /account/* # &amp;lt;-- Follow your controller request path
        pathType: ImplementationSpecific
        backend:
          service:
            name: gid-account-service
            port:
              number: 8206

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;by above deployment scripts now we have this.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiberll5gqlweam8nhkts.jpeg" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiberll5gqlweam8nhkts.jpeg" alt="Kubernetes Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  #6 Permission
&lt;/h2&gt;

&lt;p&gt;in order to ribbon be able to fetch api list ip from the namespaces you can use &lt;a href="https://www.google.com/search?client=safari&amp;amp;rls=en&amp;amp;q=RBAC+kubernetes&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8" rel="noopener noreferrer"&gt;RBAC&lt;/a&gt; or you can just give the admin permission with this command&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl create clusterrolebinding default-pod --clusterrole cluster-admin --serviceaccount=&amp;lt;namespace&amp;gt;:default&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  #7. The testing
&lt;/h2&gt;

&lt;p&gt;after we deploy the services and ingress now lets try to hit the api through ingress.&lt;/p&gt;

&lt;p&gt;first&lt;/p&gt;

&lt;p&gt;lets try &lt;code&gt;Kubectl get ing -A&lt;/code&gt; it will show all of your ingress&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowa3sl5jnnvebvzuczrr.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowa3sl5jnnvebvzuczrr.png" alt="Get Ingress"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;now you can start calling the api with public ip &lt;code&gt;34.107.131.195&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and if you take a look deeper on your ingress description using &lt;code&gt;kubectl describe ing gid-user-services-ingress&lt;/code&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5i756pxqws3ewbxbiqm.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5i756pxqws3ewbxbiqm.png" alt="Ingress Description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;you'll see that default request will be routed to &lt;code&gt;user_services&lt;/code&gt; and all request on &lt;code&gt;[ip_address]/account&lt;/code&gt; will be route to &lt;code&gt;account_services&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Happy Trying :D &lt;/p&gt;

&lt;p&gt;References : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.spring.io/spring-cloud-static/spring-cloud-kubernetes/2.1.0.RC1/multi/multi_spring-cloud-kubernetes.html" rel="noopener noreferrer"&gt;Springboot In Kubernetes From Springcloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/66654569/io-fabric8-kubernetes-client-kubernetesclientexception-forbiddenconfigured-ser" rel="noopener noreferrer"&gt;Allowing Client Side Load Balancing to fetch Pods IP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://piotrminkowski.com/2020/09/10/spring-cloud-kubernetes-load-balancer-guide/" rel="noopener noreferrer"&gt;Pyothry blogs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>kubernetes</category>
      <category>gke</category>
    </item>
    <item>
      <title>Flutter How To Use Injectable</title>
      <dc:creator>njoee</dc:creator>
      <pubDate>Sat, 13 Aug 2022 04:34:00 +0000</pubDate>
      <link>https://forem.com/noveriojoee/flutter-how-to-use-injectable-4oag</link>
      <guid>https://forem.com/noveriojoee/flutter-how-to-use-injectable-4oag</guid>
      <description>&lt;p&gt;hi, before we start, this article are continue from preivous post regarding flutter mvvm using provider, injectable, and freeze&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/noveriojoee/mvvm-with-flutter-52p6"&gt;MVVM Part 1&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/noveriojoee/mvvm-with-flutter-part2freeze-48m9"&gt;MVVM Part 2&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/noveriojoee/what_to_do_app_flutter"&gt;The Code Project Is Here...&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;this article will focused on how to implement the injectable step by step...&lt;/p&gt;

&lt;p&gt;now.. &lt;strong&gt;&lt;a href="https://pub.dev/packages/injectable#setup"&gt;Injectable&lt;/a&gt;&lt;/strong&gt;, are the &lt;strong&gt;Dependency Injection&lt;/strong&gt; component that allow us to register an object to Dependency Injection through &lt;strong&gt;Annotation&lt;/strong&gt;, instead of registering dependency with bellow approach&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getIt.registerSingleton&amp;lt;TaskRepositoryImpl&amp;gt;(TaskRepositoryImpl());
getIt.registerLazySingleton&amp;lt;MainScreenViewModel&amp;gt;(() =&amp;gt;MainScreenViewModel());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we can simply put annotation on each class declaration of &lt;code&gt;TaskRepositoryImpl&lt;/code&gt; and &lt;code&gt;MainScreenViewModel&lt;/code&gt; like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@singleton 
class TaskRepositoryImpl implements ITaskRepository{
  final String baseUrl = "run.mocky.io";

  ... 
}

@injectable
class MainScreenViewModel extends BaseViewModel {
  List&amp;lt;TaskModel&amp;gt;? _tasksData;

  final ITaskRepository _taskRepository = getIt&amp;lt;TaskRepositoryImpl&amp;gt;();

  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now in our case of &lt;strong&gt;&lt;em&gt;&lt;a href="https://github.com/noveriojoee/what_to_do_app_flutter"&gt;WhatToDoApp&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Remember This image? &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y0hpS9cS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mnaa367psh4uf5f9swap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y0hpS9cS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mnaa367psh4uf5f9swap.png" alt="How ViewModel use Repository To Manage Many Model" width="880" height="296"&gt;&lt;/a&gt;&lt;br&gt;
we'd like to have a singleton &lt;strong&gt;Repository&lt;/strong&gt; and late assign of &lt;strong&gt;ViewModel&lt;/strong&gt; layer... so we declare the &lt;code&gt;TaskRepository&lt;/code&gt; this way :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@singleton 
class TaskRepositoryImpl implements ITaskRepository{
  final String baseUrl = "run.mocky.io";

  ... 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and when we need to use it in the viewmodel we can use it this way&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@injectable
class MainScreenViewModel extends BaseViewModel {
  List&amp;lt;TaskModel&amp;gt;? _tasksData;

//=== THIS WAY ===//
  final ITaskRepository _taskRepository = getIt&amp;lt;TaskRepositoryImpl&amp;gt;();

  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;easy right?&lt;/p&gt;

&lt;p&gt;no in order to implement this style, we need to import a couple things into our &lt;strong&gt;&lt;em&gt;pubspec.yaml&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies:
  flutter:
    sdk: flutter
  injectable: ^1.5.3
  get_it: ^7.2.0
dev_dependencies:
  # add the generator to your dev_dependencies
  injectable_generator: ^1.5.4
  # add build runner if not already added
  build_runner: ^2.2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;remember, everytime we declare class with &lt;code&gt;@Injectable&lt;/code&gt; or &lt;code&gt;@Singleton&lt;/code&gt; annotation, the injectable component actually will generating file that contain a registration to &lt;a href="https://pub.dev/packages/get_it"&gt;GetIt&lt;/a&gt; like bellow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_i1.GetIt $initGetIt(_i1.GetIt get,
    {String? environment, _i2.EnvironmentFilter? environmentFilter}) {
  final gh = _i2.GetItHelper(get, environment, environmentFilter);
  gh.factory&amp;lt;_i3.MainScreenViewModel&amp;gt;(() =&amp;gt; _i3.MainScreenViewModel());
  gh.singleton&amp;lt;_i4.TaskRepositoryImpl&amp;gt;(_i4.TaskRepositoryImpl());
  return get;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in order for injectable generating file content like above, you have to &lt;strong&gt;&lt;em&gt;create some new file&lt;/em&gt;&lt;/strong&gt; in my case it called &lt;strong&gt;&lt;em&gt;Setup.dart&lt;/em&gt;&lt;/strong&gt; &lt;br&gt;
and the content is like this..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'package:what_to_do_app/Setup.config.dart';


final getIt = GetIt.instance;  

@InjectableInit(  
  initializerName: r'$initGetIt', // default  
  preferRelativeImports: true, // default  
  asExtension: false, // default  
)  

@InjectableInit(generateForDir: ['test'])  
void configureDependencies() =&amp;gt; $initGetIt(getIt);  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after we declare the &lt;code&gt;Setup.dart&lt;/code&gt; above, we can run command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter packages pub run build_runner build --delete-conflicting-outputs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then it will generating file called &lt;code&gt;Setup.config.dart&lt;/code&gt;. then that's it.. your Dependency Injection are now ready to serve you.. CHEERS!!!..&lt;/p&gt;

&lt;p&gt;Ref: &lt;br&gt;
&lt;a href="https://pub.dev/packages/injectable#setup"&gt;Injectable&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pub.dev/packages/get_it"&gt;GetIt&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>programming</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Flutter How To Use Freeze</title>
      <dc:creator>njoee</dc:creator>
      <pubDate>Sat, 13 Aug 2022 04:33:00 +0000</pubDate>
      <link>https://forem.com/noveriojoee/flutter-how-to-use-freeze-3oba</link>
      <guid>https://forem.com/noveriojoee/flutter-how-to-use-freeze-3oba</guid>
      <description>&lt;p&gt;hi, before we start, this article are continue from preivous post regarding flutter mvvm using provider, injectable, and freeze&lt;br&gt;
&lt;a href="https://dev.to/noveriojoee/mvvm-with-flutter-52p6"&gt;MVVM Part 1&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/noveriojoee/mvvm-with-flutter-part2freeze-48m9"&gt;MVVM Part 2&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/noveriojoee/what_to_do_app_flutter"&gt;The Code Project Is Here...&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;this article will focused on how to implement the freeze step by step.&lt;/p&gt;
&lt;h2&gt;
  
  
  Now, How to Use The Freezed.
&lt;/h2&gt;

&lt;p&gt;first.. on your &lt;code&gt;pubspec.yaml&lt;/code&gt; on the &lt;code&gt;dependencies&lt;/code&gt; sections you have to install &lt;strong&gt;(please ignore the version, use the latest one instead)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies:
  flutter:
    sdk: flutter
  freezed: ^2.1.0+1
  freezed_annotation: ^2.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and on the &lt;code&gt;dev_dependencies&lt;/code&gt; sections you have to install&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dev_dependencies:
  build_runner: ^2.2.0 //Generating implementation code
  flutter_test:
    sdk: flutter
  json_serializable: ^6.3.1 //Make serializable object(to/from) json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and here is the sample of the code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:freezed_annotation/freezed_annotation.dart';
part 'task_model.freezed.dart';
part 'task_model.g.dart';

@freezed
class TaskModel with _$TaskModel {
  factory TaskModel({
    required final String title,
    required final String description,
    @Default(false) bool isDone,
  }) = _TaskModel;

  factory TaskModel.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) =&amp;gt;
      _$TaskModelFromJson(json);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now lets break it into a pieces,&lt;/p&gt;

&lt;h3&gt;
  
  
  Take a look at How The Class Constructed
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@freezed
//This _$TaskModel is not autoGenerated you have to construct
//it manually using this format _${{ClassName}}
class TaskModel with _$TaskModel {
//for this section, you just have to follow these line
/* using this format
  factory {{ClassName}}({
   Declare all the fields here..
  }) = _{{ClassName}}
*/
  factory TaskModel({
    required final String title,
    required final String description,
    @Default(false) bool isDone,
  }) = _TaskModel;

//Allow your object to be serializable. can do mutation
//fromJson or toJson.
  factory TaskModel.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) =&amp;gt;
      _$TaskModelFromJson(json);
//this Factory fromJson method is not autogenerated
// so you have to declare it manually with thisFormat
//  factory {{ClassName}}.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) =&amp;gt;
//      _${{ClassName}}FromJson(json);


}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;up until here.. your code will be &lt;strong&gt;RED&lt;/strong&gt; everywhere.. haha dont worry take a look at the import&lt;/p&gt;

&lt;h3&gt;
  
  
  Take a look at the import
&lt;/h3&gt;

&lt;p&gt;to be able to use &lt;code&gt;@freezed&lt;/code&gt; or &lt;code&gt;@unfreezed&lt;/code&gt; you have to import this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:freezed_annotation/freezed_annotation.dart';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then you have to import this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;part 'task_model.freezed.dart';
//this import can be very depend on the class name
//so the format will be
//part '{{className}}.freezed.dart';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this import will allow you to have the &lt;code&gt;immutable&lt;/code&gt; or &lt;code&gt;mutable&lt;/code&gt; ability of this model.&lt;/p&gt;

&lt;p&gt;come to the next one.&lt;br&gt;
you have to import this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;part 'task_model.g.dart';
//this import are important because it makes your object are serializable.
//see the fromJson method in code above. without this import it will not run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;up until here.. your code will be &lt;strong&gt;RED&lt;/strong&gt; everywhere.. haha dont worry take a look at the code generation..&lt;/p&gt;

&lt;h3&gt;
  
  
  Lets generate the code.
&lt;/h3&gt;

&lt;p&gt;before we go, make sure you already adjust your pubspec.yaml as the first section of this article already mentioned.&lt;/p&gt;

&lt;p&gt;now lets ask the build runner to make the implementation class of our model...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;make sure you already do flutter pub get to install the pubspec.yaml&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;then you run this command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter pub run build_runner build --delete-conflicting-outputs 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and after it run it supposed to generate the implementation file like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8lxwT7pF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ints7ex7ksn1hxrdj7yc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8lxwT7pF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ints7ex7ksn1hxrdj7yc.png" alt="Image description" width="458" height="140"&gt;&lt;/a&gt;&lt;br&gt;
..&lt;/p&gt;

&lt;p&gt;and here we go.. now you can take a look at your model class, there will be no red anymore.&lt;/p&gt;

&lt;p&gt;haha thanks!!..&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>programming</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>MVVM With Flutter (Part2){Freeze}</title>
      <dc:creator>njoee</dc:creator>
      <pubDate>Thu, 11 Aug 2022 09:53:00 +0000</pubDate>
      <link>https://forem.com/noveriojoee/mvvm-with-flutter-part2freeze-48m9</link>
      <guid>https://forem.com/noveriojoee/mvvm-with-flutter-part2freeze-48m9</guid>
      <description>&lt;p&gt;well, before go to this, please take a look at the previous post first &lt;a href="https://dev.to/noveriojoee/mvvm-with-flutter-52p6"&gt;MVVM With Flutter (Part1)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Back again!,
&lt;/h2&gt;

&lt;p&gt;continue from previous post, in this post we will focus to Repositories and Model Layer.&lt;/p&gt;

&lt;p&gt;Remember We would like to create our codebaseline this way: &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vdky68deu7dx542f84z.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vdky68deu7dx542f84z.png" alt="The Whole Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;so now we are going we have this already from the previous post.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzkxdeg05xutt943ux92.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzkxdeg05xutt943ux92.png" alt="The View And ViewModel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;now we are going to focus on this layer, by using &lt;strong&gt;API&lt;/strong&gt; as our datasource.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fno7lgeholosbny4mbhqx.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fno7lgeholosbny4mbhqx.png" alt="The ViewModel And Model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;in our cases, we have &lt;br&gt;
&lt;code&gt;MainScreen&lt;/code&gt; (View)&lt;br&gt;
&lt;code&gt;MainScreenViewModel&lt;/code&gt; (ViewModel)&lt;br&gt;
&lt;code&gt;TaskModel&lt;/code&gt; (Model)&lt;br&gt;
and we have&lt;br&gt;
&lt;code&gt;ITaskRepository&lt;/code&gt; (Repositorires)&lt;br&gt;
as a tools for &lt;strong&gt;(ViewModel)&lt;/strong&gt; to fetch &lt;strong&gt;(Model)&lt;/strong&gt;.. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmnaa367psh4uf5f9swap.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmnaa367psh4uf5f9swap.png" alt="How ViewModel use Repository To Manage Many Model"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;And Maybe Later On&lt;/strong&gt; you have &lt;code&gt;XModel&lt;/code&gt; can be manage by &lt;code&gt;XRepository&lt;/code&gt; and so on...&lt;/p&gt;
&lt;h2&gt;
  
  
  Lets Take A look into code,
&lt;/h2&gt;

&lt;p&gt;First, you'll create an abstract class like this acting like an interface&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 ITaskRepository{
  Future&amp;lt;List&amp;lt;TaskModel&amp;gt;?&amp;gt; getAllTask();
  //and all the method regarding add, update, delet, getById   etc..
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and now see the implementation code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@singleton 
class TaskRepositoryImpl implements ITaskRepository{
  final String baseUrl = "run.mocky.io";

  @override
  Future&amp;lt;List&amp;lt;TaskModel&amp;gt;?&amp;gt; getAllTask() async{
    var url = Uri.https(baseUrl, "/v3/6bb86bda-08f1-4d7d-99c6-a975bc1201e0");
    final response = await networking.get(url);
    final responseBody = GetTaskDTO.fromJson(jsonDecode(utf8.decode(response.bodyBytes)) as Map&amp;lt;String,dynamic&amp;gt;);
    return responseBody.tasks;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;from the code above, as you can see. we register the &lt;code&gt;TaskRepositoryImpl&lt;/code&gt; into our Dependency Injection and provide it as a Singleton Object whenever we need it.&lt;/p&gt;

&lt;p&gt;also, we have method &lt;code&gt;getAlltask()&lt;/code&gt; responsible to fetch all the task that user have, meaning return list of &lt;code&gt;TaskModel&lt;/code&gt; fetched from the API which we are using &lt;a href="https://pub.dev/packages/http" rel="noopener noreferrer"&gt;http_package&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;as you can see, we convert all the json response directly into object in this line of code, from this json object&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "tasks": [
    {
      "title": "makan",
      "description": "makan di rumah",
      "isDone": false
    },
    {
      "title": "olahraga",
      "description": "jangan lupa olahraga",
      "isDone": false
    },
    {
      "title": "mindfulness",
      "description": "you have to mindfull",
      "isDone": false
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;into &lt;strong&gt;GetTaskDTO&lt;/strong&gt; object like bellow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GetTaskDTO.fromJson(jsonDecode(utf8.decode(response.bodyBytes)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now lets take a look at the &lt;code&gt;GetTaskDTO&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@unfreezed //--&amp;gt; this DTO are muttable
class GetTaskDTO with _$GetTaskDTO {
  factory GetTaskDTO({
    required final List&amp;lt;TaskModel&amp;gt; tasks,
  }) = _GetTaskDTO;

  factory GetTaskDTO.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) =&amp;gt;
      _$GetTaskDTOFromJson(json);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this GetTaskDTO acting as our (Data Transfer Object) to wrap all the response from the API. and within this DTO there are list of &lt;code&gt;TaskModel&lt;/code&gt; and will convert all the &lt;code&gt;tasks&lt;/code&gt; object from json response into List of TaskModel..&lt;br&gt;
now lets take a look at the &lt;code&gt;TaskModel&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@freezed //--&amp;gt; This object immutable
class TaskModel with _$TaskModel {
  factory TaskModel({
    required final String title,
    required final String description,
    //to set defaultValue using freezed
    @Default(false) bool isDone, 
  }) = _TaskModel;

  factory TaskModel.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) =&amp;gt;
      _$TaskModelFromJson(json);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;one thing about freezed, &lt;strong&gt;YOU HAVE TO MAKE SURE ALL YOUR FIELD NAMING AND CASE ARE FOLLOWING THE JSON RESPONSE FROM THE API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;and now you have it. how your viewModel, can access the model through the API.. and convert all the Json Response from API directly into model.&lt;/p&gt;

&lt;p&gt;References&lt;br&gt;
&lt;a href="https://pub.dev/packages/http" rel="noopener noreferrer"&gt;http_package&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pub.dev/packages/freezed" rel="noopener noreferrer"&gt;Freezed_package&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next : &lt;br&gt;
&lt;a href="https://dev.to/noveriojoee/flutter-how-to-use-freeze-3oba"&gt;How To Use Flutter with Freeze&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/noveriojoee/flutter-how-to-use-injectable-4oag"&gt;How To Use Flutter with Injectable&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>programming</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>MVVM With Flutter (Part1){MVVM, Provider, Injectable, Freezed}</title>
      <dc:creator>njoee</dc:creator>
      <pubDate>Thu, 11 Aug 2022 08:48:00 +0000</pubDate>
      <link>https://forem.com/noveriojoee/mvvm-with-flutter-52p6</link>
      <guid>https://forem.com/noveriojoee/mvvm-with-flutter-52p6</guid>
      <description>&lt;h1&gt;
  
  
  Hai!,
&lt;/h1&gt;

&lt;p&gt;Here i'd like to record my code base line for flutter using MVVM pattern, &lt;/p&gt;

&lt;h1&gt;
  
  
  The Idea and the pattern
&lt;/h1&gt;

&lt;p&gt;so the idea is i'd like to bind view and viewmodel one on one and making the viewmodel as our boiler plate to orchestrate all the logic related to its view like bellow.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vdky68deu7dx542f84z.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vdky68deu7dx542f84z.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;i'm using these dependencies to run &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Injectable --&amp;gt; &lt;a href="https://pub.dev/packages/injectable#setup" rel="noopener noreferrer"&gt;Dependencies Injection&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Freeze --&amp;gt; &lt;a href="https://pub.dev/packages/freezed" rel="noopener noreferrer"&gt;Model Mapper&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Provider --&amp;gt; &lt;a href="https://pub.dev/packages/provider" rel="noopener noreferrer"&gt;State Management&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The Goal, What the apps will looks like
&lt;/h1&gt;

&lt;p&gt;as a sample i create todolist app, like this&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0kckwszv4arz7j6aml4.gif" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0kckwszv4arz7j6aml4.gif" alt="Image description"&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;h1&gt;
  
  
  Now The Dev, lets deep into the code
&lt;/h1&gt;

&lt;p&gt;now, in order to create the apps as above, we need 3 things.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 Screen &lt;strong&gt;BIND&lt;/strong&gt; to 1 View Model,
&lt;/li&gt;
&lt;li&gt;1 Repositories Available for &lt;strong&gt;any&lt;/strong&gt; view model
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5emr2ja31rd9tth3ot72.png" alt="Image description"&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. Here is the MainScreen..
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MainScreen extends BaseView&amp;lt;MainScreenViewModel&amp;gt; {
  @override
  Widget build(
      BuildContext context, MainScreenViewModel viewModel, Widget? child) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          showModalBottomSheet(
              context: context,
              isScrollControlled: true,
              builder: (context) =&amp;gt; SingleChildScrollView(
                    child: Container(
                        padding: EdgeInsets.only(
                            bottom: MediaQuery.of(context).viewInsets.bottom),
                        child: AddTaskScreen(onAddTaskClicked: viewModel.onAddTaskClicked,)),
                  ));
        },
        child: Icon(Icons.add),
      ),
      body: SafeArea(
        child: Container(
          color: Colors.lightBlue,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Container(
                padding: EdgeInsets.symmetric(horizontal: 30),
                margin: EdgeInsets.only(top: 50, left: 0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: &amp;lt;Widget&amp;gt;[
                    Container(
                      child: Container(
                        child: CircleAvatar(
                          child: Icon(
                            Icons.list_rounded,
                            color: Colors.lightBlue,
                            size: 75,
                          ),
                          radius: 50,
                          backgroundColor: Colors.white,
                        ),
                      ),
                    ),
                    Container(
                      child: Text(
                        "What To Do!",
                        style: TextStyle(
                            fontSize: 30, fontWeight: FontWeight.w300),
                      ),
                    ),
                  ],
                ),
              ),
              Expanded(
                child: Container(
                  padding: EdgeInsets.symmetric(horizontal: 20),
                  decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.only(
                          topLeft: Radius.circular(30),
                          topRight: Radius.circular(30))),
                  margin: EdgeInsets.only(top: 25),
                  child: ListView.builder(
                    itemCount: viewModel.taskDataCount,
                    itemBuilder: (context, index) {
                      return ListViewTaskItem(data: viewModel.taskData[index]);
                  },),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as you can see&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Widget build(BuildContext context, MainScreenViewModel viewModel, Widget? child)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now having access to the viewModel, meaning you can access all the state within that viewModel.&lt;/p&gt;

&lt;p&gt;and now here is the &lt;code&gt;MainScreenViewModel&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Here is the MainScreenViewModel..
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@injectable
class MainScreenViewModel extends BaseViewModel {
  List&amp;lt;TaskModel&amp;gt;? _tasksData;

  final ITaskRepository _taskRepository = getIt&amp;lt;TaskRepositoryImpl&amp;gt;();

  List&amp;lt;TaskModel&amp;gt; get taskData =&amp;gt; _tasksData ?? [];  
  int get taskDataCount =&amp;gt; _tasksData?.length ?? 0;

  @override
  void init() async{
    _tasksData = await _taskRepository.getAllTask();
    notifyListeners();
  }

  Future&amp;lt;void&amp;gt; onAddTaskClicked(String textValue) async {
    final data = TaskModel(description: textValue,title: textValue, isDone: false);
    _tasksData?.add(data);
    notifyListeners();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;on that code above everytime whenever the &lt;code&gt;init&lt;/code&gt; are invoke the viewModel will fetch the taskData from repositories &lt;code&gt;_taskRepository.getAllTask();&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. and here is the task repositories looks like..
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@singleton 
class TaskRepositoryImpl implements ITaskRepository{
  final String baseUrl = "run.mocky.io";

  @override
  Future&amp;lt;List&amp;lt;TaskModel&amp;gt;?&amp;gt; getAllTask() async{
    var url = Uri.https(baseUrl, "/v3/6bb86bda-08f1-4d7d-99c6-a975bc1201e0");
    final response = await networking.get(url);
    final responseBody = GetTaskDTO.fromJson(jsonDecode(utf8.decode(response.bodyBytes)) as Map&amp;lt;String,dynamic&amp;gt;);
    return responseBody.tasks;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the repositories will responsible to makesure the data availability of task. and whenever the &lt;code&gt;getAllTask()&lt;/code&gt; are invoked, repositories will fetch the data from the backendServies...&lt;/p&gt;

&lt;p&gt;so now we have this flow : &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvaml3b2sb51vmp9jcjqn.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvaml3b2sb51vmp9jcjqn.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;... &lt;/p&gt;
&lt;h1&gt;
  
  
  When Is The ViewModel Are Injected?
&lt;/h1&gt;

&lt;p&gt;ok up until here.. it was easy to understand right?. now we are moving to when exactly the viewModel are injected into view? how to make sure the viewModel are available when its needed.&lt;/p&gt;
&lt;h2&gt;
  
  
  First Lets take a look at the &lt;code&gt;MainScreenViewModel&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;pay attention to the declaration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@injectable
class MainScreenViewModel extends BaseViewModel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we put &lt;code&gt;@injectable&lt;/code&gt; to the &lt;code&gt;MainScreenViewModel&lt;/code&gt; &lt;strong&gt;telling&lt;/strong&gt; our Dependencies Injection &lt;strong&gt;DI&lt;/strong&gt; to make sure to create the &lt;code&gt;MainScreenViewModel&lt;/code&gt; whenever it was fetch by &lt;code&gt;getIt&lt;/code&gt;..&lt;br&gt;
for example like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final viewModel = getIt&amp;lt;MainScreenViewModel&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now getIt will create the object &lt;code&gt;MainScreenViewModel&lt;/code&gt; and provide it to &lt;code&gt;viewModel&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ok, then where is the real one?
&lt;/h2&gt;

&lt;p&gt;Back to our code structure, so where exactly the viewModel being injected to view? now you can open the &lt;code&gt;BaseView&lt;/code&gt; class as bellow :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final RouteObserver&amp;lt;ModalRoute&amp;lt;void&amp;gt;&amp;gt; routeObserver =
    RouteObserver&amp;lt;ModalRoute&amp;lt;void&amp;gt;&amp;gt;();

abstract class BaseView&amp;lt;T extends BaseViewModel&amp;gt; extends StatefulWidget {
  BaseView({Key? key}) : super(key: key);

  Widget build(BuildContext context, T viewModel, Widget? child);

  @override
  State&amp;lt;BaseView&amp;gt; createState() =&amp;gt; BaseViewState&amp;lt;T&amp;gt;();
}

class BaseViewState&amp;lt;T extends BaseViewModel&amp;gt; extends State&amp;lt;BaseView&amp;lt;T&amp;gt;&amp;gt;
    with RouteAware {
  T? viewModel = getIt&amp;lt;T&amp;gt;();

  @mustCallSuper
  @override
  void initState() {
    super.initState();
    viewModel?.init();
  }

  @mustCallSuper
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    // subscribe for the change of route
    routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute);
  }

  /// Called when the top route has been popped off, and the current route
  /// shows up.
  @mustCallSuper
  @override
  void didPopNext() {

    viewModel?.routingDidPopNext();
  }

  /// Called when the current route has been pushed.
  @mustCallSuper
  @override
  void didPush() {

    viewModel?.routingDidPush();
  }

  /// Called when the current route has been popped off.
  @mustCallSuper
  @override
  void didPop() {

    viewModel?.routingDidPop();
  }

  /// Called when a new route has been pushed, and the current route is no
  /// longer visible.
  @mustCallSuper
  @override
  void didPushNext() {

    viewModel?.routingDidPushNext();
  }

  @mustCallSuper
  @override
  void dispose() {
    routeObserver.unsubscribe(this);

    viewModel?.dispose();
    viewModel = null;
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider.value(
      value: viewModel,
      child: Consumer&amp;lt;T&amp;gt;(builder: widget.build),
    );
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now pay attention to the state implementation of &lt;code&gt;BaseViewState&lt;/code&gt;, see this code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T? viewModel = getIt&amp;lt;T&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this section is when the viewModel are injected to the view. so whenever you create a &lt;code&gt;Screen&lt;/code&gt; extending to &lt;code&gt;BaseView&lt;/code&gt; and you pump the &lt;code&gt;ViewModel&lt;/code&gt;, then the &lt;code&gt;ViewModel&lt;/code&gt; will become available for that view.&lt;/p&gt;

&lt;h2&gt;
  
  
  now, what kind of view model can be injected to view.
&lt;/h2&gt;

&lt;p&gt;see this code :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class BaseView&amp;lt;T extends BaseViewModel&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this code saying that the Type of view model can be injected to view is only a view model that extend to &lt;code&gt;BaseViewModel&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  here is the BaseViewModel looks like.
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abstract class BaseViewModel extends ChangeNotifier{
  BaseViewModel();

  /// This method is executed exactly once for each State object Flutter's
  ///  framework creates.
  void init() {}

  ///  This method is executed whenever the Widget's Stateful State gets
  /// disposed. It might happen a few times, always matching the amount 
  /// of times `init` is called.
  void dispose();

  /// Called when the top route has been popped off, and the current route
  /// shows up.
  void routingDidPopNext() {}

  /// Called when the current route has been pushed.
  void routingDidPush() {}

  /// Called when the current route has been popped off.
  void routingDidPop() {}

  /// Called when a new route has been pushed, and the current route is no
  /// longer visible.
  void routingDidPushNext() {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pay attention to here&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 BaseViewModel extends ChangeNotifier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this saying that all the viewModel we create that extending &lt;code&gt;BaseViewModel&lt;/code&gt; is a &lt;code&gt;ChangeNotifier&lt;/code&gt; type. this make our &lt;strong&gt;View Model State&lt;/strong&gt; able to be subscribed by other object, and any changes on our viewModel we can notify those changes to the viewModel subscriber.&lt;/p&gt;

&lt;h2&gt;
  
  
  So Where the provider scope are declared?
&lt;/h2&gt;

&lt;p&gt;now get back to the &lt;code&gt;BaseView&lt;/code&gt; class, and you'll find this section code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider.value(
      value: viewModel,
      child: Consumer&amp;lt;T&amp;gt;(builder: widget.build),
    );
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;whenever the &lt;code&gt;view&lt;/code&gt; Extend to &lt;code&gt;BaseView&lt;/code&gt; build the widget, the &lt;code&gt;BaseView&lt;/code&gt; will first declare the provider first, so all the widget here..&lt;br&gt;
&lt;code&gt;child: Consumer&amp;lt;T&amp;gt;(builder: widget.build)&lt;/code&gt; will have access to the viewModel state.&lt;/p&gt;
&lt;h1&gt;
  
  
  Where Are We Now? how about the repositories?
&lt;/h1&gt;

&lt;p&gt;remember this ?&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5emr2ja31rd9tth3ot72.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5emr2ja31rd9tth3ot72.png" alt="Image description"&gt;&lt;/a&gt; &lt;br&gt;
nah, up until here.. now we have this diagram.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ncihpt103kzs6q3lnve.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ncihpt103kzs6q3lnve.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  so now how about the repositories?
&lt;/h2&gt;

&lt;p&gt;remember we would like to make the repositories as a singleton object, so whoever use the repositories, the object will remain single in our thread but available to many view models like this.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5f2iyl7wsziblcau2by.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5f2iyl7wsziblcau2by.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
by the diagram above, it saying.. no matter how many screen are open with its own viewModel. and all those view model are using the Repositories(A) or Repositories(B) the Repositories itself remain only one object in our memory. thats why we have to told to our &lt;strong&gt;DI&lt;/strong&gt; to make our repository as &lt;code&gt;@singleton&lt;/code&gt;...&lt;a href="https://betterprogramming.pub/what-is-a-singleton-2dc38ca08e92" rel="noopener noreferrer"&gt;Here is the link explain more about the singleton&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;##Back to our app, &lt;br&gt;
as you can see previously on the &lt;code&gt;TaskRepositoryImpl&lt;/code&gt;&lt;br&gt;
the declaration is like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@singleton 
class TaskRepositoryImpl implements ITaskRepository
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this should make our TaskRepository as a singleton object, so in our case.. whenever &lt;code&gt;MainScreenViewModel&lt;/code&gt; require &lt;code&gt;TaskRepositoryImpl&lt;/code&gt; as the code bellow :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final ITaskRepository _taskRepository = getIt&amp;lt;TaskRepositoryImpl&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;our &lt;strong&gt;DI&lt;/strong&gt; will return the existing object of the repository in the memory..&lt;/p&gt;

&lt;p&gt;#Fine, Now how to run the code? &lt;br&gt;
well, talking about the &lt;a href="https://pub.dev/packages/injectable#setup" rel="noopener noreferrer"&gt;Injectable Package&lt;/a&gt; all those repositories and viewmodel with &lt;br&gt;
 &lt;code&gt;@injectable&lt;/code&gt; and &lt;code&gt;@singleton&lt;/code&gt; will actually generating implementation file before the flutter itself compiling.. so before we run our application, whenever you create new class with injectable annotation. you have to run this command&lt;br&gt;
&lt;code&gt;fvm flutter pub run build_runner build --delete-conflicting-outputs&lt;/code&gt;&lt;br&gt;
you have to ask the build runner to create the implementation file.&lt;/p&gt;

&lt;h1&gt;
  
  
  Well, What is next?
&lt;/h1&gt;

&lt;p&gt;oke, we haven't talk about how the repositories can communicate with the rest API?.. &lt;br&gt;
lets discuss about it &lt;a href="https://dev.to/noveriojoee/mvvm-with-flutter-part2freeze-48m9"&gt;MVVM With Flutter (Part2)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;until then, you can enjoy the code &lt;a href="https://github.com/noveriojoee/what_to_do_app_flutter" rel="noopener noreferrer"&gt;Here..&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks Guys, hope this help for you to start the project with flutter.&lt;br&gt;
P.S This are my codebaseline whenever i start a new project feel free to clone it.&lt;/p&gt;

&lt;p&gt;Next : &lt;br&gt;
&lt;a href="https://dev.to/noveriojoee/mvvm-with-flutter-part2freeze-48m9"&gt;MVVM With Flutter part 2&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/noveriojoee/flutter-how-to-use-freeze-3oba"&gt;How To Use Flutter with Freeze&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/noveriojoee/flutter-how-to-use-injectable-4oag"&gt;How To Use Flutter with Injectable&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>tutorial</category>
      <category>devjournal</category>
    </item>
  </channel>
</rss>
