<?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>DEV Community: Safal Shrestha</title>
    <description>The latest articles on DEV Community by Safal Shrestha (@safalshrestha109).</description>
    <link>https://dev.to/safalshrestha109</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%2F901221%2F771799d9-61eb-45c0-83ad-b5ce3c75552c.png</url>
      <title>DEV Community: Safal Shrestha</title>
      <link>https://dev.to/safalshrestha109</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/safalshrestha109"/>
    <language>en</language>
    <item>
      <title>Flutter Platform Channels</title>
      <dc:creator>Safal Shrestha</dc:creator>
      <pubDate>Wed, 11 Oct 2023 04:33:50 +0000</pubDate>
      <link>https://dev.to/safalshrestha109/flutter-platform-channels-pgi</link>
      <guid>https://dev.to/safalshrestha109/flutter-platform-channels-pgi</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZP4UOtxq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dyvqjbxpgt80fz9f1w5f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZP4UOtxq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dyvqjbxpgt80fz9f1w5f.png" alt="Image description" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Flutter Platform Channels
&lt;/h1&gt;

&lt;p&gt;In this, we will learn how platform channels can be used to communicate between Flutter and Native Platform. They are derived from the binary messaging foundation. This is the second part of the article “&lt;a href="https://dev.to/safalshrestha109/flutter-communicating-with-the-native-platform-15ki"&gt;&lt;strong&gt;Flutter: Communicating with the Native Platform&lt;/strong&gt;&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;Flutter’s platform channel allows Flutter to communicate with the native platform. These channels enable you to pass data back and forth between Flutter and the native platform.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Platform Channel is the construct that combines a channel name and a codec.For example, if we look at the &lt;a href="https://github.com/flutter/flutter/blob/12fccda598/packages/flutter/lib/src/services/platform_channel.dart#L253"&gt;&lt;strong&gt;MethodChannel&lt;/strong&gt;&lt;/a&gt; code, we can see it combining the codec and the channel name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;MessageCodec&lt;/strong&gt; describes a message encoding/decoding mechanism. It helps with serializing and deserializing messages sent between Flutter and native code. Flutter has four predefined MessageCodec implementations. They are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/services/StringCodec-class.html"&gt;StringCodec&lt;/a&gt;: MessageCodec with UTF-8 encoded String messages. It is used for passing strings.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/services/BinaryCodec-class.html"&gt;BinaryCodec&lt;/a&gt;: MessageCodec with unencoded binary messages represented using &lt;a href="https://api.flutter.dev/flutter/dart-typed_data/ByteData-class.html"&gt;ByteData&lt;/a&gt;. It is used if encoding/decoding is not needed.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/services/JSONMessageCodec-class.html"&gt;JSONMessageCodec&lt;/a&gt;: MessageCodec with UTF-8 encoded JSON messages. It is used to send JSON strings.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/services/StandardMessageCodec-class.html"&gt;StandardMessageCodec&lt;/a&gt;: MessageCodec using the Flutter standard binary encoding. It is the default MessageCode used by the channels. It’s a versatile and efficient codec that can handle various data types.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;You can create your own custom MessageCodec implementation. You’ll have to implement compatible encoding and decoding in Dart, Java/Kotlin, and Objective-C/Swift.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K5HR6TTl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AqwvnLdUWK2EMx28vnntU6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K5HR6TTl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AqwvnLdUWK2EMx28vnntU6w.png" alt="Architectural overview: platform channels" width="580" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Platform Channels
&lt;/h4&gt;

&lt;p&gt;There are three types of platform channels in Flutter. They are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;MethodChannel&lt;/strong&gt;: It is used to invoke the method in the native platform and get some value in return. Flutter sends a method call to the native platform which processes it and returns some value. It is for invoking functions, passing data to the native platform, and expecting a response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EventChannel&lt;/strong&gt;: It is used when you want to stream data continuously from the native platform to the flutter. It establishes a unidirectional channel from native code to Dart, allowing native code to send events or stream data to Dart asynchronously. It is helpful if you want to receive continuous data like sensor data, real-time updates, Wi-Fi connection state, and so on. It is for streaming data from the platform to Flutter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BasicMessageChannel&lt;/strong&gt;: It is designed for sending and receiving asynchronous messages between Dart and native code in both directions. It can be used for continuous, bidirectional communication.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Enough with the definition, now let’s dive into the code.&lt;/p&gt;




&lt;h4&gt;
  
  
  MethodChannel
&lt;/h4&gt;

&lt;p&gt;It is a named channel for communicating with the Flutter application using asynchronous method calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Dart:&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;import 'package:flutter/services.dart';
class MethodChannelCounter {
  // Create a method channel with the channel name "methodChannelDemo"
  static MethodChannel methodChannel = const MethodChannel('methodChannelDemo');

  // Define a method to increment the counter on the native side
  static Future&amp;lt;int&amp;gt; increment({required int counterValue}) async {
    // Invoke the 'increment' method on the native side with the 'count' argument
    final result = await methodChannel.invokeMethod&amp;lt;int&amp;gt;('increment', {'count': counterValue});

    // Return the result received from the native side
    return result!;
  }

  // Define a method to decrement the counter on the native side
  static Future&amp;lt;int&amp;gt; decrement({required int counterValue}) async {
    // Invoke the 'decrement' method on the native side with the 'count' argument
    final result = await methodChannel.invokeMethod&amp;lt;int&amp;gt;('decrement', {'count': counterValue});

    // Return the result received from the native side
    return result!;
  }

  // Define a method to retrieve a random value from the native side
  static Future&amp;lt;int&amp;gt; randomValue() async {
    // Invoke the 'random' method on the native side
    final result = await methodChannel.invokeMethod&amp;lt;int&amp;gt;('random');

    // Return the result received from the native side
    return result!;
  }

  // Define a method 'tryMe' (custom method) to interact with the native side
  static Future&amp;lt;int&amp;gt; tryMe() async {
    // Invoke the 'tryMe' custom method on the native side
    final result = await methodChannel.invokeMethod&amp;lt;int&amp;gt;('tryMe');

    // Return the result received from the native side
    return result!;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can respond to the method called from the native side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Android:&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;
//MethodChannel to handle communication between Flutter and the platform.
MethodChannel(flutterEngine.dartExecutor, "methodChannelDemo")
    .setMethodCallHandler { call, result -&amp;gt;
        //call represents the incoming method call from Flutter
        //result represents result or response that you send back to Flutter after handling the method call.
        // Retrieve the 'count' argument from the method call, if provided.
        val count: Int? = call.argument&amp;lt;Int&amp;gt;("count")
        // Determine which method was called from Flutter.
        when (call.method) {
            // Handle the 'random' method call.
            "random" -&amp;gt; {
                // Generate a random number between 0 and 100 and send it back to Flutter as a success result.
                result.success(Random(System.nanoTime()).nextInt(0, 100))
            }
            // Handle the 'increment' and 'decrement' method calls.
            "increment", "decrement" -&amp;gt; {
                // Check if the 'count' argument is missing or invalid.
                if (count == null) {
                    // If the 'count' argument is missing or invalid, send an error result to Flutter.
                    result.error("INVALID ARGUMENT", "Invalid Argument", null)
                } else {
                    // If the 'count' argument is valid, perform the requested operation.
                    if (call.method == "increment") {
                        // Increment the 'count' and send the updated value to Flutter as a success result.
                        result.success(count + 1)
                    } else {
                        // Decrement the 'count' and send the updated value to Flutter as a success result.
                        result.success(count - 1)
                    }
                }
            }
            // Handle any other method calls that are not implemented.
            else -&amp;gt; {
                // Send a "not implemented" result to Flutter.
                result.notImplemented()
            }
          }
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gfF6v5SA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AamcRT_9DPv-FeeleslPU7w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gfF6v5SA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AamcRT_9DPv-FeeleslPU7w.gif" alt="Android Method Channel Demo" width="474" height="994"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In iOS:&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;//FlutterMethodChannel to handle communication between Flutter and the platform.
FlutterMethodChannel(name: "methodChannelDemo", binaryMessenger: binaryMessenger)
    .setMethodCallHandler { call, result in
        //call represents the incoming method call from Flutter
        //result represents result or response that you send back to Flutter after handling the method call.
        // Retrieve the 'count' argument from the method call, if provided.
        let count = (call.arguments as? NSDictionary)?["count"] as? Int

        // Determine which method was called from Flutter.
        switch call.method {
        case "random":
            // Generate a random number between 0 and 100 and send it back to Flutter as a result.
            result(Int.random(in: 0..&amp;lt;100))
        case "increment", "decrement":
            if count == nil {
                // If the 'count' argument is missing or invalid, send a FlutterError back to Flutter.
                result(FlutterError(code: "INVALID ARGUMENT", message: "Invalid Argument", details: nil))
            } else {
                // If the 'count' argument is valid, perform the requested operation.
                let updatedCount = call.method == "increment" ? count! + 1 : count! - 1
                result(updatedCount)
            }
        default:
            // Handle any other method calls that are not implemented.
            result(FlutterMethodNotImplemented)
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hUyk9XLk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AgFyRjewlLX9RMFpFPzuKFw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hUyk9XLk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AgFyRjewlLX9RMFpFPzuKFw.gif" alt="iOS Method Channel Demo" width="570" height="1288"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  EventChannel
&lt;/h4&gt;

&lt;p&gt;It is a named channel for communicating with platform plugins using event streams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Dart:&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;import 'package:flutter/services.dart';

class EventChannelTimer {
  // Create the EventChannel with the specified name "eventChannelTimer".
  static const _eventChannelCustom = EventChannel('eventChannelTimer');

  // Create a method to get the timerValue stream.
  static Stream&amp;lt;int&amp;gt; get timerValue {
   // Use the receiveBroadcastStream method to create a stream of events from the platform side.
    // Map the dynamic events to integers as they are received.
    return _eventChannelCustom.receiveBroadcastStream().map(
          (dynamic event) =&amp;gt; event as int,
    );
  }

}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In Android:&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;// Create an EventChannel and set its stream handler.
EventChannel(flutterEngine.dartExecutor, "eventChannelTimer")
    .setStreamHandler(CustomStreamHandler())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;CustomStreamHandler&lt;/code&gt; is a custom class that implements &lt;code&gt;StreamHandler&lt;/code&gt; interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CustomStreamHandler : EventChannel.StreamHandler {
    private val job = SupervisorJob()
    private val scope = CoroutineScope(Dispatchers.Default + job)
    private var isListening = false
    private var counter = 0

    // Code to set up and manage the event stream 
    override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
        if (events != null) {
            isListening = true
            scope.launch {
                while (isListening) {
                    val value = counter++
                    withContext(Dispatchers.Main) {
                        // Send the value to Flutter as a success event.
                        events.success(value)
                    }
                    delay(1000) // Send value every 1000 milliseconds
                }
            }
        }

    }

    override fun onCancel(arguments: Any?) {
        // Set isListening to false to stop generating events.
        isListening = false
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JFcOILDb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A2pPRSJ7D9hqEAGt_8FV9Qg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JFcOILDb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A2pPRSJ7D9hqEAGt_8FV9Qg.gif" alt="Android Event Channel Demo" width="474" height="994"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In iOS:&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;//Event Channel
FlutterEventChannel(name: "eventChannelTimer", binaryMessenger: flutterViewController.binaryMessenger)
    .setStreamHandler(CustomEventHandler())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;CustomEventHandler&lt;/code&gt; is a custom class that implements &lt;code&gt;FlutterStreamHandler&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Foundation

class CustomEventHandler: NSObject,FlutterStreamHandler{

    private var counter = 0
    private var timer: Timer?

    // Code to set up and manage the event stream
    func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -&amp;gt; FlutterError? {
        events(counter)
        timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
           // Send the value to Flutter as a success event.
           events(self.counter)
           self.counter += 1
       }
       return nil
    }

    func onCancel(withArguments arguments: Any?) -&amp;gt; FlutterError? {
        timer?.invalidate()
              timer = nil
              return nil
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zmB_h4eC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A1Llea6j_5VQYa4NG6Fft3Q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zmB_h4eC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A1Llea6j_5VQYa4NG6Fft3Q.gif" alt="iOS Event Channel Demo" width="570" height="1288"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  BasicMessageChannel
&lt;/h4&gt;

&lt;p&gt;It is a named channel for communicating with platform plugins using asynchronous message passing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Dart:&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;
class BasicChannelImage {
  // Declare a private static constant for the BasicMessageChannel
  static const _basicMessageChannel =
    BasicMessageChannel&amp;lt;dynamic&amp;gt;('platformImageDemo', StandardMessageCodec(),);

  // Define a static method to request and receive an image from the platform
  static Future&amp;lt;Uint8List&amp;gt; getImage() async {
    // Send a message to request an image from the platform using the BasicMessageChannel.
    final reply = await _basicMessageChannel.send('getImage') as Uint8List?;

    // Check if the reply is null, indicating an error in loading the image.
    if (reply == null) {
      // If null, throw a PlatformException to indicate an error.
      throw PlatformException(
        code: 'Error',
        message: 'Failed to load Platform Image',
        details: null,
      );
    }

    // Return the received image data as a Uint8List.
    return reply;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In Android:&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;//BasicMessageChannel
BasicMessageChannel(flutterEngine.dartExecutor, "platformImageDemo", StandardMessageCodec())
    .setMessageHandler { message, reply -&amp;gt;
        //message represents the incoming message from Flutter
        //result represents result or response that you send back to Flutter after handling the method call.
        // Toast message indicating the received message from Flutter.
        Toast.makeText(this, "Received message from Flutter: $message", Toast.LENGTH_SHORT).show();
        // Check if the received message is "getImage."       
       if (message == "getImage") {
            // Open the image file from the Android app's assets.
            val inputStream: InputStream = assets.open("flutter.png")
            // Read the image data from the input stream and send it as a reply.
            reply.reply(inputStream.readBytes())
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mj_CUKf3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AUoE1J9cFsslT78SiAJEk1A.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mj_CUKf3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AUoE1J9cFsslT78SiAJEk1A.gif" alt="Android BasicMessageChannelDemo" width="474" height="994"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In iOS:&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;//BasicMessage Channel
FlutterBasicMessageChannel(name: "platformImageDemo", binaryMessenger: flutterViewController.binaryMessenger, codec: FlutterStandardMessageCodec.sharedInstance()).setMessageHandler{
    (message: Any?, reply: FlutterReply) -&amp;gt; Void in
     // Handle incoming messages from Flutter and reply to them
    if(message as! String == "getImage") {
        // Handle incoming messages from Flutter and reply to them
        guard let image = UIImage(named: "flutter") else {
            reply(nil)
            return
        }
        // If the image is successfully loaded, encode it as bytes and reply with it
        reply(FlutterStandardTypedData(bytes: image.jpegData(compressionQuality: 1)!))
    }
}You can find my example project in Git Hub.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_0pJ3_at--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://miro.medium.com/v2/1%2AIa1hsTgLGXlmfrfBRWdpyA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_0pJ3_at--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://miro.medium.com/v2/1%2AIa1hsTgLGXlmfrfBRWdpyA.gif" alt="iOS Basic MessageChannel Demo" width="570" height="1288"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;You can configure channels with any method codec, including custom ones.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;You can find my example project in &lt;a href="https://github.com/Safal-Shrestha-SS/Flutter_Platform_Channel"&gt;Git Hub&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article, we discovered how to use the platform channel to communicate between Flutter and Native platforms. Hope now you can write your platform channel to make your awesome Flutter project and plugins&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Stay Curious and Follow to make sure to catch the next post.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Previous&lt;/strong&gt; &lt;strong&gt;Post&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://dev.to/safalshrestha109/flutter-communicating-with-the-native-platform-15ki"&gt;&lt;strong&gt;Flutter: Communicating with the Native Platform&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Flutter is the perfect tool for cross-platform apps. You can easily make a performant and beautiful app with Flutter.&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>Flutter: Communicating with the Native Platform</title>
      <dc:creator>Safal Shrestha</dc:creator>
      <pubDate>Sun, 20 Aug 2023 04:13:41 +0000</pubDate>
      <link>https://dev.to/safalshrestha109/flutter-communicating-with-the-native-platform-15ki</link>
      <guid>https://dev.to/safalshrestha109/flutter-communicating-with-the-native-platform-15ki</guid>
      <description>&lt;p&gt;&lt;strong&gt;Flutter&lt;/strong&gt; is the perfect tool for cross-platform apps. You can easily make a performant and beautiful app with Flutter. But in order to access the native platform API, you need to communicate with the native platform. Flutter can only understand Dart language and the native platform can only understand their respective programming language. So, how do Flutter and the native platform communicate with each other? It has to be a language of both Flutter and the native platform. So, what is used to communicate with each other?&lt;/p&gt;

&lt;p&gt;Take a guess&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xXjaOtTk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/7998/0%2A1WIV4lK5gQNs_-09" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xXjaOtTk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/7998/0%2A1WIV4lK5gQNs_-09" alt="Photo by [Markus Winkler](https://unsplash.com/@markuswinkler?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you guessed, &lt;strong&gt;binary&lt;/strong&gt; then you guessed it right.&lt;/p&gt;

&lt;p&gt;Flutter talks to the native platform by passing binary messages. To distinguish the messages, channels are used. So how do we send these binary messages across the platform?&lt;/p&gt;

&lt;p&gt;We can make use of BinaryMessenger class to send messages across the platform.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://api.flutter.dev/flutter/services/BinaryMessenger-class.html"&gt;BinaryMessenger&lt;/a&gt; class is the messenger class defined by the Flutter team which sends binary data across the Flutter platform barrier. This class also registers handlers for incoming messages.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BN0RSfSl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Azrs5Z-yYTqF7_a0V" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BN0RSfSl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Azrs5Z-yYTqF7_a0V" alt="" width="800" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code below sends a binary message to the platform using BinaryMessenger through the channel ‘foo’.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'dart:convert'; 
import 'package:flutter/services.dart';
import 'dart:ui' as ui; 

class CustomBinaryMessenger {

  // A static method for sending a given value as a binary message.
  static Future&amp;lt;void&amp;gt; givenValue(String data) async {
    // Create a buffer to hold the binary data.
    final WriteBuffer buffer = WriteBuffer();

    // Convert the given data string into UTF-8 bytes.
    final List&amp;lt;int&amp;gt; utf8Bytes = utf8.encode(data);

    // Convert the UTF-8 bytes into an Uint8List.
    final Uint8List utf8Int8List = Uint8List.fromList(utf8Bytes);

    // Put the Uint8List into the buffer.
    buffer.putUint8List(utf8Int8List);

    // Get the final binary message data from the buffer.
    final ByteData message = buffer.done();

    // Send the binary message using the 'Messenger' class through chaneel `foo`.
    await Messenger().send('foo', message);

    return;
  }
}

// A custom implementation of the BinaryMessenger interface. I am only handling
// send here for the sake of example
class Messenger implements BinaryMessenger {
  @override
  // Handle incoming platform messages. In this case, it throws an unsupported error.
  Future&amp;lt;void&amp;gt; handlePlatformMessage(
      String channel, ByteData? data, PlatformMessageResponseCallback? callback) {
    throw UnsupportedError("This platform message handling is not supported.");
  }

  @override
  // Send a binary message to the platform using the 'ui.PlatformDispatcher'.
  Future&amp;lt;ByteData?&amp;gt;? send(String channel, ByteData? message) {
    // Use the 'ui.PlatformDispatcher' to send the platform message and handle the callback
    ui.PlatformDispatcher.instance.sendPlatformMessage(channel, message, (data) {});

    return null;
  }

  @override
  // Set a handler for incoming messages. In this case, it throws an unsupported error.
  void setMessageHandler(String channel, MessageHandler? handler) {
    throw UnsupportedError("Setting message handler is not supported.");
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now on Android, you can receive it using the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MainActivity : FlutterActivity() {

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        // Configure the binary messenger to handle messages from Flutter.
        flutterEngine.dartExecutor.binaryMessenger.setMessageHandler("foo") { message, reply -&amp;gt;
        message?.order(ByteOrder.nativeOrder()) // Ensure proper byte order.
        val data = decodeUtf8String(message!!) // Decode the binary data to UTF-8 string.
        val x = message.toString() // Convert the message to a string for demonstration.
        // Display a Toast with the received message.
        Toast.makeText(this, "Received message from Flutter: $data", Toast.LENGTH_SHORT).show()
        reply.reply(null)
        }

        // Call the super method to finalize the FlutterEngine configuration.
        super.configureFlutterEngine(flutterEngine)
    }

    // Function to decode a ByteBuffer into a UTF-8 string.
    private fun decodeUtf8String(byteBuffer: ByteBuffer): String {
        return try {
            val byteArray = ByteArray(byteBuffer.remaining())
            byteBuffer.get(byteArray)
            String(byteArray, Charsets.UTF_8)
        } catch (e: Exception) {
            e.printStackTrace()
            ""
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly for IOS,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -&amp;gt; Bool {
      let flutterViewController = self.window.rootViewController as! FlutterViewController

      // Configure the binary messenger to handle messages from Flutter.
      let binaryMessenger = flutterViewController.engine!.binaryMessenger
      binaryMessenger.setMessageHandlerOnChannel("foo", binaryMessageHandler: { [weak self] message, reply in
          // Ensure proper byte order.
           guard let message = message else {
               reply(nil)
               return
           }
           // Decode the binary data to UTF-8 string.
           if let data = String(data: message, encoding: .utf8) {
               let x = message.debugDescription // Convert the message to a string for demonstration.
               // Display an alert with the received message.
               let alertController = UIAlertController(
                   title: "Message from Flutter",
                   message: data,
                   preferredStyle: .alert
               )
               alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
               flutterViewController.present(alertController, animated: true, completion: nil)
           }
           reply(nil)
      }
    )

      GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

    // Function to decode a ByteBuffer into a UTF-8 string.
    private func decodeUtf8String(byteBuffer: FlutterStandardTypedData) -&amp;gt; String? {
            let byteArray = [UInt8](byteBuffer.data)
            return  String(bytes: byteArray, encoding: .utf8)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8Xh2HNhL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ANoZUZ3qlqYoIdC3Y-glFgQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Xh2HNhL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ANoZUZ3qlqYoIdC3Y-glFgQ.gif" alt="" width="600" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Communication is bidirectional, you can send from the native platform to Flutter. Make sure to implement &lt;code&gt;setMessageHandler&lt;/code&gt; in our class &lt;code&gt;Messenger&lt;/code&gt; to receive binary messages from the native platform and decode them. Just reverse the flow of our code and you can send:&lt;br&gt;
In IOS, using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Send a binary message from platform to the flutter. It takes channel and message
// as params
flutterViewController.engine!.binaryMessenger.send(onChannel: &amp;lt;#T##String#&amp;gt;, message: &amp;lt;#T##Data?#&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Android, using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Send a binary message from platform to the flutter.It takes channel and message
// as params
flutterEngine.dartExecutor.binaryMessenger.send()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Messages and responses are passed asynchronously, to ensure the user interface remains responsive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, you can pass messages from Flutter to the native platform and vice versa. But, as you can see working with binary messages we have to worry about encoding, decoding, and handling the register, and so on. It can lead to verbose code and increase the complexity of the code. So, what is the solution?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Platform channel:&lt;/strong&gt; Making the above process easier leads to the platform channel. A platform channel is a construct that combines a channel name and a codec. This pairing enables the conversion of messages into binary format for transmission and facilitates their conversion back from binary format upon reception. It makes working with the native platform a lot easier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Have a look at one of the Platform channels named &lt;a href="https://github.com/flutter/flutter/blob/efbf63d9c6/packages/flutter/lib/src/services/platform_channel.dart#L245"&gt;&lt;strong&gt;MethodChannel&lt;/strong&gt;&lt;/a&gt;. If you look at the code, you can see it handling its own BinaryMessenger .&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In my next post, we will look at the &lt;strong&gt;Platform channel&lt;/strong&gt; and how to use it to pass messages from Flutter to the native platform and vice versa.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Stay Curious and Follow to not miss the next post.&lt;/strong&gt;&lt;/p&gt;




</description>
      <category>flutter</category>
      <category>android</category>
      <category>ios</category>
      <category>crossplatform</category>
    </item>
    <item>
      <title>Publish and upgrade your Flutter Package on pub.dev</title>
      <dc:creator>Safal Shrestha</dc:creator>
      <pubDate>Mon, 09 Jan 2023 11:04:11 +0000</pubDate>
      <link>https://dev.to/codingmountain/publish-and-upgrade-your-flutter-package-on-pubdev-2ilc</link>
      <guid>https://dev.to/codingmountain/publish-and-upgrade-your-flutter-package-on-pubdev-2ilc</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.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%2F2417fx79gjvmnudisdp2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F2417fx79gjvmnudisdp2.png" alt="Image description" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You are developing your awesome flutter app implementation awesome functionalities and awesome widgets. Now you want to share that awesomeness with others.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you do so?
&lt;/h3&gt;

&lt;p&gt;Of course. By publishing your own awesome widgets as a package.&lt;/p&gt;

&lt;p&gt;But how do you do so?&lt;/p&gt;

&lt;p&gt;In this article, I want to show how to create and publish a package in “&lt;a href="https://pub.dev/" rel="noopener noreferrer"&gt;pub.dev&lt;/a&gt; ”.&lt;/p&gt;

&lt;p&gt;First, pick a name for your package, mine will be **hello_world **which will return a container with the text “Hello World”. Then run&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter create --template=package hello_world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;in your terminal. It will create a template for your package in my case &lt;strong&gt;hello_world&lt;/strong&gt;. In the template, you will find different files. Let’s look at some of them:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F3yfxh7ehbfahdrsb6feg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F3yfxh7ehbfahdrsb6feg.png" width="800" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CHANGELOG.md:&lt;/strong&gt; Here you will write the changes you made/added to the project. It is a record of changes for tracking your package and its version. It will appear in the changelog of your package.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LICENSE:&lt;/strong&gt; You can add your license here.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;pubspec.yaml:&lt;/strong&gt; Your package dependencies go here.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;README.md:&lt;/strong&gt; It will appear in the Readme of your package. It can contain brief summary of your package along with documentation, example, installation, and so on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;lib:&lt;/strong&gt; It is where you will write your package&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now let’s write the package.&lt;/p&gt;

&lt;p&gt;Inside the lib, we will find &lt;em&gt;hello_world.dart&lt;/em&gt;. Inside you will find the template.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;library hello_world;

/// A Calculator.
class Calculator {
  /// Returns [value] plus 1.
  int addOne(int value) =&amp;gt; value + 1;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;The library keyword is used to give the library a name, which can be used to reference it from other parts of the code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s write our package.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;library hello_world;

import 'package:flutter/material.dart';

class HelloWorld extends StatelessWidget {
  const HelloWorld({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text("Hello World!"),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Oh, and let’s initialize a Git repo in our project which helps when we need to publish our package.&lt;/p&gt;

&lt;p&gt;Now we are ready to publish our package. Right?&lt;/p&gt;

&lt;p&gt;Wrong. Before publishing the package, we still go something left to do. First, let’s organize our code.&lt;/p&gt;

&lt;p&gt;We will create a new folder *lib/src *and put our implementation/widget there.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can have any folder structure, but it is recommended to use lib/src . [source](&lt;a href="https://dart.dev/guides/libraries/create-library-packages%5C" rel="noopener noreferrer"&gt;https://dart.dev/guides/libraries/create-library-packages\&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After that our project will look like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fyeayghc5qa9xftbet8uc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fyeayghc5qa9xftbet8uc.png" width="308" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have moved out implementation code to &lt;em&gt;hello.dart *inside *src&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;E.g., &lt;em&gt;hello.dart&lt;/em&gt;&lt;/p&gt;

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

class HelloWorld extends StatelessWidget {
  const HelloWorld({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text("Hello World!"),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;hello_world.dart&lt;/em&gt; is used as a barrel file to export our implementation.&lt;/p&gt;

&lt;p&gt;E.g., &lt;em&gt;hello_world.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;library hello_world;

export "src/hello.dart";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;A barrel file is a way to integrate multiple exports from different files into a single export.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now our package is complete. Before publishing let’s add an example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fwo1apn233vya8omb3lc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fwo1apn233vya8omb3lc6.png" width="788" height="63"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The example will contain a code from &lt;em&gt;example/lib/main.dart.&lt;/em&gt; We haven’t yet created an example folder.&lt;/p&gt;

&lt;p&gt;Let’s run the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter create example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After this, you will have a flutter project with a name example. Inside pubspec.yaml of example you can import your package in example with *path: ../ *instead of version.&lt;/p&gt;

&lt;p&gt;E.g. &lt;em&gt;example/pubspec.yaml&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: example
description: A new Flutter project.

publish_to: 'none'

version: 1.0.0+1

environment:
  sdk: '&amp;gt;=2.18.5 &amp;lt;3.0.0'

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  hello_world:
    path: ../

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0

flutter:
  uses-material-design: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now my &lt;em&gt;lib/main.dart&lt;/em&gt; will be&lt;/p&gt;

&lt;p&gt;E.g &lt;em&gt;lib/main.dart&lt;/em&gt;&lt;/p&gt;

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'My Package'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State&amp;lt;MyHomePage&amp;gt; createState() =&amp;gt; _MyHomePageState();
}

class _MyHomePageState extends State&amp;lt;MyHomePage&amp;gt; {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: const HelloWorld(),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will be displayed in the example section of pub.dev of your package.&lt;/p&gt;

&lt;p&gt;Now let’s change CHANGELOG.md&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## 0.0.1

* Initial release of Hello World.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now let’s write README.md&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Hello World
Gives Hello World widget

## Features
  - Hello world
  - Awesome
  - Null Safety

## Example Project
 Check the `example` folder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, let’s add a license to our package. You can use &lt;a href="https://choosealicense.com/licenses/" rel="noopener noreferrer"&gt;**this &lt;/a&gt;**website to help you choose your license.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIT License

Copyright (c) 2022 Safal Shrestha

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can add the homepage and repository field to your pubspec.yaml .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fk4pbtknztpvwymlnc7cl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fk4pbtknztpvwymlnc7cl.png" width="401" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now run&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter pub publish --dry-run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This command will analyze our package and warns us if there is any error/issues in our packages. After that, you can publish your package to pub.dev with the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter pub publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Remember publishing is forever. After running the command, you will be asked to authenticate, and your package will be published after authenticating.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to upgrade your package. Increase your package version and run flutter pub publish again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this post, you learned how to publish and upgrade your package. If you have any problem, you can reference my package &lt;a href="https://pub.dev/packages/focus_widget_list" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://pub.dev/packages/focus_widget_list" rel="noopener noreferrer"&gt;&lt;strong&gt;focus_widget_list | Flutter Package&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Dart enhanced enum with custom values</title>
      <dc:creator>Safal Shrestha</dc:creator>
      <pubDate>Wed, 04 Jan 2023 15:55:49 +0000</pubDate>
      <link>https://dev.to/safalshrestha109/dart-enhanced-enum-with-custom-values-1g9i</link>
      <guid>https://dev.to/safalshrestha109/dart-enhanced-enum-with-custom-values-1g9i</guid>
      <description>&lt;p&gt;An enum type is &lt;strong&gt;a special data type that enables for a variable to be a set of predefined constants&lt;/strong&gt;. It helps to make code readable and easier to understand.&lt;/p&gt;

&lt;p&gt;For example, you might use an enum to define the gender of the people, like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum Gender{
  Male,
  Female,
  Other
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now if you run the following code&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void main() {
  print(Gender.Female.index);          // 1
  print(Gender.Male.index);            // 0
  print(Gender.Male);                  //Gender.Male
  print(Gender.values[2]);             //Gender.Other
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can access &lt;em&gt;index *of the element defined and element using the *index&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now what if we want to define custom value to the element of our enum. What if we want to assign number 1 to Male, 2 to Female and null to Other, and what if we want to return element of enum from the values that we defined for the element?&lt;/p&gt;

&lt;p&gt;How can we do so ?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum Gender {
  Male(1),
  Female(2),
  Other(null);
  const Gender(this.number);
  final int? number;
  static Gender getByValue(int? i) {
    return Gender.values.firstWhere((element) =&amp;gt; element.number == i);
  }
}

void main() {
  print(Gender.getByValue(1));    //Gender.Male 
  print(Gender.getByValue(2));    //Gender.Female
  print(Gender.getByValue(3));    //Uncaught Error: Bad state: No element
  print(Gender.getByValue(null)); //Gender.Other
  print(Gender.Other.number);     //null
  print(Gender.Female.index);     //1
  print(Gender.values[2]);        //Gender.Other
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the above code snippet, we defined our values to the element of the the enum Gender. So, we can access the element of enum using the values we defined and vice versa. We can also access element using &lt;em&gt;index&lt;/em&gt; and &lt;em&gt;values&lt;/em&gt; like before. To use the values we defined, we can use the function &lt;em&gt;getByValue&lt;/em&gt; that we created and &lt;em&gt;number&lt;/em&gt; variable we defined.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks for Reading! ✌️
&lt;/h2&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>Learning TDD with Clean Architecture for Flutter Part IV</title>
      <dc:creator>Safal Shrestha</dc:creator>
      <pubDate>Wed, 04 Jan 2023 15:51:00 +0000</pubDate>
      <link>https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-part-iv-16b4</link>
      <guid>https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-part-iv-16b4</guid>
      <description>&lt;p&gt;Part &lt;strong&gt;I &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-part-i-46nk"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Part &lt;strong&gt;II &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-domain-layer-part-ii-1pi5"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Part &lt;strong&gt;III &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-data-layer-part-iii-1fff"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the final part of the series. Let’s get write into it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fkmffnqmizz2zujbgca3l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fkmffnqmizz2zujbgca3l.png" alt="Presentation Layer" width="493" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Presentation Layer
&lt;/h2&gt;

&lt;p&gt;It is the UI part. Code is written to give life to the app. It is the part where users interact. It consists of pages, widgets, and state management (bloc, provider, etc).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F09ya9td80mjyldws1q3n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F09ya9td80mjyldws1q3n.png" width="136" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pages
&lt;/h3&gt;

&lt;p&gt;It consists of the screens to be displayed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Widgets
&lt;/h3&gt;

&lt;p&gt;It consists of the widgets that are being used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bloc
&lt;/h3&gt;

&lt;p&gt;Let’s create a bloc for the movie list state management.&lt;/p&gt;

&lt;p&gt;Eg. Movie Bloc &lt;em&gt;lib/features/movie/presentation/bloc/movie_bloc.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:movie_show/core/usecases/usecase.dart';
import 'package:movie_show/features/movie/domain/entities/movie_entity.dart';
import 'package:movie_show/features/movie/domain/usecases/get_movie_list_usecase.dart';

part 'movie_event.dart';
part 'movie_state.dart';

class MovieBloc extends Bloc&amp;lt;MovieEvent, MovieState&amp;gt; {
  final GetMovieListUsecase getMovieListUsecase;

  MovieBloc({required this.getMovieListUsecase}) : super(MovieInitial()) {
    on&amp;lt;MovieEvent&amp;gt;((event, emit) async =&amp;gt; await _onGetMovies(emit));
  }

  Future&amp;lt;void&amp;gt; _onGetMovies(Emitter&amp;lt;MovieState&amp;gt; emit) async {
    emit(MovieLoading());
    final failureOrMovieList = await getMovieListUsecase.call(NoParams());
    emit(failureOrMovieList.fold(
        (failure) =&amp;gt; const Error(message: "Server Failure"),
        (movieList) =&amp;gt; MovieLoaded(movieList: movieList)));
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Eg. Movie Bloc State &lt;em&gt;lib/features/movie/presentation/bloc/movie_state.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;part of 'movie_bloc.dart';

abstract class MovieState extends Equatable {
  const MovieState();

  @override
  List&amp;lt;Object&amp;gt; get props =&amp;gt; [];
}

class MovieInitial extends MovieState {}

class MovieLoading extends MovieState {}

class MovieLoaded extends MovieState {
  final List&amp;lt;MovieEntity&amp;gt; movieList;
  const MovieLoaded({
    required this.movieList,
  });
  @override
  List&amp;lt;Object&amp;gt; get props =&amp;gt; [movieList];
}

class Error extends MovieState {
  final String message;
  const Error({
    required this.message,
  });
  @override
  List&amp;lt;Object&amp;gt; get props =&amp;gt; [message];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Eg. Movie Bloc Event &lt;em&gt;lib/features/movie/presentation/bloc/movie_event.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;part of 'movie_bloc.dart';

abstract class MovieEvent extends Equatable {
  const MovieEvent();

  @override
  List&amp;lt;Object&amp;gt; get props =&amp;gt; [];
}

class GetMovies extends MovieEvent {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After creating the bloc we will test it.&lt;/p&gt;

&lt;p&gt;Eg. Movie Bloc test: &lt;em&gt;test/features/movie/presentation/bloc/movie_bloc_test.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:dartz/dartz.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:movie_show/core/error/failure.dart';
import 'package:movie_show/core/usecases/usecase.dart';
import 'package:movie_show/features/movie/domain/entities/movie_entity.dart';
import 'package:movie_show/features/movie/domain/usecases/get_movie_list_usecase.dart';
import 'package:movie_show/features/movie/presentation/bloc/movie_bloc.dart';

class MockGetMovieListUsecase extends Mock implements GetMovieListUsecase {}

void main() {
  late MovieBloc movieBloc;
  late MockGetMovieListUsecase mockGetMovieListUsecase;
  final tMovieList = [
    const MovieEntity(
      movieId: 'movieId',
      title: 'title',
      thumbnail: 'thumbnail',
      movieUrl: 'movieUrl',
      unlocked: true,
    ),
    const MovieEntity(
      movieId: 'moviesIds',
      title: 'titles',
      thumbnail: 'thumbnails',
      movieUrl: 'movieUrls',
      unlocked: false,
    )
  ];
  setUp(() {
    mockGetMovieListUsecase = MockGetMovieListUsecase();
    movieBloc = MovieBloc(getMovieListUsecase: mockGetMovieListUsecase);
  });
  group('Bloc Test', () {
    test('initial state should be MovieInitial()', () async {
      //Arrange
      //Act
      //Assert
      expect(movieBloc.state, equals(MovieInitial()));
    });
    test('should get data from usecase', () async {
      //Arrange
      when(
        () =&amp;gt; mockGetMovieListUsecase.call(NoParams()),
      ).thenAnswer((_) async =&amp;gt; Right(tMovieList));
      //Act
      movieBloc.add(GetMovies());
      await untilCalled(() =&amp;gt; mockGetMovieListUsecase.call(NoParams()));
      //Assert
      verify(() =&amp;gt; mockGetMovieListUsecase.call(NoParams()));
    });
    test('should emit MovieLoaded when data is obtained succesfully', () async {
      //Arrange
      when(
        () =&amp;gt; mockGetMovieListUsecase.call(NoParams()),
      ).thenAnswer((_) async =&amp;gt; Right(tMovieList));
//Assert Later
      final expected = [
        MovieLoading(),
        MovieLoaded(movieList: tMovieList),
      ];
      expectLater(movieBloc.stream, emitsInOrder(expected));
//Act
      movieBloc.add(GetMovies());
      // print(movieBloc.stream.runtimeType);
    });
    test('should emit Error when getting data fails', () async {
      //Arrange
      when(
        () =&amp;gt; mockGetMovieListUsecase.call(NoParams()),
      ).thenAnswer((_) async =&amp;gt; Left(ServerFailure()));
//Assert Later
      final expected = [
        MovieLoading(),
        const Error(message: 'Server Failure'),
      ];
      expectLater(movieBloc.stream, emitsInOrder(expected));
//Act
      movieBloc.add(GetMovies());
      // print(movieBloc.stream.runtimeType);
    });
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;First, we test the initial state of the bloc. During the GetMovies() event the bloc should emit two states MovieInitial() and MovieLoaded() or MovieLoading() or Error(). The state of the bloc is obtained as a stream. Here we are using the expectLater() as the bloc is executing later. So we should keep on listening for the stream of state. What about the page and widget? Shouldn’t we test it? Here we are doing the unit test, in order to test those we need to do a widget test. That’s a topic for another time. Now let’s create the UI i.e. pages and widgets. Wait a minute there arises a problem. The presentation layer only knows about the domain layer. It doesn’t know about the data layer. There seems to be no connection between those. In the presentation, we are only calling the use-case and the use-case only contains the abstract function. The UI has no way to access implementation. With all the work we have done and we can’t connect those dots.&lt;/p&gt;

&lt;p&gt;We can solve these issues by using dependency injection. It connects all the things we have been doing so far. So let’s connect the dots using &lt;a href="https://pub.dev/packages/get_it" rel="noopener noreferrer"&gt;get_it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s create a file &lt;em&gt;injection_container.dart&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Eg . &lt;em&gt;lib&lt;/em&gt;/&lt;em&gt;injection_container.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final sl = GetIt.instance;
Future&amp;lt;void&amp;gt; init() async {
//bloc
  // movie bloc
  sl.registerFactory&amp;lt;MovieBloc&amp;gt;(
    () =&amp;gt; MovieBloc(
      getMovieListUsecase: sl(),
    ),
  );
//usecase

//movie use case
  sl.registerLazySingleton&amp;lt;GetMovieListUsecase&amp;gt;(
      () =&amp;gt; GetMovieListUsecase(movieRepository: sl()));

//repository

// movie repository
  sl.registerLazySingleton&amp;lt;MovieRepository&amp;gt;(
    () =&amp;gt; MovieRepositoryImpl(
      networkInfo: sl(),
      movieListRemoteDataSource: sl(),
      awsDataSource: sl(),
    ),
  );

//data sources

sl.registerLazySingleton&amp;lt;MovieListRemoteDataSource&amp;gt;(
    () =&amp;gt; MovieListRemoteDataSourceImpl(provideFakeData: sl()),
  )

//core

//network info --&amp;gt; internet connected or not
  sl.registerLazySingleton&amp;lt;NetworkInfo&amp;gt;(
    () =&amp;gt; NetworkInfoImpl(sl()),
  );
//fake Data
  sl.registerLazySingleton&amp;lt;ProvideFakeData&amp;gt;(() =&amp;gt; ProvideFakeData());

//external
  final sharedPreferences = await SharedPreferences.getInstance();
  sl.registerLazySingleton&amp;lt;SharedPreferences&amp;gt;(
    () =&amp;gt; sharedPreferences,
  );

sl.registerLazySingleton&amp;lt;Dio&amp;gt;(
    () =&amp;gt; Dio(),
  );

sl.registerLazySingleton&amp;lt;Connectivity&amp;gt;(
    () =&amp;gt; Connectivity(),
  );

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

&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;get_it&lt;/strong&gt; package supports creating &lt;strong&gt;singletons&lt;/strong&gt; and instance &lt;strong&gt;factories&lt;/strong&gt;. Here, we’re going to register everything as required. We will register most of them as a singleton so that our app gets only one instance of the class per lifecycle except bloc which might need multiple instances.&lt;/p&gt;

&lt;p&gt;To register, instantiate the class as usual and pass in sl() into every constructor parameter and define the constructor parameter in the same way and repeat until no constructor parameter is left.&lt;/p&gt;

&lt;p&gt;Here we provide the implementation of the abstract classes should they appear in our code. Dependency injection was the missing link between the production and test codes, where we sort of injected the dependencies manually with mocked classes. Now that we’ve implemented the &lt;strong&gt;service locator&lt;/strong&gt;, nothing can stop us from &lt;strong&gt;writing Flutter widgets&lt;/strong&gt; which will utilize every bit of code we’ve written until now by showing a fully functional UI to the user.&lt;/p&gt;

&lt;p&gt;Now you can initialize it in the &lt;em&gt;main.dart&lt;/em&gt; file and start building your UI&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure to use the service locator that we created when accessing the bloc. To access movie bloc instance, you can use sl.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'injection_container.dart' as di;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await di.init();
  runApp(
    const MyApp(),
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;I won’t be doing the UI part. For reference go &lt;a href="https://resocoder.com/2019/10/29/flutter-tdd-clean-architecture-course-14-user-interface/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://bloclibrary.dev/#/" rel="noopener noreferrer"&gt;here&lt;/a&gt;(bloc)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Happy Coding!!&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>Learning TDD with Clean Architecture for Flutter (Data Layer) Part III</title>
      <dc:creator>Safal Shrestha</dc:creator>
      <pubDate>Thu, 22 Sep 2022 04:57:09 +0000</pubDate>
      <link>https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-data-layer-part-iii-1fff</link>
      <guid>https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-data-layer-part-iii-1fff</guid>
      <description>&lt;p&gt;Part I &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-part-i-46nk"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part II &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-domain-layer-part-ii-1pi5"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part &lt;strong&gt;IV &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-part-iv-16b4"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this part, let’s finish the data layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Layer
&lt;/h2&gt;

&lt;p&gt;It is the layer in which the app interacts with the outside world. It provides data to the app from the outside. It consists of low-level Data sources, Repositories which are the single source of truth for the data, and finally Models.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RkqGx6eI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AYvVW937gxOeSNzzawbTeeA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RkqGx6eI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AYvVW937gxOeSNzzawbTeeA.png" alt="data layer" width="148" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Models
&lt;/h3&gt;

&lt;p&gt;Models are the entity with some additional functionalities. The data from the outside mightn’t be in the format we desired. So, models interact with this harsh environment and convert the outside data to the entity. As the relationship between model and entity is very important, we should test if the models return the entity.&lt;/p&gt;

&lt;p&gt;Eg. Movie Model Test &lt;em&gt;test/features/movie/data/models/movie_model_test.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'dart:convert';
import 'package:flutter_test/flutter_test.dart';
import 'package:movie_show/features/movie/data/models/movie_model.dart';
import 'package:movie_show/features/movie/domain/entities/movie_entity.dart';

import '../../../../fixtures/fixture_reader.dart';

void main() {
  const tMovieModel = MovieModel(
    movieId:
        '''Big Buck Bunny tells the story of a giant rabbit with a heart bigger than himself. When one sunny day three rodents rudely harass him, something snaps... and the rabbit ain't no bunny anymore! In the typical cartoon tradition he prepares the nasty rodents a comical revenge.\n\nLicensed under the Creative Commons Attribution license\nhttp://[www.bigbuckbunny.org'''](http://www.bigbuckbunny.org'''),
    title: 'Big Buck Bunny',
    thumbnail: 'images/BigBuckBunny.jpg',
    movieUrl:
        "[http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4](http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4)",
    unlocked: true,
  );
  setUp(() {});
  test('MovieModel should be subclass of MovieEntity', () async {
//arrange
//act
//assert
    expect(tMovieModel, isA&amp;lt;MovieEntity&amp;gt;());
  });
  group('fromJson', () {
    test('should return a valid MovieModel', () async {
//Arrange
      final Map&amp;lt;String, dynamic&amp;gt; jsonMap =
          json.decode(await fixture('video.json'));
//Act
      final result = MovieModel.fromJson(jsonMap);
//Assert
      expect(result, tMovieModel);
    });
  });
  group('toJson', () {
    test('should return a JSON map from MovieModel', () async {
//Arrange
//Act
      final result = tMovieModel.toJson();
//Assert
      final expectedMap = {
        "movieId":
            "Big Buck Bunny tells the story of a giant rabbit with a heart bigger than himself. When one sunny day three rodents rudely harass him, something snaps... and the rabbit ain't no bunny anymore! In the typical cartoon tradition he prepares the nasty rodents a comical revenge.\n\nLicensed under the Creative Commons Attribution license\nhttp://[www.bigbuckbunny.org](http://www.bigbuckbunny.org)",
        "movieUrl":
            "[http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4](http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4)",
        "thumbnail": "images/BigBuckBunny.jpg",
        "title": "Big Buck Bunny",
        "unlocked": true
      };
      expect(result, expectedMap);
    });
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Json file has been used from &lt;a href="https://gist.github.com/jsturgis/3b19447b304616f18657"&gt;here&lt;/a&gt;. You might be thinking why is &lt;strong&gt;movieID&lt;/strong&gt; so long. It doesn’t matter here as we are just trying to learn here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here, we are writing multiple tests. A test can also be grouped together using a group.&lt;/p&gt;

&lt;p&gt;At first, we make sure that the movie model extends from the movie entity and it returns the entity. Here we can see isA() keyword. It is used to check the type of object.&lt;/p&gt;

&lt;p&gt;As our model interacts with the outside world and most of the data we get from the outside is in form of JSON, our model will have a function to convert this data to an entity. So, let’s write a test for &lt;strong&gt;fromjson&lt;/strong&gt; and &lt;strong&gt;tojson&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As we are in the testing phase, let’s mimic those JSON responses.&lt;/p&gt;

&lt;p&gt;Eg. Json responses &lt;em&gt;test/fixtures/fixture_reader.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'dart:io';  
Future&amp;lt;String&amp;gt; fixture(String name) {   
   return Future.value(File('test/fixtures/$name').readAsStringSync()); 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Fixture reads from the JSON that we have created and returns them. Let’s look at our JSON file.&lt;/p&gt;

&lt;p&gt;Eg. JSON file. &lt;em&gt;test/fixtures/video.json&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "description": "Big Buck Bunny tells the story of a giant rabbit with a heart bigger than himself. When one sunny day three rodents rudely harass him, something snaps... and the rabbit ain't no bunny anymore! In the typical cartoon tradition he prepares the nasty rodents a comical revenge.\n\nLicensed under the Creative Commons Attribution license\nhttp://[www.bigbuckbunny.org](http://www.bigbuckbunny.org)",
    "sources": [
        "[http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4](http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4)"
    ],
    "subtitle": "By Blender Foundation",
    "thumb": "images/BigBuckBunny.jpg",
    "title": "Big Buck Bunny",
    "unlocked": true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;In test/fixtures/video_list.json Copy json file from &lt;a href="https://gist.github.com/jsturgis/3b19447b304616f18657"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wait a minute something seems wrong. It is not in the format where we defined the entity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should we go back and change the entity?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No, an entity is a rule that we cannot change (actually we can but we shouldn’t). The model is in charge of handling it, so the entity can get what it wants. If we run this test, the test fails (obviously as the model hasn’t been created yet), so let us write the model to make it pass.&lt;/p&gt;

&lt;p&gt;Eg. Entity of Movie &lt;em&gt;lib/features/movie/data/models/movie_model.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import '../../domain/entities/movie_entity.dart';

class MovieModel extends MovieEntity {
  const MovieModel(
      {required String movieId,
      required String title,
      required String thumbnail,
      required String movieUrl,
      required bool unlocked})
      : super(
            movieId: movieId,
            title: title,
            thumbnail: thumbnail,
            movieUrl: movieUrl,
            unlocked: unlocked);
  Map&amp;lt;String, dynamic&amp;gt; toJson() {
    return &amp;lt;String, dynamic&amp;gt;{
      'movieId': movieId,
      'title': title,
      'thumbnail': thumbnail,
      'movieUrl': movieUrl,
      'unlocked': unlocked,
    };
  }

factory MovieModel.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) {
    return MovieModel(
      movieId: json['description'] as String,
      title: json['title'] as String,
      thumbnail: json['thumb'] as String,
      movieUrl: json['sources'][0] as String,
      unlocked: json['unlocked'] as bool,
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the model, you might see the &lt;strong&gt;super&lt;/strong&gt; being used. This super is responsible to change the model into an entity (super passes the parameter to its parent constructor).&lt;/p&gt;

&lt;h3&gt;
  
  
  DataSources
&lt;/h3&gt;

&lt;p&gt;Just like the name, they provide the data. They are the sources of data. There can be multiple data sources. For now, let’s go with a remote data source and create an interface for it.&lt;/p&gt;

&lt;p&gt;Eg. movie data source. &lt;em&gt;lib/features/movie/data/datasources/video_list_remote_datasource.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abstract class MovieListRemoteDataSource {
  /// Throws a [ServerException] for all error codes.
  Future&amp;lt;List&amp;lt;MovieModel&amp;gt;&amp;gt; getMovieList();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, let’s write a test.&lt;/p&gt;

&lt;p&gt;Eg. Video List Remote DataSource Test. &lt;em&gt;test/features/movie/data/datasources/video_list_datasource_test.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:movie_show/core/error/exceptions.dart';
import 'package:movie_show/features/movie/data/datasources/video_list_remote_datasource.dart';
import 'package:movie_show/features/movie/data/models/movie_model.dart';
import 'package:movie_show/fixtures/fixture_reader.dart';

import '../../../../fixtures/fixture_reader.dart';

class MockMovie extends Mock implements MovieListRemoteDataSourceImpl {}

class MockProvideFakeData extends Mock implements ProvideFakeData {}

void main() {
  late MovieListRemoteDataSourceImpl movieListRemoteDataSourceImpl;
  late MockProvideFakeData mockProvideFakeData;
  setUp(() {
    mockProvideFakeData = MockProvideFakeData();
    movieListRemoteDataSourceImpl =
        MovieListRemoteDataSourceImpl(provideFakeData: mockProvideFakeData);
  });
  group('remote Data Source', () {
    test('should return list of movie model', () async {
      //Arrange
      when(() =&amp;gt; mockProvideFakeData.fixture('video_list.json'))
          .thenAnswer((_) async =&amp;gt; await fixture('video_list.json'));
      //Act
      final result = await movieListRemoteDataSourceImpl.getMovieList();
      //Assert
      verify(() =&amp;gt; mockProvideFakeData.fixture('video_list.json'));
      expect(result, isA&amp;lt;List&amp;lt;MovieModel&amp;gt;&amp;gt;());
    });
    test('should return serverexception if caught', () async {
      //Arrange
      when(() =&amp;gt; mockProvideFakeData.fixture('video_list.json'))
          .thenThrow(ServerException());
      //Act
      final result = movieListRemoteDataSourceImpl.getMovieList;
//Assert
      expect(() async =&amp;gt; await result.call(),
          throwsA(const TypeMatcher&amp;lt;ServerException&amp;gt;()));
    });
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Where did the provide fake data come from? Remember data sources interact with the outside world, we are simulating the outside world with that class. When the function is supposed to throw an error, we should use &lt;strong&gt;thenthrow()&lt;/strong&gt; and call a function &lt;strong&gt;throwsA()&lt;/strong&gt; from the &lt;strong&gt;expect()&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;Eg. ProvideFake Data. &lt;em&gt;lib/fixtures/fixture_reader.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter/services.dart';
class ProvideFakeData {
  Future&amp;lt;String&amp;gt; fixture(String name) async {
// for a file
    return await rootBundle.loadString("assets/$name");
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now let’s write the implementation of the data source so that the test can pass.&lt;/p&gt;

&lt;p&gt;Eg. movie data source. &lt;em&gt;lib/features/movie/data/datasources/video_list_remote_datasource.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:convert';

import '../../../../core/error/exceptions.dart';
import '../../../../fixtures/fixture_reader.dart';
import '../models/movie_model.dart';

abstract class MovieListRemoteDataSource {
  /// Throws a [ServerException] for all error codes.
  Future&amp;lt;List&amp;lt;MovieModel&amp;gt;&amp;gt; getMovieList();
}

class MovieListRemoteDataSourceImpl implements MovieListRemoteDataSource {
  final ProvideFakeData provideFakeData;
  MovieListRemoteDataSourceImpl({required this.provideFakeData});
  [@override](http://twitter.com/override)
  Future&amp;lt;List&amp;lt;MovieModel&amp;gt;&amp;gt; getMovieList() async {
    List&amp;lt;MovieModel&amp;gt; movieList = [];
    try {
      final jsonMap =
          json.decode(await provideFakeData.fixture('video_list.json'));
      final result = jsonMap['categories'][0]['videos'];
      for (var item in result) {
        movieList.add(MovieModel.fromJson(item));
      }
      return movieList;
    } catch (e) {
      throw ServerException();
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After this, the test will pass.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repositories
&lt;/h3&gt;

&lt;p&gt;It is the brain of the model deciding what to do with the data obtained from the data sources. It is the implementation of the repository defined in the domain layer.&lt;/p&gt;

&lt;p&gt;Before writing the test we create an abstraction for the dependencies that depend on the NetworkInfo.&lt;/p&gt;

&lt;p&gt;Eg . Network Info. &lt;em&gt;lib/core/network/network_info.dart&lt;/em&gt;&lt;/p&gt;

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

abstract class NetworkInfo {
  Future&amp;lt;bool&amp;gt; get isConnected;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We don’t need to create the implementation of NetworkInfo as we are going to mock it (You can write implementation if you want but it won’t be used in the test). Now let’s write a test.&lt;/p&gt;

&lt;p&gt;Eg . Repository Implementation test. &lt;em&gt;test/features/movie/data/repositories/movie_repository_impl_test.dart&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:dartz/dartz.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:movie_show/core/error/exceptions.dart';
import 'package:movie_show/core/error/failure.dart';
import 'package:movie_show/core/network/network_info.dart';
import 'package:movie_show/features/movie/data/datasources/video_list_remote_datasource.dart';
import 'package:movie_show/features/movie/data/models/movie_model.dart';
import 'package:movie_show/features/movie/data/repositories/movie_repository_impl.dart';
import 'package:movie_show/features/movie/domain/entities/movie_entity.dart';

class MockRemoteDataSource extends Mock implements MovieListRemoteDataSource {}

class MockNetworkInfo extends Mock implements NetworkInfo {}

void main() {
  late MovieRepositoryImpl movieRepositoryImpl;
  late MockRemoteDataSource mockRemoteDataSource;
  late MockNetworkInfo mockNetworkInfo;
  final tMovieModelList = [
    const MovieModel(
      movieId: 'movieId',
      title: 'title',
      thumbnail: 'thumbnail',
      movieUrl: 'movieUrl',
      unlocked: true,
    ),
    const MovieModel(
      movieId: 'moviesIds',
      title: 'titles',
      thumbnail: 'thumbnails',
      movieUrl: 'movieUrls',
      unlocked: false,
    )
  ];
  final List&amp;lt;MovieEntity&amp;gt; tMovieEntityList = tMovieModelList;
  setUp(() {
    mockRemoteDataSource = MockRemoteDataSource();
    mockNetworkInfo = MockNetworkInfo();
    movieRepositoryImpl = MovieRepositoryImpl(
      networkInfo: mockNetworkInfo,
      movieListRemoteDataSource: mockRemoteDataSource,
    );
  });
  group('getMovieList:', () {
    test('should check if device is online', () async {
      //Arrange
      when(
        () =&amp;gt; mockNetworkInfo.isConnected,
      ).thenAnswer((_) async =&amp;gt; true);
      await mockNetworkInfo.isConnected;
//Assert
      verify(() =&amp;gt; mockNetworkInfo.isConnected);
    });
    group('when device is online', () {
      setUp(() {
        when(
          () =&amp;gt; mockNetworkInfo.isConnected,
        ).thenAnswer((_) async =&amp;gt; true);
      });
      test('should return remote data when call is succesfull', () async {
        //Arrange
        when(
          () =&amp;gt; mockRemoteDataSource.getMovieList(),
        ).thenAnswer((_) async =&amp;gt; tMovieModelList);
        //Act
        final result = await movieRepositoryImpl.getMovieList();
//Assert
        verify(
          () =&amp;gt; mockRemoteDataSource.getMovieList(),
        );
        expect(result, equals(Right(tMovieEntityList)));
      });
      test('should return failure when call is unsuccesfull', () async {
        //Arrange
        when(
          () =&amp;gt; mockRemoteDataSource.getMovieList(),
        ).thenThrow(ServerException());
        //Act
        final result = await movieRepositoryImpl.getMovieList();
//Assert
        verify(
          () =&amp;gt; mockRemoteDataSource.getMovieList(),
        );
        expect(result, equals(Left(ServerFailure())));
      });
    });
    group('device is offline', () {
      setUp(() {
        when(
          () =&amp;gt; mockNetworkInfo.isConnected,
        ).thenAnswer((_) async =&amp;gt; false);
      });
      test('should return failure', () async {
        //Arrange
        /// No arrange as datasource is not called if no network is found
        //Act
        final result = await movieRepositoryImpl.getMovieList();
//Assert
        verifyNever(
          () =&amp;gt; mockRemoteDataSource.getMovieList(),
        );
        expect(result, equals(Left(ServerFailure())));
      });
    });
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;While checking for exceptions, we should not call the function as it results in exceptions. It should be called within the expect() function. While writing tests we should try to consider every possible scenario. The &lt;em&gt;verifyNever&lt;/em&gt; verifies that mockRemoteDataSource.getMovieList() isn’t called.&lt;/p&gt;

&lt;p&gt;Now let’s write the implementation of the repository&lt;/p&gt;

&lt;p&gt;Eg. Movie Repository Implementation. &lt;em&gt;lib/features/movie/data/repositories/movie_repository_impl.dart&lt;/em&gt;&lt;/p&gt;

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

import '../../../../core/error/exceptions.dart';
import '../../../../core/error/failure.dart';
import '../../../../core/network/network_info.dart';
import '../../domain/entities/movie_entity.dart';
import '../../domain/repositories/movie_repository.dart';
import '../datasources/video_list_remote_datasource.dart';

class MovieRepositoryImpl implements MovieRepository {
  final NetworkInfo networkInfo;
  final MovieListRemoteDataSource movieListRemoteDataSource;
  MovieRepositoryImpl({
    required this.networkInfo,
    required this.movieListRemoteDataSource,
  });
  [@override](http://twitter.com/override)
  Future&amp;lt;Either&amp;lt;Failure, List&amp;lt;MovieEntity&amp;gt;&amp;gt;&amp;gt; getMovieList() async {
    if (await networkInfo.isConnected) {
      try {
        final movieList = await movieListRemoteDataSource.getMovieList();
        return Right(movieList);
      } on ServerException {
        return Left(ServerFailure());
      }
    } else {
      return Left(ServerFailure());
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After this, the test should pass and the data layer has been completed.&lt;/p&gt;

&lt;p&gt;Finally, we have the following file and folder&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L9Ww0R_7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AJ7HWfL0Vhnyd8UHpK3WKLw.png" alt="Data Layer in lib" width="280" height="158"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;DataLayer in lib&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U6AUO3vX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2Abh5P57tMSNVXk69OSF0aAA.png" alt="Data Layer in test" width="259" height="156"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;DataLayer in test&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sptgLbxv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AGzJ7V9sdgMNKApdguG-8WA.png" alt="Fixture in test" width="279" height="130"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Fixture in test&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bQPZ9q5L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/560/1%2AfuGfw-dNIdnD4ymQVEavdQ.png" alt="Lib structure" width="280" height="376"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Lib structure&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In the next part, we will finish the presentation layer and dependency injection. See you there :)&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>cleanarchitecture</category>
      <category>dart</category>
      <category>tdd</category>
    </item>
    <item>
      <title>Learning TDD with Clean Architecture for Flutter (Domain Layer) Part II</title>
      <dc:creator>Safal Shrestha</dc:creator>
      <pubDate>Thu, 11 Aug 2022 16:49:00 +0000</pubDate>
      <link>https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-domain-layer-part-ii-1pi5</link>
      <guid>https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-domain-layer-part-ii-1pi5</guid>
      <description>&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%2Fjryd85jvf62219jolngj.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%2Fjryd85jvf62219jolngj.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part &lt;strong&gt;I &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-part-i-46nk"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Part &lt;strong&gt;III &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-data-layer-part-iii-1fff"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Part &lt;strong&gt;IV &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-part-iv-16b4"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Welcome back to the Part II of this series. Let’s continue from where we left. Here we will begin to code and finish TDD for the domain layer.&lt;/p&gt;
&lt;h2&gt;
  
  
  TDD Clean Architecture
&lt;/h2&gt;

&lt;p&gt;Now we know a little bit about TDD and Clean Architecture, let us combine those two to get the best of both worlds. Before jumping onwards here are a few things :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; We will be writing a unit test.&lt;/li&gt;
&lt;li&gt; We will be using Mocktail to mock the dependencies.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; class MockAwsDataSource extends Mock implements AwsDataSource {} 
    // To mock class AwsDataSourece using mocktail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt; While testing any class, mock all the classes/dependencies inside it except the class we are testing and control all the functions inside those classes.&lt;/li&gt;
&lt;li&gt; You should have a similar folder structure inside the &lt;em&gt;test&lt;/em&gt; folder i.e. mimic the &lt;em&gt;lib&lt;/em&gt; folder structure inside the &lt;em&gt;test&lt;/em&gt; folder.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;You should have basic knowledge on dart and abstraction&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Domain Layer
&lt;/h2&gt;

&lt;p&gt;It is one of the most important layers. It should remain unchanged even if all other layer changes. We should always start with the domain layer.&lt;/p&gt;

&lt;p&gt;The domain layer consists of entities, repositories, and use cases.&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ALxYD7KSKLkGj3C2hD2DzIg.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ALxYD7KSKLkGj3C2hD2DzIg.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Entities
&lt;/h3&gt;

&lt;p&gt;It is a lightweight domain object and the basic data structure that we will absolutely need.&lt;/p&gt;

&lt;p&gt;Eg. Entity of Movie &lt;em&gt;lib/features/movie/domain/entities/movie_entity.dart&lt;/em&gt;&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:equatable/equatable.dart';

    class MovieEntity extends Equatable {
      final String movieId;
      final String title;
      final String thumbnail;
      final String movieUrl;
      final bool unlocked;
      const MovieEntity({
        required this.movieId,
        required this.title,
        required this.thumbnail,
        required this.movieUrl,
        required this.unlocked,
      });

    @override
      List&amp;lt;Object&amp;gt; get props {
        return [
          movieId,
          title,
          thumbnail,
          movieUrl,
          unlocked,
        ];
      }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://pub.dev/packages/equatable" rel="noopener noreferrer"&gt;Equatable &lt;/a&gt;overrides == and hashCode for you so you don't have to waste your time writing lots of boilerplate code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Repositories
&lt;/h3&gt;

&lt;p&gt;It is in both the domain and data layer. Its definition is in the domain layer and implementation is in the data layer allowing total independence of the domain layer.&lt;/p&gt;

&lt;p&gt;Eg. Repository of Movie &lt;em&gt;lib/features/movie/domain/repositories/movie_repository.dart&lt;/em&gt;&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:dartz/dartz.dart';
    import '../../../../core/error/failure.dart';
    import '../entities/movie_entity.dart';
    abstract class MovieRepository {
      Future&amp;lt;Either&amp;lt;Failure, List&amp;lt;MovieEntity&amp;gt;&amp;gt;&amp;gt; getMovieList();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will have a method to get a list of movies, i.e. list of movie entities. &lt;em&gt;Future&amp;gt;&amp;gt;&lt;/em&gt; will ensure error handling . Let us move on. Wait a minute what is &lt;em&gt;either&lt;/em&gt; keyword? It allows a function to return between failure and List of movie entities, not both. It has been obtained from package &lt;em&gt;Dartz&lt;/em&gt; which gives functional programming capabilities to dart. &lt;em&gt;Failure&lt;/em&gt; class was defined in the &lt;em&gt;core/error&lt;/em&gt; file to define the failure of the code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In core the features, abstraction or module that is used in other features are defined&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eg. Failure is defined in &lt;em&gt;lib/core/error/failure.dart&lt;/em&gt;&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:equatable/equatable.dart';
    abstract class Failure extends Equatable {
     @override
      List&amp;lt;Object?&amp;gt; get props =&amp;gt; [];
    }
    //General Failures
    class ServerFailure extends Failure {}
    class CacheFailure extends Failure {}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Usecases
&lt;/h3&gt;

&lt;p&gt;Use Cases are where the business logic gets executed. It calls a repository to get data.&lt;/p&gt;

&lt;p&gt;Eg. Usecase to get movie list &lt;em&gt;lib/features/movie/domain/usecases/get_movie_list_usecase.dart&lt;/em&gt;&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:dartz/dartz.dart';
    import '../../../../core/error/failure.dart';
    import '../../../../core/usecases/usecase.dart';
    import '../entities/movie_entity.dart';
    import '../repositories/movie_repository.dart';

    class GetMovieListUsecase implements UseCase&amp;lt;List&amp;lt;MovieEntity&amp;gt;, NoParams&amp;gt; {
      final MovieRepository movieRepository;
      GetMovieListUsecase({
        required this.movieRepository,
      });

    @override
      Future&amp;lt;Either&amp;lt;Failure, List&amp;lt;MovieEntity&amp;gt;&amp;gt;&amp;gt; call(NoParams params) async {
        return await movieRepository.getMovieList();
      }
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;GetVideoLiseUsecase&lt;/em&gt; implements use-case inside &lt;em&gt;lib/core/use-case&lt;/em&gt; . We are defining rules for use cases there.&lt;/p&gt;

&lt;p&gt;Eg. Base use-case is defined in &lt;em&gt;lib/core/usecases/usecase.dart&lt;/em&gt;&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:dartz/dartz.dart';
    import 'package:equatable/equatable.dart';
    import '../error/failure.dart';
    abstract class UseCase&amp;lt;Type, Params&amp;gt; {
      Future&amp;lt;Either&amp;lt;Failure, Type&amp;gt;&amp;gt; call(Params params);
    }

    class NoParams extends Equatable {
      @override
      List&amp;lt;Object?&amp;gt; get props =&amp;gt; [];
    }

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

&lt;/div&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A7g4dzGioUVJGb7Qv8-7SOg.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A7g4dzGioUVJGb7Qv8-7SOg.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wait a minute this was supposed to be TDD Clean Architecture. Shouldn’t we write a test first?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, before writing a use case, we should first write the test first. Just imagine the above code hasn’t been written yet for now and let’s write a test.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Test file should end with ‘_test.dart’ and you can run test by typing &lt;strong&gt;&lt;em&gt;flutter test&lt;/em&gt;&lt;/strong&gt; in terminal or you can run them manually clicking run. While naming the test give it the same name as the file you are trying to test and add ‘ _test ’ to it&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eg. Test for use-case &lt;em&gt;test/features/movie/domain/usecases/get_movie_list_usecase_test.dart&lt;/em&gt;&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:dartz/dartz.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:mocktail/mocktail.dart';

class MockMovieRepository extends Mock implements MovieRepository {}
  void main() {
      late GetMovieListUsecase getMovieListUsecase;
      late MockMovieRepository mockMovieRepository;
      final tMovieList = [
        const MovieEntity(
          movieId: 'movieId',title: 'title',thumbnail: 'thumbnail',
      movieUrl: 'movieUrl',unlocked: true,
        ),
        const MovieEntity(
          movieId: 'movieIds',title: 'titles',thumbnail: 'thumbnails',
      movieUrl: 'movieUrls',unlocked: false,
        )   
      ];
      setUp(() {
        mockMovieRepository = MockMovieRepository();
        getMovieListUsecase =
            GetMovieListUsecase(movieRepository: mockMovieRepository);
      });
      test(
        'should get list of movie',
        () async {
          // arrange
          when(() =&amp;gt; mockMovieRepository.getMovieList())
              .thenAnswer((_) async =&amp;gt; Right(tMovieList));

    // act
          final result = await getMovieListUsecase(NoParams());

    // assert
          verify(() =&amp;gt; mockMovieRepository.getMovieList());

    expect(result, Right(tMovieList));
          verifyNoMoreInteractions(mockMovieRepository);
        },
      );
    }

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

&lt;/div&gt;



&lt;p&gt;Now let’s explain the code&lt;/p&gt;

&lt;p&gt;We are testing &lt;em&gt;GetMovieListUsecase&lt;/em&gt; in &lt;em&gt;get_movie_list_usecase.dart&lt;/em&gt; which implements a base use case in &lt;em&gt;lib/core/usecases/usecase.dart&lt;/em&gt; . &lt;em&gt;GetMovieListUsecase&lt;/em&gt; use case calls a repository for data, so the repository must be mocked to test the use case. After mocking the repository, we write the test.&lt;/p&gt;

&lt;p&gt;Now just like in the original dart file, there is the main file that will be executed. The main function contains the test.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;First, we define all the dependencies we need.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Then we instantiate them in setUp. If we look at the &lt;strong&gt;test&lt;/strong&gt; there are three parts.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In &lt;strong&gt;arrange&lt;/strong&gt; we control the outcome of the functions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In &lt;strong&gt;act&lt;/strong&gt;, we run the functions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In &lt;strong&gt;assert&lt;/strong&gt;, we verify/check if the test is successful or not. &lt;strong&gt;verify&lt;/strong&gt; function is making sure that the function has been executed. expect to compare the result and &lt;strong&gt;verifyNoMoreInteractions&lt;/strong&gt; to ensure that the repository is no longer being used or interacted with.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If we look closely, we can see that the test looks like documentation explaining to us what the code is supposed to do.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;You might be wondering if usecase hasn’t been created yet how do we map or visualize the test. Here comes, abstraction to the rescue . Even though getMovieListUsecase hasn’t been created , the usecase has been defined using abstract class. We can use this abstract class to visualize what the usecase class will be like and use it to write the test(most of the time). So interface/abstract class are very important in TDD. After writing the test, we write the usecase until the test in successful and refactor it as needed.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Only use-case needs to be tested in the domain layer as the repository and entity have nothing to test as they are very simple.&lt;/p&gt;

&lt;p&gt;Finally, we have the following file and folder&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AOlkcfu9WbtcANI-SVN7-Gg.png" alt="Domain Layer in lib"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Domain Layer in lib&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AKdK_YDCnuGPEFsjRfIr9bw.png" alt="Domain Layer in test"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Domain Layer in test&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In my next post, we will implement TDD for the Data layer.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>tdd</category>
      <category>cleanarchitecture</category>
      <category>dart</category>
    </item>
    <item>
      <title>Learning TDD with Clean Architecture for Flutter Part I</title>
      <dc:creator>Safal Shrestha</dc:creator>
      <pubDate>Mon, 08 Aug 2022 10:49:00 +0000</pubDate>
      <link>https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-part-i-46nk</link>
      <guid>https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-part-i-46nk</guid>
      <description>&lt;p&gt;This will be four-part series in which we will learn about TDD in Flutter.&lt;br&gt;
Part &lt;strong&gt;II &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-domain-layer-part-ii-1pi5"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Part &lt;strong&gt;III &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-data-layer-part-iii-1fff"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Part &lt;strong&gt;IV &lt;a href="https://dev.to/codingmountain/learning-tdd-with-clean-architecture-for-flutter-part-iv-16b4"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TDD(Test Driven Development)
&lt;/h2&gt;

&lt;p&gt;TDD is an approach in which the test is written to validate the code that we write. Here the test is written and the code is modified to pass the test. It is also known as Test First Development.&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AqwfFPioDUsTxB6eG1w5BkQ.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AqwfFPioDUsTxB6eG1w5BkQ.png" alt="TDD"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  TDD cycle defines
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Write a test&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make it run&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the code to make it right i.e. Refactor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Repeat process&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  TDD Advantages
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fewer bugs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding new functionalities becomes easier&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Faster in the long run&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tidier Code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forces you to focus on one thing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clean Interfaces&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  TDD Disadvantages
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Slow Process&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Faulty test code/No Silver Bullet&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All members should do it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Increases Complexity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Design dependent&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Clean Architecture
&lt;/h2&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A25u1HBuqn542BskxxJRpXA.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A25u1HBuqn542BskxxJRpXA.png" alt="Clean Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clean Architecture is also known as Domain-Driven Design. The primary idea in Clean Architecture is to make the solution adaptive, and keep the core business or application logic use cases independent of frontend and external frameworks.&lt;/p&gt;

&lt;p&gt;It produces the system that is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Independent of Frameworks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Independent of UI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Independent of Database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Independent of any external agency&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In clean architecture, codes are divided into layers. Inner layers are independent of the outer layer and changes can be made to the outer layer without ever touching the inner layer. It follows the &lt;em&gt;**Dependency Rule&lt;/em&gt;&lt;em&gt;.&lt;/em&gt; &lt;em&gt;This rule says that source code dependencies can only point inwards&lt;/em&gt;. Nothing in an inner circle can know anything at all about something in an outer circle. Here it contains four layers:&lt;/p&gt;

&lt;h3&gt;
  
  
  Entities
&lt;/h3&gt;

&lt;p&gt;Entities encapsulate &lt;em&gt;Enterprise-wide&lt;/em&gt; business rules. An entity can be an object with methods, or it can be a set of data structures and functions. It doesn’t matter so long as the entities could be used by many different applications in the enterprise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;p&gt;The software in this layer contains &lt;em&gt;application-specific&lt;/em&gt; business rules. It encapsulates and implements all of the use cases of the system. These use cases orchestrate the flow of data to and from the entities and direct those entities to use their &lt;em&gt;enterprise-wide&lt;/em&gt; business rules to achieve the goals of the use case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interface Adapters
&lt;/h3&gt;

&lt;p&gt;The software in this layer is a set of adapters that convert data from the format most convenient for the use cases and entities to the format most convenient for some external agency such as the Database or the Web.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frameworks and Drivers
&lt;/h3&gt;

&lt;p&gt;The outermost layer is generally composed of frameworks and tools such as the Database, the Web Framework, etc. Generally, you don’t write much code in this layer other than glue code that communicates to the next circle inwards.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There can be more than four layers. This diagram is only symbolic. There can be more layer as long as it follows &lt;em&gt;dependency rule&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Clean Architecture and Flutter
&lt;/h2&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A1m2Zf6LtFZM_vVjRMpXfZw.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A1m2Zf6LtFZM_vVjRMpXfZw.jpeg" alt="Clean Architecture in Flutter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make things clear and Flutter-specific, we are using &lt;a href="https://resocoder.com/2019/08/27/flutter-tdd-clean-architecture-course-1-explanation-project-structure/" rel="noopener noreferrer"&gt;Reso Coder’s Flutter Clean Architecture Proposal&lt;/a&gt;. It consists of three layers :&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain Layer
&lt;/h3&gt;

&lt;p&gt;It is the inner layer that shouldn’t be susceptible to the whims of changing data sources or porting our app to Angular Dart. It will contain only the core &lt;strong&gt;business logic&lt;/strong&gt; (&lt;strong&gt;&lt;em&gt;use cases&lt;/em&gt;&lt;/strong&gt;) and &lt;strong&gt;business objects&lt;/strong&gt; (&lt;strong&gt;&lt;em&gt;entities&lt;/em&gt;&lt;/strong&gt;). It should be totally &lt;em&gt;independent&lt;/em&gt; of every other layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Layer
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;data layer&lt;/strong&gt; consists of a &lt;strong&gt;Repository implementation&lt;/strong&gt; (the contract comes from the &lt;strong&gt;domain layer&lt;/strong&gt;) and &lt;strong&gt;data sources&lt;/strong&gt; — one is usually for getting remote (API) data and the other for caching that data. &lt;strong&gt;A repository&lt;/strong&gt; is where you decide if you return fresh or cached data when to cache it and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Presentation Layer
&lt;/h3&gt;

&lt;p&gt;This layer contains UI and state management approaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Folder Structure
&lt;/h3&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ar9tu36PyWrak4msITx_mfA.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ar9tu36PyWrak4msITx_mfA.png" alt="Folder Structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this post, you learn a little bit about test-driven development and clean architecture. For more, head on to part II.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>tdd</category>
      <category>cleanarchitecture</category>
      <category>dart</category>
    </item>
  </channel>
</rss>
