Saturday, December 11, 2021

Flutter: Top 10 Amazing Flutter chart libraries

Flutter, an open-source development kit created by Google has grown over the years.

Features Like Hot Reload, a vast widget catalog, very good performance, and a solid community contribute to meeting that objective and makes Flutter a pretty good framework.

Because sometimes in life charts and graphs are inevitable for us to display.

In order to make sense of numerics and data overall, in the same spirit, we need beautiful, responsive, customizable and easy to implement charts.

Flutter OpenSource chart libraries have the answers we need.

Here is a collection of 10 best chart libraries for Flutter to implement in your next Flutter project.

1. Fl_animated_linechart
Animated line chart library for a flutter, with tons of customization options, currently supports line and area

















Features
  • Support for DateTime axis
  • Multiple y-axes, supporting different units
  • Highlight selection
  • Animation of the chart
  • Tested with more than 3000 points and still performing

2. Bezier Chart
A beautiful bezier line chart widget for flutter that is highly interactive and configurable.














Features
  • Multi bezier lines
  • Allow numbers and datetimes
  • Gestures support like touch, pinch/zoom, scrolling
  • Highly customizable

3. Flutter_candlesticks
An Elegant OHLC Candlestick and Trade Volume charts library for the Flutter.

























Features
  • Easily create price watch apps using Flutter.
  • Suited for CryptoCurrency and share market apps
  • Fully customizable

4. Flutter Circular Chart
A library for creating animated circular chart widgets with Flutter, you can Create easily animated pie charts and radial charts by providing them with data objects they can plot into charts and animate between























Features
  • Beautifully animated circular charts
  • Fully customizable
  • Supports radial charts with multiple concentric circles

5. Flutter_charts
Flutter Charts is a charting library for Flutter, written in Flutter. Currently, the column chart and line chart are supported.

























Features
  • Automatically checks for the X label overlap.
  • Plenty of examples available for easy start
  • The highly customizable flutter chart library

6. Flutter Plot
A pretty plotting package for Flutter apps. Sizing and auto adding aren’t great right now, but tinkering with padding and font size will allow for you to align things well.

Features
  • Fully customizable
  • examples available for an easy start
  • you can create super neat plots

7. Charts by Google
Charts is a general charting library Created by Google for the Flutter mobile UI framework.



Features
  • Wide Range of Charts Available
  • Includes charts like Line chart, combo chart, Axes chart e.t.c
  • A charting package for Flutter, supporting both Android and iOS.

8. Fcharts
With Fcharts you can Create beautiful, responsive, animated charts using a simple and intuitive API.





















Features
  • A work-in-progress chart library for Flutter.
  • Responsive charts
  • simple and intuitive API

9. FL Chart
FlChart allows you to draw your charts in the Flutter, It’s a powerful Flutter chart library, currently supporting Line Chart, Bar Chart, and Pie Chart

Features
  • Handles Touches
  • Handles Animations
  • You can create awesome BarCharts
  • Also supports LineChart and PieChart

10. MPFlutterChart
A powerful Flutter chart view/graph view library, supporting line- bar- pie- radar- bubble- and candlestick charts as well as scaling, dragging and animations.



































Features
  • Tons of charts available
  • supports dragging and animations
  • Highly customizable

Conclusion
That’s my collection of the best chart libraries for Flutter, if you have a great component and didn’t see it in here, leave a suggestion in the comments below. Have a wonderful charting and visualization experience!
#flutter #programming

Reference

Saturday, December 4, 2021

iOS: QoS - Quality of service

The Quality of Service (QoS) class classifies what you want dispatchQueue to do. Indicates the importance of your app by specifying the quality of the task. When scheduling tasks, the system prioritizes tasks with higher service classes. Higher priority tasks are faster than lower priority tasks and are performed using more resources, which typically requires more energy than lower priority tasks. You can ensure your app's responsiveness and energy efficiency by specifying exactly the right QoS class for what your app does.

priority

userInteractive > userInitiated > default > utility > background


userInteractive

actions that interact with the user, such as working on the main thread, refreshing the user interface, or performing animations. focus on responsiveness and performance.

The task is almost instantaneous.


userInitiated

this class assigns it to tasks that provide immediate results for what the user is doing or prevent the user from using the app. for example, you can load the contents of the email that you want to display to the mercenary. you need immediate results, such as opening documents saved as user-initiated tasks,or performing tasks when a user clicks something in the user interface. work is required to continue user interaction. focus on responsiveness and performance.

Tasks like seconds or less are almost instantaneous.


default

The default quality of service class. Assign this class to a task or queue that your app starts or uses to perform active tasks on behalf of the user. This QoS is not used by developers to classify tasks. QoS is used as the default for unspecified operations and runs at the GCD global queue level.


utility

a quality of service class for tasks that are not actively tracked by the user. tasks that take time to complete and do not require immediate results, such as downloading or importing data. utility operations typically have progress bars that are visible to the user. it focuses on providing a balance between responsiveness, performance and energy efficiency.

The operation takes a few seconds to a few minutes.


background

tasks that work in the background and are not visible to the user, such as indexing, synchronization, and backup. focus on energy efficiency.

Tasks that take a considerable amount of time and require minutes or hours


unspecified

There are no quality of service classes. This indicates that there is no QoS information and signals that QoS should be inferred into the system. If a thread uses a legacy API, the thread can have unspecified QoS.

Reference:

iOS: GCD - Grand Central Dispatch



GCD is an API that performs parallelism programming or multithreading operations. In other words, the GCD API handles which tasks to do, one sequentially, multiple simultaneously, sync or Async. You can choose the right queue and QoS for your situation to improve execution efficiency.

Dispatch Queue


GCD provides Thread Safe one Dispatch Queue to perform Multi-threading operations. All Dispatch Queues are FIFO data structures. Therefore, the task always starts in the order in which it was added.

Serial(main)


Serial queues are serial queues that process them one by one in the order in which they were added to the queue. One Task must be completed to process the next Task.



Because all events related to the UI are attached to Main Thread, all UI operations must be performed on the Main Queue.

Concurrent(global)


Component queues are parallel queues that execute multiple operations at the same time. Task runs in the order in which they were added to the queue. The number of tabs that can be run at once is variable and depends on system conditions. Global Queue provides quality of service (QOS)for prioritizing tasks.


When sending tasks to global concurrent queues, they do not specify a direct priority. Instead, specify a Quality of Service (QOS) class property: this indicates the importance of the task and helps the GCD determine the priorities to assign to the task.

Sync, Async


Sync (synchronous)

After the thread registered with the queue is finished, run the next queue sequentially.


Async (asynchronous)

The threads registered in the queue do not wait until the end of the operation, and the next queue is run sequentially and simultaneously. The end of a task is not sequential and can vary from task to task. The difference is whether to wait until one task is completed and then run the next. In the case of Sync, you should use Async because you can't do anything if you use it if it takes a long time or you're uncertain when it's going to be done. Depending on which queue uses synchronous asynchronous, you can use it as follows:
  • Serial
    • Sync
    • Async
  • Concurrent
    • Sync
    • Async


Using Dispatch Queue


Create DispatchQueue

// Serial Queue
DispatchQueue.main.sync { } // CRASH!
DispatchQueue.main.async { }
DispatchQueue(label: "com.CustomSerialQueue").sync { }
DispatchQueue(label: "com.CustomSerialQueue").async { }

// Concurrent Queue
DispatchQueue.global().sync { }
DispatchQueue.global().async { }
DispatchQueue(label: "com.CustomConcurrentQueue", attributes: .concurrent).sync { }
DispatchQueue(label: "com.CustomConcurrentQueue", attributes: .concurrent).async { }
  






DispatchQueue.main.sync If you use , you will get an error. The reason for this is that if you sync to the main queue while working on the main queue and block it, you will fall into a deadlock. If you synchronise serial queues, you can create and use custom queues rather than main.


Serial queue - Sync

Because other tasks are blocked until the end of the queue's work, one operation must be completed before the other runs sequentially.

let serialQueue = DispatchQueue(label: "serialQueue")

serialQueue.sync {
  for i in 0...3{
    print("\(i) [serial_sync_1]")
  }
  print("--------------------------")
}

serialQueue.sync {
  for i in 0...5{
      print("\(i) [serial_sync_1]")
  }
  print("--------------------------")
}

for i in 0...5{
  print(i)
}


======== Result ========

0 [serial_sync_1]
1 [serial_sync_1]
2 [serial_sync_1]
3 [serial_sync_1]
--------------------------
0 [serial_sync_2]
1 [serial_sync_2]
2 [serial_sync_2]
3 [serial_sync_2]
--------------------------
0
1
2
3  


Serial queue - Async

Because it is a serial queue, the operations entered the queue are processed in order, although other operations are still processed by running the queue asynchronously.

let serialQueue = DispatchQueue(label: "serialQueue")

serialQueue.async {
  for i in 0...3{
    print("\(i) [serial_async_1]")
  }
  print("--------------------------")
}


serialQueue.async {
  for i in 0...3{
    print("\(i) [serial_async_2]")
  }
  print("--------------------------")
}

for i in 0...5 {
  print(i)
}


======== Result ========

0
0 [serial_async_1]
1
1 [serial_async_1]
2
2 [serial_async_1]
3
3 [serial_async_1]
4
--------------------------
0 [serial_async_2]
5
1 [serial_async_2]
2 [serial_async_2]
3 [serial_async_2]
--------------------------


Concurrent queue - Sync

In the serial queue, one operation must be completed, such as sync, before the other runs sequentially.

DispatchQueue.global().sync {
  for i in 0...3{
    print("\(i) [global_sync_1]")
  }
  print("--------------------------")
}

DispatchQueue.global().sync {
  for i in 0...3{
    print("\(i) [global_sync_2]")
  }
  print("--------------------------")
}

for i in 0...3 {
  print(i)
}


======== Result ========

0 [global_sync_1]
1 [global_sync_1]
2 [global_sync_1]
3 [global_sync_1]
--------------------------
0 [global_sync_2]
1 [global_sync_2]
2 [global_sync_2]
3 [global_sync_2]
--------------------------
0
1
2
3

Concurrent queue - Async

Because we process tasks simultaneously in parallel, we don't know what will start and end first.

DispatchQueue.global().async {
  for i in 0...3{
    print("\(i) [global_async_1]")
  }
  print("--------------------------")
}

DispatchQueue.global().async {
  for i in 0...3 {
    print("\(i) [global_async_2]")
  }
  print("--------------------------")
}

for i in 0...3 {
  print(i)
}

======== Result ========

0
0 [global_async_2]
0 [global_async_1]
1
1 [global_async_2]
1 [global_async_1]
2
2 [global_async_1]
3
2 [global_async_2]
3 [global_async_1]
3 [global_async_2]
--------------------------
--------------------------
Reference:

Monday, November 29, 2021

Swift: Three dot operator

You may see three dot ... operator in swift for two different cases:

1. ... as variadic parameter in function definition A variadic parameter accepts zero or more values of a specified type. The parameters are separated with comma. The value of a variadic parameter in the function’s body is an array with the specified element type. A function can only have at most one variadic parameter.

func arithmeticMean(_ numbers: Double...) -> Double {
  var total: Double = 0
    for number in numbers {
      total += number
    }
  return total / Double(numbers.count)
}

arithmeticMean(1, 2, 3, 4, 5)
arithmeticMean()
2. ... as a closed range operator in statement The closed range operator a...b creates a ClosedRange object that contains elements from a to b inclusive. The value of a must not be greater than b. It is most used to enumerate all elements in a for loop

for index in 1...5 {
  print("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25
And from the Swift documentation:
A variadic parameter accepts zero or more values of a specified type. You use a variadic parameter to specify that the parameter can be passed a varying number of input values when the function is called. Write variadic parameters by inserting three period characters (...) after the parameter’s type name. The values passed to a variadic parameter are made available within the function’s body as an array of the appropriate type. For example, a variadic parameter with a name of numbers and a type of Double... is made available within the function’s body as a constant array called numbers of type [Double].

Sunday, November 28, 2021

Which HTTP errors should never trigger an automatic retry ?


TLDR: 1xx, 2xx, 3xx, 4xx, 5xx

There are some errors that should not be retried because they seem permanent:

  • 400 Bad Request
  • 401 Unauthorized
  • 402 Payment Required
  • 403 Forbidden
  • 405 Method Not Allowed
  • 406 Not Acceptable
  • 407 Proxy Authentication Required
  • 409 Conflict - it depends
  • 410 Gone
  • 411 Length Required
  • 412 Precondition Failed
  • 413 Payload Too Large 
  • 414 URI Too Long
  • 415 Unsupported Media Type
  • 416 Range Not Satisfiable
  • 417 Expectation Failed
  • 418 I'm a teapot - not sure about this one
  • 421 Misdirected Request
  • 422 Unprocessable Entity
  • 423 Locked - it depends on how long a resource is locked in average (?)
  • 424 Failed Dependency
  • 426 Upgrade Required - can the client be upgraded automatically?
  • 428 Precondition Required - I don't thing that the precondition can be fulfilled the second time without retrying from the beginning of the whole process but it depends
  • 429 Too Many Requests - it depends but it should not be retried to fast
  • 431 Request Header Fields TooLarge
  • 451 Unavailable For Legal Reasons

So, most of the 4** Client errors should not be retried.

4xx codes mean that an error has been made at the caller's side. That could be a bad URL, bad authentication credentials or anything that indicates it was a bad request. Therefore, without fixing that problem, there isn't an use of retry. The error is in caller's domain and caller should fix it instead of hoping that it will fix itself.

The 5** Servers errors that should not be retried:

  • 500 Internal Server Error - it depends on the cause of the error
  • 501 Not Implemented
  • 502 Bad Gateway - I saw used for temporary errors so it depends
  • 505 HTTP Version Not Supported
  • 506 Variant Also Negotiates
  • 507 Insufficient Storage
  • 508 Loop Detected
  • 510 Not Extended
  • 511 Network Authentication Required

5xx error codes should be retried as those are service errors. They could be short term (overflowing threads, dependent service refusing connections) or long term (system defect, dependent system outage, infrastructure unavailable). Sometimes, services reply back with the information (often headers) whether this is permanent or temporary; and sometimes a time parameter as to when to retry. Based on these parameters, callers can choose to retry or not.

1xx, 2xx and 3xx codes need not be retried for obvious reasons.

However, in order to make the microservices more resilient you should use the Circuit breaker pattern and fail fast when the upstream is down.

Wednesday, November 24, 2021

Dart: Isolate

Lately, I have been working on a janky-improvement issue in a Flutter application, so I have a chance to understand a little bit how Dart supports the asynchronous programming - despite of being a Single Thread Language.
Here is the key you will need to remember is: Dart does one task a time. Once a task is running, everything is blocked waiting for its finish.
When a Dart app is started, an instance of the isolate is created by DartVM automatically and you can run your "main" code on it - we can call it Main Isolate (Isolate is not a thread, though they share some similar context). The process is:
  1. Make 2 FIFO queues named "MicroTask Queue" and "Event Queue"
  2. Run main() function until it's complete
  3. Run Event Loop

Event loop

  • Event loop is an infinite loop. It is there to check if no task remains on Micro Task Queue, then it will push the tasks from Event Queue to main Isolate and working on it.
  • MicroTask Queue: short time tasks for internal event that need to be done before return back to Event Queue
  • Event Queue: all tasks from external events like I/O, gesture, drawing, timers, streams, future, async, await... So, onPressed is waiting for a tap, and the future is waiting for network data, but from Dart’s perspective, those are both just events in the Event Queue - these APIs are all just ways for you to tell Dart’s event loop, "Here’s some code, please run it later."

Isolate

You can think about Isolate as a simple computer, with some `Memory`, a Single Thread, and an Event Loop. The idea is to move the heavy task to another computer that you don't interact to so you don't feed it janky (:D)

What is differences between Isolate and Thread

  • AFAIK the isolate is like its name, quite isolation, have own resources, zone, limitation.
  • Does not share heap memory between each other
  • Uses Ports and Messages to communicate between them.
  • Only support primitive data (though complex data can be passed around by Dictionary type)

When to use Isolate

  • Big JSON encoding/ decoding
  • Encryption
  • Image/ video processing

How to create an Isolate

  • Create 3 instances isolate, sendPort, receivePort
  • Registering an entry point to send and receive data
IMO, you wont use Isolate usually in most common applications. Mostly one Isolate but asynchronous is enough. This is doable through the async and await.