<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="https://publishpress.com/"
	>

<channel>
	<title>linh chau, Author at Tomoshare</title>
	<atom:link href="https://blog.tomosia.com.vn/author/linhchau/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.tomosia.com.vn/author/linhchau/</link>
	<description>Kênh chia sẻ kiến thức Tomosia Việt Nam</description>
	<lastBuildDate>Tue, 02 Jan 2024 14:20:08 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://blog.tomosia.com.vn/wp-content/uploads/2023/09/cropped-icon-32x32.png</url>
	<title>linh chau, Author at Tomoshare</title>
	<link>https://blog.tomosia.com.vn/author/linhchau/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Một vài ví dụ về animation trong Flutter</title>
		<link>https://blog.tomosia.com.vn/mot-vai-vi-du-ve-animation-trong-flutter/</link>
					<comments>https://blog.tomosia.com.vn/mot-vai-vi-du-ve-animation-trong-flutter/#comments</comments>
		
		<dc:creator><![CDATA[linh chau]]></dc:creator>
		<pubDate>Tue, 02 Jan 2024 14:20:06 +0000</pubDate>
				<category><![CDATA[Flutter]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=2703</guid>

					<description><![CDATA[<p>Như bạn biết, Animation trong các ứng dụng moblie giúp tăng tính trực quan, tính tương tác cho&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/mot-vai-vi-du-ve-animation-trong-flutter/">Một vài ví dụ về animation trong Flutter</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Như bạn biết, Animation trong các ứng dụng moblie giúp tăng tính trực quan, tính tương tác cho giao diện người dùng. Animation khi được sử dụng đúng cách, có thể tạo ra sự khác biệt lớn trong cách người dùng cảm nhận ứng dụng của bạn.</p>



<p>Với Flutter các animation được tạo bằng thư viện Animation. Chúng ta bắt đầu tìm hiểu thôi nào.</p>



<p>Chúng ta sẽ bắt đầu với 1 animation đơn giản nhất </p>



<p class="has-x-large-font-size"><strong>Rotation animation</strong></p>



<p>Bây giờ ta sẽ tạo 1 file tên là <strong>animate_widget.dart</strong> với nội dung như sau:</p>



<pre class="wp-block-code"><code>class AnimatedWidget extends StatefulWidget {
  const AnimatedWidget({super.key});

  @override
  State&lt;AnimatedWidget&gt; createState() =&gt; _AnimatedWidgetState();
}

class _AnimatedWidgetState extends State&lt;AnimatedWidget&gt;
    with TickerProviderStateMixin {
  late Animation _arrowAnimation;
  late AnimationController _arrowAnimationController;

  @override
  void initState() {
    super.initState();
    _arrowAnimationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    )..repeat();
    _arrowAnimation =
        Tween(begin: 0.0, end: pi).animate(_arrowAnimationController);
  }

  @override
  void dispose() {
    _arrowAnimationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: AnimatedBuilder(
        animation: _arrowAnimationController,
        builder: (context, child) =&gt; Transform.rotate(
          angle: _arrowAnimation.value,
          child: Image.asset("assets/image.jpg"),
        ),
      ),
    );
  }
}
</code></pre>



<p>Trong phương thức&nbsp;<strong>initState()</strong>,&nbsp;<strong>_arrowAnimationControll</strong>&nbsp;được khởi tạo với thời gian xảy ra của animation là 300 mili giây.</p>



<p><strong>_arrowAnimation</strong>&nbsp;được khởi tạo với giá trị begin là 0,0 và giá trị end là <strong>π </strong>do đó, nó sẽ xoay 180 độ. (pi = π = 180°)</p>



<p>Trong đoạn code trên chúng ta tạo 1 image và thêm một animation cho nó. Để image có animation thì cần phải bọc nó trong 1 <strong>AnimatedBuilder widget</strong> và dùng thuộc tính Transform.rotate để có thể tạo 1 vòng tròn với góc là giá trị của <strong>_arrowAnimation</strong>.</p>



<p><strong>AnimatedBuilder widget </strong>là một widget rất hữu ích khi xây dựng animation. Nó hiệu quả hơn việc gọi <strong>setState()</strong> mỗi khi có sự thay đổi giá trị của animation.</p>



<p>Ở đây mình có sử dụng hàm <strong>repeat()</strong> để có thể lặp đi lặp lại việc xoay tròn widget</p>



<p>Và để có thể sử dụng được animation thì bắt buộc phải kế thừa class <strong>TickerProviderStateMixin</strong> bằng cách thêm thuộc tính <strong>with TickerProviderStateMixin </strong></p>



<p>Và cũng đừng quên dùng phương thức  <strong>_arrowAnimationController.dispose()</strong> trong hàm <strong>dispose</strong>, nếu không thì sẽ bị memory leak đấy.</p>



<p class="has-x-large-font-size"><strong>Scale Up, Down Animation</strong></p>



<p>Chúng ta sửa lại 1 chút ở file <strong>animate_widget.dart</strong> ở trên </p>



<pre class="wp-block-code"><code>class AnimatedWidget extends StatefulWidget {
  const AnimatedWidget({super.key});

  @override
  State&lt;AnimatedWidget&gt; createState() =&gt; _AnimatedWidgetState();
}

class _AnimatedWidgetState extends State&lt;AnimatedWidget&gt;
    with TickerProviderStateMixin {
  late Animation _heartAnimation;
  late AnimationController _heartAnimationController;

  @override
  void initState() {
    super.initState();
      _heartAnimationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    );
    _heartAnimation = Tween(begin: 160.0, end: 200.0).animate(
      CurvedAnimation(
        curve: Curves.bounceOut,
        parent: _heartAnimationController,
      ),
    );

    _heartAnimationController.addStatusListener((AnimationStatus status) {
      if (status == AnimationStatus.completed) {
        _heartAnimationController.repeat();
      }
    });
  }

  @override
  void dispose() {
    _heartAnimationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(children: &#91;
        const SizedBox(height: 100),
        Center(
          child: AnimatedBuilder(
            animation: _heartAnimationController,
            builder: (context, child) {
              return Center(
                child: SizedBox(
                  child: Center(
                    child: Icon(
                      Icons.favorite,
                      color: Colors.red,
                      size: _heartAnimation.value,
                    ),
                  ),
                ),
              );
            },
          ),
        ),
        const Spacer(),
        InkWell(
          onTap: () {
            _heartAnimationController.forward();
          },
          child: Container(
            color: Colors.red,
            margin: const EdgeInsets.only(bottom: 30),
            padding: const EdgeInsets.all(20),
            child: const Text("Run Example"),
          ),
        )
      ]),
    );
  }
}
</code></pre>



<p>Ta thêm hai biến&nbsp;<strong>_heartAnimation</strong>&nbsp;và&nbsp;<strong>_heartAnimationController</strong>&nbsp;tương ứng với Animation và AnimationController .</p>



<p><strong>_heartAnimationController</strong> sẽ được khởi tạo với duration là 1200 mili giây.</p>



<p><strong>_heartAnimation</strong> với begin là 150 và end là 170. Tương ứng với kích thước bé nhất và lớn nhất của trái tim.</p>



<p><img decoding="async" src="https://twemoji.maxcdn.com/v/14.0.2/72x72/2764.png" alt="❤️"></p>



<p>Giờ thì ta cần ghép icon trái tim với animation ở trên.</p>



<p>Và chúng ta có kết quả chạy như ở dưới đây</p>



<figure class="wp-block-video"><video height="1648" style="aspect-ratio: 762 / 1648;" width="762" controls src="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screen-Recording-2023-12-25-at-2.48.59-PM.mov"></video></figure>



<p>Qua bài này mình đã giới thiệu các animation đơn giản và được sử dụng nhiều trong Flutter. Cảm ơn các bạn đã theo dõi.</p>
<p>The post <a href="https://blog.tomosia.com.vn/mot-vai-vi-du-ve-animation-trong-flutter/">Một vài ví dụ về animation trong Flutter</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/mot-vai-vi-du-ve-animation-trong-flutter/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		<enclosure url="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screen-Recording-2023-12-25-at-2.48.59-PM.mov" length="1015134" type="video/quicktime" />

			</item>
		<item>
		<title>Đa luồng trong Flutter </title>
		<link>https://blog.tomosia.com.vn/da-luong-trong-flutter/</link>
					<comments>https://blog.tomosia.com.vn/da-luong-trong-flutter/#comments</comments>
		
		<dc:creator><![CDATA[linh chau]]></dc:creator>
		<pubDate>Mon, 11 Dec 2023 12:20:22 +0000</pubDate>
				<category><![CDATA[Flutter]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=2457</guid>

					<description><![CDATA[<p>Trước khi vào bài viết thì mình xin giới thiệu 1 chút về Flutter: Flutter là Mobile UI&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/da-luong-trong-flutter/">Đa luồng trong Flutter </a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p></p>



<p>Trước khi vào bài viết thì mình xin giới thiệu 1 chút về <strong>Flutter</strong>:</p>



<p>Flutter là Mobile UI Framework được Google phát hành vào năm 2017, được sử dụng để phát triền giao diện các ứng dụng di động trên các nền tảng Android/ iOS/ MacOs/……</p>



<p>Bất kỳ ngôn ngữ lập trình nào thì cũng phải tìm cách xử lý khi chạy những task nặng, tốn thời gian…Thì khi đó việc lập trình bất đồng bộ hoặc xử lý chúng trong background được tạo ra, thay vì xử lý trên Main thread thì việc gây giật UI hoặc ứng dụng chạy chậm, gây nóng máy làm khó chịu cho người sử dụng.</p>



<p>Và cũng là một UI Framework, Flutter đã cung cấp Stream và Future để hỗ trợ chúng ta trong việc giải quyết các vấn đề trong lập trình bất đồng bộ</p>



<ol class="wp-block-list">
<li class="has-large-font-size"><strong>Stream:&nbsp;</strong></li>
</ol>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="536" height="358" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/1.png" alt="" class="wp-image-2462" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/12/1.png 536w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/1-300x200.png 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/1-380x254.png 380w" sizes="(max-width: 536px) 100vw, 536px" /></figure>



<ol class="wp-block-list">
<li>Thực chất <strong>Stream</strong> là một luồng data bất đồng bộ, nó giống như 1 cái ống gồm 1 đầu nhận dữ liệu và đầu kia sẽ là dữ liệu khi nó xử lý xong</li>



<li>Cấu trúc của 1 <strong>Stream</strong>:&nbsp;</li>
</ol>



<ul class="wp-block-list">
<li>Để handle một Stream thì ta có <strong>StreamController</strong>.</li>
</ul>



<ul class="wp-block-list">
<li>Để đẩy dữ liệu vào <strong>Stream</strong> thì thông qua thuộc tính <strong>sink</strong>(có thể đẩy bất kỳ dữ liệu nào vào Stream: value, object, collection….)</li>
</ul>



<ul class="wp-block-list">
<li>Để <strong>publish</strong> dữ liệu ra ngoài thì chúng ta dùng thuộc tính <strong>stream</strong>,&nbsp; và dùng hàm <strong>listen</strong> để lắng nghe dữ liệu trả về</li>
</ul>



<p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color">Như ví dụ dưới đây, chúng ta sẽ tạo 1 danh sách có 10 phần tử, sau mỗi lần chạy thì sẽ add dữ liệu đó vào Stream.</mark></p>



<pre class="wp-block-code"><code>class _StreamWidgetExampleState extends State&lt;StreamWidgetExample&gt; {
 final StreamController _counterController = StreamController&lt;int&gt;();
 Stream get _counterStream =&gt; _counterController.stream;
 late StreamSubscription _subscription;

  _increment() {
    List.generate(10, (data) {
      _counterController.sink.add(data);
    });
  }

  @override
  void initState() {
    super.initState();
    _increment();
    _subscription = _counterStream.listen((data) {
      print("Receive data $data");
    });
  }

  @override
  void dispose() {
    _subscription.cancel();
    _counterController.close();
    super.dispose();
  }
}</code></pre>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="378" height="362" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screenshot-2023-12-11-at-8.25.40-AM.png" alt="" class="wp-image-2496" style="width:230px;height:auto" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screenshot-2023-12-11-at-8.25.40-AM.png 378w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screenshot-2023-12-11-at-8.25.40-AM-300x287.png 300w" sizes="(max-width: 378px) 100vw, 378px" /></figure>



<p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color">và đây là kết quả khi chạy function trên</mark></p>



<p class="has-large-font-size">2. <strong>Future</strong></p>



<ul class="wp-block-list">
<li><strong>Future </strong>là một hàm thực thi cho các hoạt động bất đồng bộ, và có 2 trạng thái đó là <strong>Completed </strong>và<strong> UnCompleted</strong></li>
</ul>



<ul class="wp-block-list">
<li><strong>Uncompleted</strong>: khi bạn gọi một hàm không đồng bộ, nó trả về một uncompleted future. Future này đang chờ cho các hoạt động không đồng bộ của hàm kết thúc hoặc trả về một error.</li>



<li><strong>Completed</strong>: nếu một hành động không đồng bộ thành công, future sẽ hoàn thành với một giá trị. Nếu không nó hoàn thành với một error.<ul><li>Hoàn thành với một giá trị: một future của kiểu <strong>Future&lt;T&gt;</strong> hoàn thành với một giá trị thuộc kiểu <strong>T</strong>. Ví dụ, một future với kiểu <strong>Future&lt;String&gt;</strong> thì nó sẽ trả về một giá trị string. Nếu một future không cung cấp một kiểu giá trị nào thì kiểu của future là <strong>Future&lt;void&gt;</strong>.</li></ul>
<ul class="wp-block-list">
<li>Hoàn thành với một error: nếu một hoạt động bất đồng bộ được thực hiện bởi một hàm thất bại vì bất kỳ lý do gì thì future hoàn thành với một error.</li>
</ul>
</li>



<li>Khi sử dụng hàm Future thì bắt buộc phải có từ khoá <strong>async</strong> và <strong>await:</strong></li>
</ul>



<p>Khi tạo 1 hàm bất đồng bộ thì ta phải thêm từ khoá <strong>async</strong> trước thân hàm:</p>



<ul class="wp-block-list">
<li><strong>async</strong>: Bạn có thể sử dụng từ khóa&nbsp;async&nbsp;trước thân hàm bất đồng bộ.</li>
</ul>



<ul class="wp-block-list">
<li><strong>async function</strong>: là một function được đánh dấu bởi từ khóa&nbsp;async.</li>
</ul>



<ul class="wp-block-list">
<li><strong>await</strong>: bạn có thể sử dụng từ khóa&nbsp;await&nbsp;để lấy kết quả từ một việc bất đồng bộ. Từ khóa&nbsp;await&nbsp;chỉ được sử dụng với hàm&nbsp;async.</li>
</ul>



<pre class="wp-block-code"><code> futureExampleFunc() async {
    //do something
 }</code></pre>



<p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color">Đây là hàm không có kiểu dữ liệu trả về</mark></p>



<pre class="wp-block-code"><code>  Future&lt;Auth&gt; futureFunc() async {
    //do something
    return Auth();
  }</code></pre>



<p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color">Còn đây là hàm có kiểu dữ liệu trả về</mark></p>



<pre class="wp-block-code"><code>
  initData() async {
    var auth = await futureFunc();
    print(auth);
  }</code></pre>



<p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color">Bây giờ chỉ cần thêm await khi chờ hàm này thực thi xong thì sẽ gán dữ liệu cho auth</mark></p>



<p>Đây là sơ đồ hoạt động của 1 <strong>Async Function</strong> </p>



<figure class="wp-block-image size-full"><img decoding="async" width="382" height="442" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/dart-async-function.png" alt="" class="wp-image-2501" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/12/dart-async-function.png 382w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/dart-async-function-259x300.png 259w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/dart-async-function-380x440.png 380w" sizes="(max-width: 382px) 100vw, 382px" /></figure>



<p>Mặc dù Stream và Future đã hỗ trợ rất tốt trong việc lập trình bất đồng bộ, nhưng việc này vẫn chưa giải quyết được triệt để vấn đề vì chúng đều thực hiện trên luồng chính. Vì vậy Isolate được đưa ra như là một giải pháp cho việc này, bằng việc thực hiện các việc trên dưới background. </p>



<p class="has-large-font-size">3. <strong>Isolate</strong></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="931" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/image-16-1024x931.png" alt="" class="wp-image-2505" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/12/image-16-1024x931.png 1024w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/image-16-300x273.png 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/image-16-768x698.png 768w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/image-16-1536x1397.png 1536w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/image-16-380x346.png 380w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/image-16-800x727.png 800w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/image-16-1160x1055.png 1160w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/image-16.png 1686w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="has-text-align-center">Sơ đồ hoạt động của Isolate</p>



<p><strong>Isolate</strong> là một tham chiếu đến một thread, thường khác với main thread hiện tại. Hay có thể nói dễ hiểu hơn thì Isolate là một phiên bản tương ứng của Thread trên ngôn ngữ lập trình Dart. Nó tương tự với Vòng lặp sự kiện <strong>(Event Loop)</strong> nhưng có một số điểm khác biệt như sau:</p>



<ul class="wp-block-list">
<li>Nó là 1 thread với bộ nhớ riêng, biệt lập.</li>



<li>Nó không thể chia sẻ trực tiếp dữ liệu với các thread khác.</li>



<li>Bất kể dữ liệu nào được truyền giữa các thread đều bị trùng lặp.</li>
</ul>



<p>Mỗi Isolate có một vòng lặp sự kiện <strong>(Event Loop)</strong> của riêng mình nhờ đó chúng sẽ hoạt động song song và độc lập với nhau.</p>



<p>Hãy xem ví dụ dưới đây để có thể hiểu rõ hơn cách hoạt động của 1 Isolate. Chúng ta tạo ra 1 Isolate để xử lý cho việc chạy 1 vòng lặp từ 1 -&gt; 1000000, sau khi chạy xong vòng lặp sẽ kết thúc và trả dữ liệu về cho hàm gọi nó. </p>



<pre class="wp-block-code"><code>void myIsolate(SendPort sendPort) {
  int data = 0;
  for (int i = 0; i &lt;= 1000000; i++) {
    data += i;
  // sau mỗi vòng lặp thì data sẽ cộng thêm giá trị của biến i
  }
  //sau khi kết thúc vòng lặp sẽ gọi hàm exit để kết thúc isolate này và trả data về
  Isolate.exit(sendPort, data);
}</code></pre>



<pre class="wp-block-code"><code>  void _runMyIsolate() async {
    var receivePort = ReceivePort();
  // đăng ký một isolate thông qua hàm spawn, ở đây ta sẽ truyền hàm xử lý dữ liệu và 1 port
    await Isolate.spawn(myIsolate, receivePort.sendPort);
    print(await receivePort.first);
  }</code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="286" height="115" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screenshot-2023-12-11-at-9.38.42-AM.png" alt="" class="wp-image-2514"/></figure>



<p>Chúng ta có thể thấy khi thực hiện việc tạo 1 thread isolate là thông qua method <strong>Isolate.spawn</strong> thì lúc này ứng dụng sẽ tạo ra 1 thread với tên là <strong>myIsolate</strong> chạy song song với luồng main, và luồng này sẽ bị đóng lại khi sử dụng method <strong>Isolate.exit.</strong></p>



<p class="has-large-font-size">4. Kết luận</p>



<p>Flutter ( Dart ) là Single-Thread , do đó để làm hài lòng người dùng, các nhà phát triển phải đảm bảo rằng ứng dụng sẽ chạy trơn tru nhất có thể. <strong>Stream</strong>, <strong>Futures</strong> và <strong>Isolates</strong> là những công cụ rất mạnh có thể giúp bạn đạt được mục tiêu này.</p>
<p>The post <a href="https://blog.tomosia.com.vn/da-luong-trong-flutter/">Đa luồng trong Flutter </a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/da-luong-trong-flutter/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
