<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Quang Dang - ARROW Technologies Blog]]></title><description><![CDATA[Trang tổng hợp các kiến thức về lập trình]]></description><link>https://blog.arrow-tech.vn/</link><image><url>https://blog.arrow-tech.vn/favicon.png</url><title>Quang Dang - ARROW Technologies Blog</title><link>https://blog.arrow-tech.vn/</link></image><generator>Ghost 5.81</generator><lastBuildDate>Sun, 12 Apr 2026 08:26:14 GMT</lastBuildDate><atom:link href="https://blog.arrow-tech.vn/author/quangdn/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Hướng dẫn crawl website với Scrapy]]></title><description><![CDATA[Crawl
]]></description><link>https://blog.arrow-tech.vn/huong-dan-crawl-website-voi-scrapy-2/</link><guid isPermaLink="false">63915acd7a2f410001205def</guid><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Tue, 11 Feb 2020 04:42:52 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2020/02/maxresdefault.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.arrow-tech.vn/content/images/2020/02/maxresdefault.jpg" alt="H&#x1B0;&#x1EDB;ng d&#x1EAB;n crawl website v&#x1EDB;i Scrapy"><p><a href="https://scrapy.org/?ref=blog.arrow-tech.vn">Scrapy</a> l&#xE0; m&#x1ED9;t tr&#xEC;nh thu th&#x1EAD;p d&#x1EEF; li&#x1EC7;u d&#x1EF1;a tr&#xEA;n Python c&#xF3; th&#x1EC3; &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; tr&#xED;ch xu&#x1EA5;t th&#xF4;ng tin t&#x1EEB; c&#xE1;c trang web. N&#xF3; nhanh v&#xE0; &#x111;&#x1A1;n gi&#x1EA3;n, v&#xE0; c&#xF3; th&#x1EC3; &#x111;i&#x1EC1;u h&#x1B0;&#x1EDB;ng c&#xE1;c trang gi&#x1ED1;ng nh&#x1B0; tr&#xEC;nh duy&#x1EC7;t c&#xF3; th&#x1EC3;. N&#xF3; l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng framework &#xA0;m&#xE3; ngu&#x1ED3;n m&#x1EDF; t&#x1ED1;t nh&#x1EA5;t d&#xF9;ng &#x111;&#x1EC3; crawl d&#x1EEF; li&#x1EC7;u. (<a href="https://www.scrapehero.com/open-source-web-scraping-frameworks-and-tools/?ref=blog.arrow-tech.vn">link</a>)</p><h2 id="b-c-1-c-i-t">B&#x1B0;&#x1EDB;c 1: C&#xE0;i &#x111;&#x1EB7;t </h2><p>&#x1EDE; &#x111;&#xE2;y ch&#xFA;ng t&#xF4;i s&#x1EED; d&#x1EE5;ng <a href="https://virtualenv.pypa.io/en/stable/?ref=blog.arrow-tech.vn" rel="nofollow">virtualenv</a> &#x111;&#x1EC3; c&#xE0;i &#x111;&#x1EB7;t scrapy. &#x110;i&#x1EC1;u n&#xE0;y cho ph&#xE9;p ch&#xFA;ng t&#xF4;i c&#xE0;i &#x111;&#x1EB7;t scrapy m&#xE0; kh&#xF4;ng &#x1EA3;nh h&#x1B0;&#x1EDF;ng &#x111;&#x1EBF;n c&#xE1;c m&#xF4;-&#x111;un c&#xE0;i &#x111;&#x1EB7;t h&#x1EC7; th&#x1ED1;ng kh&#xE1;c.</p><p>T&#x1EA1;o m&#x1ED9;t th&#x1B0; m&#x1EE5;c ch&#x1EE9;a project crawler d&#x1EEF; li&#x1EC7;u d&#xF9;ng &#x111;&#x1EC3; l&#x1B0;u tr&#x1EEF; code v&#xE0; t&#x1EA1;o m&#x1ED9;t m&#xF4;i tr&#x1B0;&#x1EDD;ng &#x1EA3;o trong &#x111;&#xF3;.</p><pre><code>mkdir crawlBlogArrow
cd crawlBlogArrow
virtualenv venv
. venv/bin/activate</code></pre><p>C&#xE0;i &#x111;&#x1EB7;t scrapy</p><pre><code>pip install scrapy</code></pre><p>Ki&#x1EC3;m tra xem n&#xF3; &#x111;&#xE3; ho&#x1EA1;t &#x111;&#x1ED9;ng hay ch&#x1B0;a. M&#xE0;n h&#xEC;nh d&#x1B0;&#x1EDB;i &#x111;&#xE2;y cho th&#x1EA5;y phi&#xEA;n b&#x1EA3;n m&#xE0; t&#xF4;i &#x111;ang s&#x1EED; d&#x1EE5;ng l&#xE0; 1.8.0</p><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2020/02/1.png" class="kg-image" alt="H&#x1B0;&#x1EDB;ng d&#x1EAB;n crawl website v&#x1EDB;i Scrapy" loading="lazy"></figure><h2 id="b-c-2-t-o-project-v-s-d-ng">B&#x1B0;&#x1EDB;c 2: T&#x1EA1;o Project v&#xE0; s&#x1EED; d&#x1EE5;ng</h2><h3 id="2-1-t-o-project">2.1 T&#x1EA1;o Project </h3><p>&#x110;&#x1EC3; t&#x1EA1;o 1 project scrapy ta s&#x1EED; d&#x1EE5;ng c&#xE2;u l&#x1EC7;nh sau</p><pre><code>scrapy startproject crawl</code></pre><p>&#x110;&#xE2;y l&#xE0; c&#x1EA5;u tr&#xFA;c th&#x1B0; m&#x1EE5;c ch&#xFA;ng ta v&#x1EEB;a t&#x1EA1;o th&#xF4;ng qua Scrapy</p><p>crawl/<br>&#x251C;&#x2500;&#x2500; crawl &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; # n&#x1A1;i ch&#x1EE9;a code c&#x1EE7;a d&#x1EF1; &#xE1;n<br>&#x2502; &#xA0; &#x251C;&#x2500;&#x2500; <strong>init</strong>.py<br>&#x2502; &#xA0; &#x251C;&#x2500;&#x2500; items.py &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;# n&#x1A1;i &#x111;&#x1ECB;nh ngh&#x129;a c&#xE1;c tr&#x1B0;&#x1EDD;ng d&#x1EEF; li&#x1EC7;u c&#x1EA7;n l&#x1B0;u v&#xE0;o db<br>&#x2502; &#xA0; &#x251C;&#x2500;&#x2500; pipelines.py &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;# n&#x1A1;i x&#x1EED; l&#xFD; c&#xE1;c item tr&#xED;ch xu&#x1EA5;t &#x111;&#x1B0;&#x1EE3;c v&#xE0; l&#x1B0;u v&#xE0;o db<br>&#x2502; &#xA0; &#x251C;&#x2500;&#x2500; settings.py &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;# c&#x1EA5;u h&#xEC;nh th&#xEA;m c&#xE1;c ph&#x1EA7;n m&#x1EDF; r&#x1ED9;ng (middlewares) v&#xE0; c&#xE1;c th&#xF4;ng s&#x1ED1; c&#x1EA5;u h&#xEC;nh kh&#xE1;c<br>&#x2502; &#xA0; &#x2514;&#x2500;&#x2500; spiders &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; # th&#x1B0; m&#x1EE5;c ch&#x1EE9;a c&#xE1;c spider<br>&#x2502; &#xA0; &#xA0; &#xA0; &#x2514;&#x2500;&#x2500; <strong>init</strong>.py<br>&#x2514;&#x2500;&#x2500; scrapy.cfg &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;# file c&#x1EA5;u h&#xEC;nh v&#x1EC1; deploy v&#xE0; settings c&#x1EE7;a project</p><h3 id="2-2-c-t-d-li-u">2.2 &#x110;&#x1EB7;c t&#x1EA3; d&#x1EEF; li&#x1EC7;u</h3><p>File <code>items.py</code> &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; khai b&#xE1;o metadata cho nh&#x1EEF;ng d&#x1EEF; li&#x1EC7;u m&#xE0; ch&#xFA;ng ta mu&#x1ED1;n scrape. Trong file n&#xE0;y c&#xF3; class <code>StackItem</code> l&#xE0; class &#x111;&#x1B0;&#x1EE3;c k&#x1EBF; th&#x1EEB;a t&#x1EEB; class <a href="http://doc.scrapy.org/en/latest/topics/items.html?ref=blog.arrow-tech.vn"><code>Item</code></a> c&#x1EE7;a Scrapy. Trong class n&#xE0;y &#x111;&#xE3; &#x111;&#x1ECB;nh ngh&#x129;a tr&#x1B0;&#x1EDB;c m&#x1ED9;t s&#x1ED1; &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng m&#xE0; Scrapy c&#x1EA7;n d&#xF9;ng &#x111;&#x1EC3; scrape.</p><pre><code>import scrapy

class StackItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass</code></pre><p>B&#xE2;y gi&#x1EDD;, ch&#xFA;ng ta s&#x1EBD; th&#xEA;m v&#xE0; nh&#x1EEF;ng d&#x1EEF; li&#x1EC7;u m&#xE0; ch&#xFA;ng ta c&#x1EA7;n</p><pre><code>import scrapy

class StackItem(scrapy.Item):
    title = scrapy.Field()
    thumb = scrapy.Field()    
    content = scrapy.Field()    
    author = scrapy.Field()</code></pre><h3 id="2-3-t-o-spiders">2.3 T&#x1EA1;o spiders</h3><p>Ch&#xFA;ng ta s&#x1EBD; t&#x1EA1;o m&#x1ED9;t &#xA0;spider <code>blogarrow.py</code> trong th&#x1B0; m&#x1EE5;c <code>spiders</code> &#xA0;&#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o &#x1EDF; tr&#xEA;n. Th&#x1B0; m&#x1EE5;c n&#xE0;y kh&#xE1; &#x111;&#x1EB7;c bi&#x1EC7;t, b&#x1EDF;i n&#xF3; l&#xE0; n&#x1A1;i ch&#xFA;ng ta &#x111;&#x1B0;a ra c&#xE1;c ch&#x1EC9; &#x111;&#x1ECB;nh cho Scrapy bi&#x1EBF;t ch&#xED;nh x&#xE1;c ch&#xFA;ng ta mu&#x1ED1;n thu th&#x1EAD;p d&#x1EEF; li&#x1EC7;u g&#xEC;. Trong th&#x1B0; m&#x1EE5;c n&#xE0;y, b&#x1EA1;n c&#xF3; th&#x1EC3; &#x111;&#x1ECB;nh ngh&#x129;a c&#xE1;c Spider kh&#xE1;c nhau cho c&#xE1;c trang Web kh&#xE1;c nhau.</p><p>B&#x1EAF;t &#x111;&#x1EA7;u b&#x1EB1;ng m&#x1ED9;t class k&#x1EBF; th&#x1EEB;a t&#x1EEB; class <code>Spider</code> c&#x1EE7;a Scrapy v&#xE0; ch&#xFA;ng ta s&#x1EBD; th&#xEA;m v&#xE0;o c&#xE1;c thu&#x1ED9;c t&#xED;nh c&#x1EA7;n thi&#x1EBF;t.</p><pre><code>from scrapy import Spider

class CrawlerSpider(Spider):
    name = &quot;crawler&quot;
    allowed_domains = [&quot;blog.arrow-tech.vn&quot;]
    start_urls = [
        &quot;https://blog.arrow-tech.vn/detect-labels-faces-and-landmarks-in-images-with-the-cloud-vision-api/&quot;,
    ]</code></pre><p>Nh&#x1EEF;ng thu&#x1ED9;c t&#xED;nh &#x1EDF; &#x111;&#xE2;y kh&#xE1; d&#x1EC5; hi&#x1EC3;u, ch&#xFA;ng th&#x1EC3; hi&#x1EC7;n &#xFD; ngh&#x129;a qua ch&#xED;nh t&#xEA;n c&#x1EE7;a m&#xEC;nh. N&#x1EBF;u c&#x1EA7;n th&#xEA;m th&#xF4;ng tin, b&#x1EA1;n c&#xF3; th&#x1EC3; tham kh&#x1EA3;o &#x1EDF; <a href="http://doc.scrapy.org/en/latest/topics/spiders.html?ref=blog.arrow-tech.vn">&#x111;&#xE2;y</a>:</p><ul><li><code>name</code> &#x111;&#x1ECB;nh ngh&#x129;a t&#xEA;n c&#x1EE7;a Spider.</li><li><code>allowed_domains</code> ch&#x1EE9;a URL g&#x1ED1;c c&#x1EE7;a trang Web b&#x1EA1;n mu&#x1ED1;n scrape.</li><li><code>start_urls</code> l&#xE0; danh s&#xE1;ch c&#xE1;c URL &#x111;&#x1EC3; Spider b&#x1EAF;t &#x111;&#x1EA7;u qu&#xE1; tr&#xEC;nh scraping. T&#x1EA5;t c&#x1EA3; m&#x1ECD;i d&#x1EEF; li&#x1EC7;u s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c Spider download t&#x1EEB; c&#xE1;c URL &#x1EDF; trong <code>start_urls</code> n&#xE0;y.</li></ul><h3 id="xpath-selector">XPath selector</h3><p>M&#x1ED9;t &#x111;i&#x1EC1;u r&#x1EA5;t quan tr&#x1ECD;ng, &#x111;&#xF3; l&#xE0; <a href="http://doc.scrapy.org/en/latest/topics/selectors.html?ref=blog.arrow-tech.vn">Scrapy s&#x1EED; d&#x1EE5;ng XPath selector</a> &#x111;&#x1EC3; tr&#xED;ch xu&#x1EA5;t d&#x1EEF; li&#x1EC7;u t&#x1EEB; c&#xE1;c trang Web. N&#xF3;i m&#x1ED9;t c&#xE1;ch kh&#xE1;c, &#x111;&#xF3; l&#xE0; ch&#xFA;ng ta c&#xF3; th&#x1EC3; ch&#x1ECD;n l&#x1ECD;c ra m&#x1ED9;t th&#xE0;nh ph&#x1EA7;n ch&#xED;nh x&#xE1;c tr&#xEA;n m&#x1ED9;t trang Web b&#x1EB1;ng c&#xE1;ch s&#x1EED; d&#x1EE5;ng <a href="http://www.w3.org/TR/xpath/?ref=blog.arrow-tech.vn">XPath</a>.</p><h3 id="tr-ch-xu-t-d-li-u">Tr&#xED;ch xu&#x1EA5;t d&#x1EEF; li&#x1EC7;u</h3><p>Ch&#xFA;ng ta th&#x1EF1;c hi&#x1EC7;n tr&#xED;ch xu&#x1EA5;t d&#x1EEF; li&#x1EC7;u v&#x1EDB;i &#x111;o&#x1EA1;n code d&#x1B0;&#x1EDB;i &#x111;&#xE2;y</p><pre><code>import scrapy
from scrapy import Spider
from crawl.items import CrawlItem

class CrawlerSpider(Spider):
    name = &quot;crawler&quot;
    allowed_domains = [&quot;blog.arrow-tech.vn&quot;]
    start_urls = [
        &quot;https://blog.arrow-tech.vn/detect-labels-faces-and-landmarks-in-images-with-the-cloud-vision-api/&quot;,
    ]
    
    def parse(self, response):

        item = CrawlItem()
        item[&apos;title&apos;] = response.xpath(&apos;//h1[@class=&quot;post-title u-fontSizeLargest u-md-fontSizeLarger&quot;]/text()&apos;).extract()[0].strip()    
        thumb_link = &quot;https://blog.arrow-tech.vn&quot; + response.xpath(&apos;//img[@class=&quot;post-img u-block u-marginAuto&quot;]/@src&apos;).extract()[0].strip()   
        item[&apos;thumb&apos;] = thumb_link.split(&apos;/&apos;)[-1]
        yield scrapy.Request(thumb_link,callback=self.parse_img)
        item[&apos;author&apos;] =  response.xpath(&apos;//a[@class=&quot;link link--underline u-fontWeightMedium u-textColorDarker&quot;]/text()&apos;).extract()[0].strip() 
        item[&apos;content&apos;] =  response.xpath(&apos;//div[@class=&quot;post-inner js-post-content&quot;]&apos;).extract()[0].strip() 
        yield item


    def parse_img(self, response):
        with open(&quot;img/%s&quot; % response.url.split(&apos;/&apos;)[-1], &apos;wb&apos;) as f:
            f.write(response.body)
    

    </code></pre><ul><li><strong><code>item = CrawlItem()</code> </strong>Kh&#x1EDF;i t&#x1EA1;o m&#x1ED9;t m&#x1EA3;ng d&#x1EEF; li&#x1EC7;u nh&#x1B0; &#x111;&#xE3; &#x111;&#x1EB7;c t&#x1EA3; &#x1EDF; b&#xEA;n tr&#xEA;n</li><li><code><strong>item[&apos;title&apos;] = response.xpath(&apos;//h1[@class=&quot;post-title u-fontSizeLargest u-md-fontSizeLarger&quot;]/text()&apos;).extract()[0].strip()</strong></code><strong> </strong>T&#xEC;m ki&#x1EBF;m th&#x1EBB; h1 c&#xF3; class <strong><code>post-title u-fontSizeLargest u-md-fontSizeLarger</code>&#x2003;</strong>v&#xE0; l&#x1EA5;y text c&#x1EE7;a n&#xF3; <code>text()</code> </li><li><code>thumb_link = &quot;<a href="https://blog.arrow-tech.vn/">https://blog.arrow-tech.vn</a>&quot; + response.xpath(&apos;//img[@class=&quot;post-img u-block u-marginAuto&quot;]/@src&apos;).extract()[0].strip()</code> &#xA0;L&#x1EA5;y <code>thumb_link</code> v&#x1EDB;i img c&#xF3; class <code>post-img u-block u-marginAuto</code> </li><li><code>item[&apos;thumb&apos;] = thumb_link.split(&apos;/&apos;)[-1]</code> L&#x1EA5;y tr&#x1B0;&#x1EDD;ng thumb b&#x1EB1;ng c&#xE1;c x&#x1EEF; l&#xFD; bi&#x1EBF;n thumb_link v&#x1EEB;a l&#x1EA5;y &#x111;&#x1B0;&#x1EE3;c &#x1EDF; tr&#xEA;n</li><li><code>yield scrapy.Request(thumb_link,callback=self.parse_img)</code> Th&#x1EF1;c hi&#x1EC7;n download image thumb t&#x1EEB; <code>thumb_link</code> </li></ul><p>&#x2003;&#x110;o&#x1EA1;n code d&#x1B0;&#x1EDB;i &#x111;&#xE2;y c&#xF3; ch&#x1EE9;c n&#x103;ng l&#x1B0;u &#x1EA3;nh thumb v&#xE0;o m&#xE1;y c&#x1EE7;a ch&#xFA;ng ta (&#x1EDF; &#x111;&#xE2;y m&#xEC;nh l&#x1B0;u tr&#x1EEF; v&#xE0;o th&#x1B0; m&#x1EE5;c <code>img</code> c&#xF9;ng c&#x1EA5;p v&#x1EDB;i th&#x1B0; m&#x1EE5;c project)</p><pre><code>def parse_img(self, response):
        with open(&quot;img/%s&quot; % response.url.split(&apos;/&apos;)[-1], &apos;wb&apos;) as f:
            f.write(response.body)</code></pre><ul><li><code>item[&apos;content&apos;] = &#xA0;response.xpath(&apos;//div[@class=&quot;post-inner js-post-content&quot;]&apos;).extract()[0].strip()</code> L&#x1EA5;y content v&#x1EDB;i th&#x1EBB; div c&#xF3; class l&#xE0; <code>post-inner js-post-content</code> </li></ul><p>Sau khi &#x111;&#xE3; th&#x1EF1;c hi&#x1EC7;n xong nh&#x1EEF;ng b&#x1B0;&#x1EDB;c tr&#xEA;n, ch&#x1EA1;y l&#x1EC7;nh <code>crawl</code> </p><p>L&#x1EC7;nh n&#xE0;y s&#x1EBD; l&#x1B0;u tr&#x1EEF; k&#x1EBF;t qu&#x1EA3; crawl v&#xE0;o file result.json</p><pre><code>scrapy crawl crawler -o result.json </code></pre><p>B&#x1EA1;n c&#xF3; th&#x1EC3; clone v&#xED; d&#x1EE5; tr&#xEA;n &#x1EDF; &#x111;&#xE2;y &#x111;&#x1EC3; d&#xF9;ng th&#x1EED;</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/phobrv/demo_use_scrapy.git?ref=blog.arrow-tech.vn"><div class="kg-bookmark-content"><div class="kg-bookmark-title">phobrv/demo_use_scrapy</div><div class="kg-bookmark-description">Demo use Scrapy to crawler website data. Contribute to phobrv/demo_use_scrapy development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/favicon.ico" alt="H&#x1B0;&#x1EDB;ng d&#x1EAB;n crawl website v&#x1EDB;i Scrapy"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">phobrv</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://avatars0.githubusercontent.com/u/9550597?s=400&amp;v=4" alt="H&#x1B0;&#x1EDB;ng d&#x1EAB;n crawl website v&#x1EDB;i Scrapy"></div></a></figure>]]></content:encoded></item><item><title><![CDATA[Hướng dẫn sử dụng tool Auditd để giám sát hoạt động User trên Ubuntu Server]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><em>M&#x1ED9;t ng&#xE0;y &#x111;&#x1EB9;p tr&#x1EDD;i kh&#xE1;ch h&#xE0;ng y&#xEA;u c&#x1EA7;u h&#xE0;ng th&#xE1;ng ph&#x1EA3;i c&#xF3; report v&#x1EC1; ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a ssh user tr&</em></p>]]></description><link>https://blog.arrow-tech.vn/huong-dan-su-dung-tool-auditd-de-giam-sat-hoat-dong-user-tren-ubuntu-server-2/</link><guid isPermaLink="false">63915acd7a2f410001205ded</guid><category><![CDATA[ubuntu]]></category><category><![CDATA[Security]]></category><category><![CDATA[auditd]]></category><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Wed, 12 Jun 2019 07:35:51 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2019/06/1_Gmpq3RbI2TvL344DdAg55w-1.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.arrow-tech.vn/content/images/2019/06/1_Gmpq3RbI2TvL344DdAg55w-1.png" alt="H&#x1B0;&#x1EDB;ng d&#x1EAB;n s&#x1EED; d&#x1EE5;ng tool Auditd &#x111;&#x1EC3; gi&#xE1;m s&#xE1;t ho&#x1EA1;t &#x111;&#x1ED9;ng User tr&#xEA;n Ubuntu Server"><p><em>M&#x1ED9;t ng&#xE0;y &#x111;&#x1EB9;p tr&#x1EDD;i kh&#xE1;ch h&#xE0;ng y&#xEA;u c&#x1EA7;u h&#xE0;ng th&#xE1;ng ph&#x1EA3;i c&#xF3; report v&#x1EC1; ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a ssh user tr&#xEA;n server. Loay hoay h&#x1EBF;t m&#x1EA5;y h&#xF4;m google search, cu&#x1ED1;i c&#xF9;ng t&#xEC;m &#x111;&#x1B0;&#x1EE3;c em n&#xE0;y, th&#x1EA5;y c&#x169;ng kh&#xE1; ngon , vi&#x1EBF;t l&#xEA;n &#x111;&#xE2;y chia s&#x1EBB; v&#x1EDB;i a/e.</em></p>
<h2 id="vyauditlg">V&#x1EAD;y Audit l&#xE0; g&#xEC;?</h2>
<p>&#x110;&#x1A1;n gi&#x1EA3;n &#x111;&#x1EC3; hi&#x1EC3;u, auditd l&#xE0; m&#x1ED9;t th&#x1EB1;ng d&#x1ECB;ch v&#x1EE5; ch&#x1EA1;y ng&#x1EA7;m (audit deamon) ch&#x1ECB;u tr&#xE1;ch nhi&#x1EC7;m ghi l&#x1EA1;i t&#x1EA5;t c&#x1EA3; ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a h&#x1EC7; th&#x1ED1;ng , ng&#x1B0;&#x1EDD;i d&#xF9;ng ... Theo nh&#x1B0; google search th&#xEC; c&#xF3; v&#x1EBB; audit &#x111;&#x1B0;&#x1EE3;c t&#xED;ch h&#x1EE3;p m&#x1EB7;c &#x111;&#x1ECB;nh tr&#xEA;n h&#x1EA7;u Linux operating system.<br>
H&#x1EA7;u h&#x1EBF;t th&#xF4;i ch&#x1EE9; kh&#xF4;ng ph&#x1EA3;i l&#xE0; t&#x1EA5;t c&#x1EA3;, trong tr&#x1B0;&#x1EDD;ng h&#x1EE3;p m&#xEC;nh ph&#x1EA3;i ti&#x1EBF;n h&#xE0;nh c&#xE0;i &#x111;&#x1EB7;t :))</p>
<h2 id="citauditnhthno">C&#xE0;i &#x111;&#x1EB7;t audit nh&#x1B0; th&#x1EBF; n&#xE0;o?</h2>
<ul>
<li>
<p>B&#x1EA1;n c&#xF3; th&#x1EC3; google search v&#x1EDB;i keyword <code>Installing the Linux Audit System on ...</code>. C&#xF2;n n&#x1EBF;u kh&#xF4;ng th&#xEC; c&#xF3; th&#x1EC3; tham kh&#x1EA3;o t&#x1EA1;i &#x111;&#xE2;y (Trong tr&#x1B0;&#x1EDD;ng h&#x1EE3;p n&#xE0;y m&#xEC;nh d&#xF9;ng Ubuntu Server 18).</p>
<pre><code>sudo apt install -y auditd audispd-plugins
</code></pre>
</li>
<li>
<p>C&#xE1;c c&#x1EA5;u h&#xEC;nh s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c l&#x1B0;u trong folder <code>/etc/audit</code></p>
</li>
<li>
<p>&#x110;&#x1EC3; th&#x1EF1;c hi&#x1EC7;n log ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a t&#x1EA5;t c&#x1EA3; ng&#x1B0;&#x1EDD;i d&#xF9;ng:</p>
<ul>
<li>M&#x1EDF; file <code>nano /etc/audit/rules.d/audit.rules</code></li>
<li>Th&#xEA;m 2 d&#xF2;ng b&#xEA;n d&#x1B0;&#x1EDB;i v&#xE0;o cu&#x1ED1;i file</li>
</ul>
<pre><code>-a exit,always -F arch=b64 -S execve
-a exit,always -F arch=b32 -S execve
</code></pre>
<ul>
<li>Sau &#x111;&#xF3; restart v&#x1EDB;i l&#x1EC7;nh <code>sudo service auditd restart</code></li>
<li>M&#x1EB7;c &#x111;&#x1ECB;nh log s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c l&#x1B0;u tr&#x1EEF; &#x1EDF;  <code>/var/log/audit/audit.log</code>. Ho&#x1EB7;c c&#xF3; th&#x1EC3; c&#x1EA5;u h&#xEC;nh trong file /etc/audit/auditd.conf</li>
</ul>
</li>
</ul>
<p>Ok v&#x1EAD;y l&#xE0; c&#x1A1; b&#x1EA3;n h&#x1EC7; th&#x1ED1;ng &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c gi&#xE1;m s&#xE1;t b&#x1EDF;i audit r&#x1ED3;i. Gi&#x1EDD; ch&#xFA;ng ta s&#x1EBD; t&#xEC;m hi&#x1EC3;u qua c&#xE1;ch &#x111;&#x1EC3; s&#x1EED; d&#x1EE5;ng audit.</p>
<h2 id="sdngauditdnhthno">S&#x1EED; d&#x1EE5;ng <code>auditd</code> nh&#x1B0; th&#x1EBF; n&#xE0;o ?</h2>
<ul>
<li>
<p>3 ti&#x1EC7;n &#xED;ch hay d&#xF9;ng:</p>
<ul>
<li>auditctl &#x2013; 1 ti&#x1EC7;n &#xED;ch &#x111;&#x1EC3; ki&#x1EC3;m so&#xE1;t h&#x1EC7; th&#x1ED1;ng kernel audit</li>
<li>ausearch &#x2013; 1 ti&#x1EC7;n &#xED;ch cho vi&#x1EC7;c t&#xEC;m ki&#x1EBF;m c&#xE1;c audit log v&#x1EDB;i c&#xE1;c event &#x111;&#x1EB7;c bi&#x1EC7;t.</li>
<li>aureport &#x2013; 1 ti&#x1EC7;n &#xED;ch &#x111;&#x1EC3; t&#x1EA1;o c&#xE1;c b&#xE1;o c&#xE1;o v&#x1EC1; s&#x1EF1; ki&#x1EC7;n &#x111;&#x1B0;&#x1EE3;c ghi l&#x1EA1;i.</li>
</ul>
</li>
<li>
<p>C&#xE1;c th&#xF4;ng s&#x1ED1; trong logs:</p>
<ul>
<li><code>time</code> - is when the audit is done</li>
<li><code>name</code> - is the object name to be audited</li>
<li><code>cwd</code> - is the current directory</li>
<li><code>syscall</code> - is related syscall</li>
<li><code>auid</code> - is the audit user ID</li>
<li><code>uid</code> and <code>gid</code> -  User ID and Group ID<br>
...</li>
</ul>
</li>
<li>
<p>C&#xE1;c l&#x1EC7;nh aureport hay d&#xF9;ng:</p>
<ul>
<li><code>sudo aureport -au</code> : Report about authentication attempts</li>
<li><code>sudo aureport -m</code>: Report all events related to account modification<br>
...</li>
<li>Xem th&#xEA;m t&#x1EA1;i <code>sudo man aureport</code></li>
</ul>
</li>
<li>
<p>C&#xE1;c l&#x1EC7;nh ausearch hay d&#xF9;ng:</p>
<ul>
<li><code>ausearch -m USER_AUTH</code> -  Xem c&#xE1;c n&#x1ED9;i dung li&#xEA;n quan &#x111;&#x1EBF;n authentication</li>
<li><code>ausearch -m USER_CMD</code> -  Xem c&#xE1;c n&#x1ED9;i dung li&#xEA;n quan &#x111;&#x1EBF;n l&#x1EC7;nh m&#xE0; user th&#x1B0;c hi&#x1EC7;n<br>
... Xem th&#xEA;m t&#x1EA1;i <code>ausearch -m</code></li>
<li><code>man ausearch this-month</code> - (today,this-week,this-mounth ...) Xem t&#x1EA5;t c&#x1EA3; c&#xE1;c log trong th&#xE1;ng.</li>
<li><code>man ausearch this-month --file csv &gt; audit.csv</code> - Export log trong th&#xE1;ng ra file CSV.</li>
<li>... Xem th&#xEA;m t&#x1EA1;i <code>sudo man ausearch</code></li>
</ul>
</li>
</ul>
<h2 id="mtviscriptshuchnucn">M&#x1ED9;t v&#xE0;i scripts h&#x1EEF;u &#xED;ch n&#x1EBF;u c&#x1EA7;n.</h2>
<p>Export CSV per month.</p>
<pre><code>#!/bin/bash

#Current date time
CURRENT_DATE=`date +&quot;%Y%m%d&quot;`

#Create folder to store
rm -rf ${CURRENT_DATE}
mkdir ${CURRENT_DATE}
cd ${CURRENT_DATE}

#Export authentication log per month
sudo ausearch -m USER_AUTH -ts this-month --format default &gt; ${CURRENT_DATE}_audit_auth.txt

#Export detail log per month
sudo ausearch  -m USER_CMD -ts this-month --format csv &gt; ${CURRENT_DATE}_audit_detail.csv
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Style Guide for Angular]]></title><description><![CDATA[<h2 id="l-i-m-u">L&#x1EDD;i m&#x1EDF; &#x111;&#x1EA7;u</h2><p>Angular l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng Framework c&#xF3; s&#x1EE9;c &#x1EA3;nh h&#x1B0;&#x1EDF;ng l&#x1EDB;n trong vi&#x1EC7;c thi&#x1EBF;t k&#x1EBF; &#x1EE9;ng d&#x1EE5;ng &#x1EDF; ph&#xED;</p>]]></description><link>https://blog.arrow-tech.vn/style-guide-angular-2/</link><guid isPermaLink="false">63915acd7a2f410001205deb</guid><category><![CDATA[Angular]]></category><category><![CDATA[Style Guide]]></category><category><![CDATA[Code Convention]]></category><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Mon, 25 Feb 2019 03:09:08 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2019/02/1_XZiWn4Ej-ZfJ6Pxj-b9AkQ-1.png" medium="image"/><content:encoded><![CDATA[<h2 id="l-i-m-u">L&#x1EDD;i m&#x1EDF; &#x111;&#x1EA7;u</h2><img src="https://blog.arrow-tech.vn/content/images/2019/02/1_XZiWn4Ej-ZfJ6Pxj-b9AkQ-1.png" alt="Style Guide for Angular"><p>Angular l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng Framework c&#xF3; s&#x1EE9;c &#x1EA3;nh h&#x1B0;&#x1EDF;ng l&#x1EDB;n trong vi&#x1EC7;c thi&#x1EBF;t k&#x1EBF; &#x1EE9;ng d&#x1EE5;ng &#x1EDF; ph&#xED;a Client Side. N&#xF3; r&#x1EA5;t m&#x1EA1;nh m&#x1EBD; b&#x1EDF;i c&#xF3; th&#xE0;nh ph&#x1EA7;n nh&#x1B0; h&#x1EC7; th&#x1ED1;ng qu&#x1EA3;n l&#xFD; routing, dependency injection, two-way binding,..</p><p>Vi&#x1EC7;c s&#x1EED; d&#x1EE5;ng Angular kh&#xE1; &#x111;&#x1A1;n gi&#x1EA3;n b&#x1EDF;i c&#x1ED9;ng &#x111;&#x1ED3;ng h&#x1ED7; tr&#x1EE3; kh&#xE1; nhi&#x1EC1;u v&#xE0; nh&#x1EEF;ng ki&#x1EBF;n th&#x1EE9;c tr&#xEA;n trang ch&#x1EE7; <a href="https://angular.io/?ref=blog.arrow-tech.vn">angular.io</a> cung c&#x1EA5;p kh&#xE1; &#x111;&#x1EA7;y &#x111;&#x1EE7;. B&#x1EA1;n c&#xF3; th&#x1EC3; d&#x1EF1;a theo lu&#x1ED3;ng h&#x1B0;&#x1EDB;ng d&#x1EAB;n v&#xE0; t&#x1EEB; &#x111;&#xF3; vi&#x1EBF;t m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng demo d&#x1EC5; d&#xE0;ng.</p><!--kg-card-begin: markdown--><p>M&#x1ED9;t ng&#x1B0;&#x1EDD;i l&#x1EAD;p tr&#xEC;nh vi&#xEA;n gi&#x1ECF;i kh&#xF4;ng ch&#x1EC9; th&#xE0;nh th&#x1EA1;o c&#xE1;c framework v&#xE0; c&#xF4;ng ngh&#x1EC7; m&#x1EDB;i m&#xE0; c&#xF2;n ph&#x1EA3;i qu&#x1EA3;n l&#xFD; v&#xE0; c&#x1EA5;u tr&#xFA;c code sao cho t&#x1ED1;t nh&#x1EA5;t. K&#x1EBF;t qu&#x1EA3; l&#xE0; code c&#x1EE7;a ch&#xFA;ng ta ph&#x1EA3;i c&#xF3; t&#xED;nh t&#xE1;i s&#x1EED; d&#x1EE5;ng, d&#x1EC5; &#x111;&#x1ECD;c, d&#x1EC5; m&#x1EDF; r&#x1ED9;ng, d&#x1EC5; qu&#x1EA3;n l&#xFD; v&#xE0; ti&#x1EBF;t ki&#x1EC7;m &#x111;&#x1B0;&#x1EE3;c th&#x1EDD;i gian debug.</p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>L&#xE0; m&#x1ED9;t dev v&#xE0; &#xED;t nhi&#x1EC1;u th&#x1EDD;i gian t&#xEC;m hi&#x1EC3;u c&#xF4;ng ngh&#x1EC7; (framework Angular 7), h&#xF4;m nay t&#xF4;i s&#x1EBD; n&#xEA;u ra m&#x1ED9;t s&#x1ED1; style guide cho Angular cho m&#x1ECD;i ng&#x1B0;&#x1EDD;i c&#xF9;ng nghi&#xEA;n c&#x1EE9;u v&#xE0; &#xE1;p d&#x1EE5;ng.</p>
<!--kg-card-end: markdown--><h2 id="m-t-s-nguy-n-t-c">M&#x1ED9;t s&#x1ED1; nguy&#xEA;n t&#x1EAF;c</h2><!--kg-card-begin: markdown--><h3 id="1ruleofone">1. Rule of One</h3>
<ul>
<li>M&#x1ED9;t component kh&#xF4;ng qu&#xE1; 400 d&#xF2;ng code</li>
<li>&#x110;&#x1EC3; thu&#x1EAD;n ti&#x1EC7;n trong vi&#x1EC7;c t&#xE1;i s&#x1EED; d&#x1EE5;ng code, hay d&#x1EC5; &#x111;&#x1ECD;c code h&#x1A1;n th&#xEC; ta n&#xEA;n chia th&#xE0;nh c&#xE1;c file service, model, module v&#xE0; component thay v&#xEC; vi&#x1EBF;t chung h&#x1EBF;t v&#xE0;o trong m&#x1ED9;t component.</li>
</ul>
<h3 id="2smallfunction">2. Small Function</h3>
<ul>
<li>M&#x1ED9;t small function gi&#x1EDB;i h&#x1EA1;n kh&#xF4;ng qu&#xE1; 75 d&#xF2;ng</li>
<li>Y&#xEA;u c&#x1EA7;u &#x111;&#x1EB7;t t&#xEA;n h&#xE0;m sao cho d&#x1EC5; &#x111;&#x1ECD;c, th&#xED;ch h&#x1EE3;p v&#x1EDB;i t&#xED;nh n&#x103;ng c&#x1EE7;a t&#x1EEB;ng h&#xE0;m.</li>
</ul>
<h3 id="3generalnamingguidelines">3. General Naming Guidelines</h3>
<ul>
<li>Khuy&#x1EBF;n kh&#xED;ch &#x111;&#x1EB7;t t&#xEA;n theo c&#x1EA5;u tr&#xFA;c: &#x201C;feature.type.file-style&#x201D;, <strong>trong &#x111;&#xF3;</strong>:<br>
+feature l&#xE0; danh t&#x1EEB; di&#x1EC5;n t&#x1EA3; &#x111;&#x1EB7;c t&#xED;nh t&#x1B0;&#x1EE3;ng tr&#x1B0;ng c&#x1EE7;a file.<br>
+type di&#x1EC5;n t&#x1EA3; ki&#x1EC3;u flie (module, service hay component).<br>
+file-style l&#xE0; t&#xEA;n &#x111;&#x1ECB;nh d&#x1EA1;ng file (ts, html hay css|scss).<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>check-list.component.ts
create-event.component.html
</code></pre>
<h3 id="4separatefilenameswithdotanddashes">4. Separate file names with dot and dashes</h3>
<ul>
<li>S&#x1EED; d&#x1EE5;ng d&#x1EA5;u &#x2018; - &#x2018; ng&#x103;n c&#xE1;ch &#x111;&#x1EB7;c t&#xED;nh t&#x1B0;&#x1EE3;ng tr&#x1B0;ng t&#xEA;n file.</li>
<li>S&#x1EED; d&#x1EE5;ng d&#x1EA5;u &#x2018; . &#x2018; &#x111;&#x1EC3; ph&#xE2;n bi&#x1EC7;t c&#xE1;c ph&#x1EA7;n trong 1 c&#x1EA5;u tr&#xFA;c &#x111;&#x1EB7;t t&#xEA;n.</li>
<li>V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>check-list.component.ts
// &apos;check-list&apos;
create-event.component.html
// &apos;create-event.component&apos;
</code></pre>
<h3 id="5symbolsandfilenamesservicenames">5. Symbols and file names / Service names</h3>
<ul>
<li>&#x110;&#x1EB7;t t&#xEA;n class t&#x1B0;&#x1A1;ng &#x1EE9;ng v&#x1EDB;i ki&#x1EC3;u file<br>
V&#xED; d&#x1EE5;: file name c&#xF3; c&#x1EA5;u tr&#xFA;c app.component.ts th&#xEC; t&#xEA;n class t&#x1B0;&#x1A1;ng &#x1EE9;ng l&#xE0; AppComponent</li>
</ul>
<pre><code>@Component({ ... })
export class AppComponent { }
--&gt; file names: app.component.ts
</code></pre>
<h3 id="6bootstrapping">6. Bootstrapping</h3>
<ul>
<li>&#x110;&#x1EB7;t bootstrapping v&#xE0; platform logic v&#xE0;o file main.ts gi&#xFA;p thu&#x1EAD;n ti&#x1EC7;n vi&#x1EC7;c kh&#x1EDF;i t&#x1EA1;o logic &#x1EE9;ng d&#x1EE5;ng v&#xE0; tu&#xE2;n th&#x1EE7; nguy&#xEA;n t&#x1EAF;c c&#xF9;ng c&#xE1;c framework kh&#xE1;c.<br>
<img src="https://blog.arrow-tech.vn/content/images/2019/02/Screen-Shot-2019-02-25-at-10.56.10-AM.png" alt="Style Guide for Angular" loading="lazy"></li>
</ul>
<h3 id="7componentselectors">7. Component selectors</h3>
<ul>
<li>S&#x1EED; d&#x1EE5;ng d&#x1EA5;u &#x2018; - &#x2018; ng&#x103;n c&#xE1;ch t&#xEA;n selector c&#x1EE7;a m&#x1ED9;t component.<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>selector: &apos;ngx-todo-list&apos; thay v&#xEC; &apos;ngxToDoList&apos;
</code></pre>
<h3 id="8componentcustomprefix">8. Component custom prefix</h3>
<ul>
<li>N&#xEA;n &#x111;&#x1EB7;t t&#xEA;n c&#xE1;c selector theo ph&#x1EA1;m vi quy&#x1EC1;n truy c&#x1EAD;p b&#x1EB1;ng vi&#x1EC7;c th&#xEA;m ti&#x1EC1;n t&#x1ED1; v&#xE0;o ph&#xED;a tr&#x1B0;&#x1EDB;c t&#xEA;n selector &#x111;&#x1ECB;nh ngh&#x129;a.<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>admin-user v&#xE0; client-user.
</code></pre>
<h3 id="9classesinterface">9. Classes / Interface</h3>
<ul>
<li>T&#xEA;n Class/Interface ph&#x1EA3;i vi&#x1EBF;t hoa ch&#x1EEF; c&#xE1;i &#x111;&#x1EA7;u ti&#xEA;n m&#x1ED7;i t&#x1EEB;.<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>export class EventService { }
</code></pre>
<h3 id="10constants">10. Constants</h3>
<ul>
<li>&#x110;&#x1ECB;nh ngh&#x129;a c&#xE1;c bi&#x1EBF;n c&#xF3; gi&#xE1; tr&#x1ECB; kh&#xF4;ng &#x111;&#x1ED5;i trong th&#x1B0; m&#x1EE5;c chung &#x2018;shared&#x2019;</li>
</ul>
<h3 id="11propertiesandmethod">11. Properties and method</h3>
<ul>
<li>T&#xEA;n c&#xE1;c ph&#x1B0;&#x1A1;ng th&#x1EE9;c ph&#x1EA3;i b&#x1EAF;t &#x111;&#x1EA7;u b&#x1EB1;ng ch&#x1EEF; c&#xE1;i vi&#x1EBF;t in th&#x1B0;&#x1EDD;ng.<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>this.timeToHide();
</code></pre>
<h3 id="12importlinespacing">12. Import line spacing</h3>
<ul>
<li>N&#xEA;n ng&#x103;n c&#xE1;ch m&#x1ED9;t d&#xF2;ng gi&#x1EEF;a th&#x1B0; vi&#x1EC7;n framework v&#x1EDB;i th&#x1B0; vi&#x1EC7;n b&#xEA;n th&#x1EE9; 3.<br>
<img src="https://blog.arrow-tech.vn/content/images/2019/02/Screen-Shot-2019-02-25-at-11.08.52-AM.png" alt="Style Guide for Angular" loading="lazy"></li>
</ul>
<h3 id="13membersequence">13. Member sequence</h3>
<ul>
<li>N&#xEA;n khai b&#xE1;o t&#xEA;n bi&#x1EBF;n theo b&#x1EA3;ng alphabet</li>
<li>N&#xEA;n comment v&#xE0; ng&#x103;n c&#xE1;ch d&#xF2;ng gi&#x1EEF;a c&#xE1;c bi&#x1EBF;n/h&#xE0;m  c&#xF3; ki&#x1EC3;u public v&#xE0; private</li>
</ul>
<h3 id="14structurecodebyliftlocateidentifyflattdry">14. Structure code By LIFT (Locate-Identify-Flat-T-DRY)</h3>
<ul>
<li>Locate: &#x110;&#x1EB7;t c&#xE1;c file li&#xEA;n quan g&#x1EA7;n v&#x1EDB;i nhau &#x111;&#x1EC3; thu&#x1EAD;n ti&#x1EC7;n cho vi&#x1EC7;c qu&#x1EA3;n l&#xFD; v&#xE0; t&#xEC;m ki&#x1EBF;m file.</li>
<li>Identify: &#x110;&#x1EB7;t t&#xEA;n t&#x1B0;&#x1A1;ng &#x1EE9;ng v&#x1EDB;i n&#x1ED9;i dung c&#x1EE7;a file &#x111;&#x1EC3; x&#xE1;c &#x111;&#x1ECB;nh m&#x1ED9;t component.</li>
<li>Flat: N&#xEA;n tr&#x1EA3;i c&#x1EA5;u tr&#xFA;c m&#x1ED9;t th&#x1B0; m&#x1EE5;c d&#xE0;i nh&#x1EA5;t c&#xF3; th&#x1EC3; nh&#x1B0;ng kh&#xF4;ng &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o d&#x1B0; th&#x1EEB;a b&#x1EB1;ng c&#xE1;ch th&#xEA;m c&#xE1;c folder ph&#x1EE5; khi folder &#x111;&#xF3; ch&#x1B0;a nhi&#x1EC1;u file kh&#xE1;c nhau.</li>
<li>T-DRY: DRY (Don&#x2019;t repeat yourself) H&#x1EA1;n ch&#x1EBF; t&#x1ED1;i &#x111;a s&#x1EF1; l&#x1EB7;p &#x111;i l&#x1EB7;p l&#x1EA1;i code.</li>
</ul>
<h3 id="15outputinputdecorator">15. Output &amp; Input Decorator</h3>
<ul>
<li>Kh&#xF4;ng &#x111;&#x1EB7;t ti&#x1EC1;n t&#x1ED1; &apos;on&apos; tr&#x1B0;&#x1EDB;c action c&#x1EA7;n emit tr&#x1EEB; khi ph&#x1EE5; v&#x1EE5; cho nghi&#x1EC7;p v&#x1EE5; c&#x1EA7;n thi&#x1EBF;t.<br>
V&#xED; d&#x1EE5;:</li>
</ul>
<pre><code>@Output() changeDate = new EventEmitter(); thay v&#xEC; &apos;onChangeDate&apos;
</code></pre>
<ul>
<li>S&#x1EED; d&#x1EE5;ng Input/Output decorator thay v&#xEC; input/output directive.</li>
</ul>
<h3 id="16putpresentationlogicinthecomponentclass">16. Put presentation logic in the component class</h3>
<ul>
<li>Vi&#x1EBF;t c&#xE1;c h&#xE0;m t&#xED;nh to&#xE1;n hay x&#x1EED; l&#xFD; logic trong component class thay v&#xEC; vi&#x1EBF;t trong template.</li>
</ul>
<h3 id="17service">17. Service</h3>
<ul>
<li>L&#xE0; m&#x1ED9;t singletons (t&#x1EE9;c l&#xE0; service l&#xE0; m&#x1ED9;t class ch&#x1EC9; t&#x1EA1;o ch&#x1EE9;a duy nh&#x1EA5;t m&#x1ED9;t th&#x1EF1;c th&#x1EC3; v&#xE0; n&#xF3; s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c d&#xF9;ng, g&#x1ECD;i &#x111;&#x1EBF;n &#x1EDF; b&#x1EA5;t c&#x1EE9; &#x111;&#xE2;u qua m&#x1ED9;t bi&#x1EBF;n to&#xE0;n c&#x1EE5;c)</li>
<li>S&#x1EED; d&#x1EE5;ng Injectable Decoration khai b&#xE1;o to&#xE0;n c&#x1EE5;c thay v&#xEC; @Inject khai b&#xE1;o c&#x1EE5;c b&#x1ED9;</li>
</ul>
<!--kg-card-end: markdown--><h2 id="k-t-lu-n">K&#x1EBF;t lu&#x1EAD;n</h2><!--kg-card-begin: markdown--><p>V&#x1EAD;y l&#xE0; ch&#xFA;ng ta &#x111;&#xE3; &#x111;i&#x1EC3;m qua m&#x1ED9;t v&#xE0;i nguy&#xEA;n t&#x1EAF;c trong vi&#x1EC7;c t&#xE1;i c&#x1EA5;u tr&#xFA;c code trong Angular. Hy v&#x1ECD;ng b&#xE0;i vi&#x1EBF;t tr&#xEA;n c&#xF3; th&#x1EC3; gi&#xFA;p c&#xE1;c b&#x1EA1;n g&#x1EA7;n g&#x169;i h&#x1A1;n v&#x1EDB;i Angular &#x111;&#x1ED3;ng th&#x1EDD;i gi&#xFA;p ta c&#xF3; t&#x1B0; duy v&#x1EC1; t&#xE1;i c&#x1EA5;u tr&#xFA;c code v&#xE0; qu&#x1EA3;n l&#xFD; code t&#x1ED1;t h&#x1A1;n. H&#x1EB9;n g&#x1EB7;p l&#x1EA1;i c&#xE1;c b&#x1EA1;n &#x1EDF; c&#xE1;c b&#xE0;i vi&#x1EBF;t ti&#x1EBF;p theo.</p>
<!--kg-card-end: markdown--><h2 id="ngu-n-tham-kh-o">Ngu&#x1ED3;n tham kh&#x1EA3;o</h2><!--kg-card-begin: markdown--><p><a href="https://angular.io/guide/styleguide?ref=blog.arrow-tech.vn#toc">https://angular.io/guide/styleguide#toc</a><br>
<a href="https://itnext.io/clean-code-checklist-in-angular-%EF%B8%8F-10d4db877f74?ref=blog.arrow-tech.vn">https://itnext.io/clean-code-checklist-in-angular-&#xFE0F;-10d4db877f74</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[[Seri] Lập trình Xamarin - Bài 1: Tổng quan về Xamarin]]></title><description><![CDATA[<p>C&#xF4;ng ngh&#x1EC7; x&#xE2;y d&#x1EF1;ng &#x1EE9;ng d&#x1EE5;ng mobile ng&#xE0;y c&#xE0;ng ph&#xE1;t tri&#x1EC3;n b&#xF9;ng n&#x1ED5;. N&#x1EBF;u nh&#x1B0; tr&#x1B0;&#x1EDB;c &#x111;&#xE2;y, c&#xE1;c b&</p>]]></description><link>https://blog.arrow-tech.vn/gioi-thieu-ve-xamarin-2/</link><guid isPermaLink="false">63915acd7a2f410001205dea</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Mobile]]></category><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Thu, 13 Dec 2018 08:02:48 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/12/Picture1.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.arrow-tech.vn/content/images/2018/12/Picture1.png" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin"><p>C&#xF4;ng ngh&#x1EC7; x&#xE2;y d&#x1EF1;ng &#x1EE9;ng d&#x1EE5;ng mobile ng&#xE0;y c&#xE0;ng ph&#xE1;t tri&#x1EC3;n b&#xF9;ng n&#x1ED5;. N&#x1EBF;u nh&#x1B0; tr&#x1B0;&#x1EDB;c &#x111;&#xE2;y, c&#xE1;c b&#x1EA1;n ch&#x1EC9; c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng Java &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng &#x1EE9;ng d&#x1EE5;ng Android hay Objective-C &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng &#x1EE9;ng d&#x1EE5;ng iOS th&#xEC; ng&#xE0;y nay, c&#xE1;c b&#x1EA1;n ch&#x1EC9; c&#x1EA7;n bi&#x1EBF;t m&#x1ED9;t ng&#xF4;n ng&#x1EEF; b&#x1EA5;t k&#x1EF3; c&#x169;ng c&#xF3; th&#x1EC3; x&#xE2;y d&#x1EF1;ng &#x111;&#x1B0;&#x1EE3;c &#x1EE9;ng d&#x1EE5;ng mobile s&#x1EED; d&#x1EE5;ng ng&#xF4;n ng&#x1EEF; &#x111;&#xF3;. Ng&#xE0;y c&#xE0;ng c&#xF3; nhi&#x1EC1;u framework h&#x1ED7; tr&#x1EE3; vi&#x1EC7;c l&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng mobile m&#x1ED9;t c&#xE1;ch nhanh ch&#xF3;ng ph&#x1EA3;i k&#x1EC3; &#x111;&#x1EBF;n nh&#x1B0; React Native, Flutter, NativeScript,...</p><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-19.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><p>Tuy nhi&#xEA;n &#x111;&#x1ED1;i v&#x1EDB;i nh&#x1EEF;ng b&#x1EA1;n y&#xEA;u th&#xED;ch Microsoft, y&#xEA;u th&#xED;ch C#, y&#xEA;u th&#xED;ch Visual Studio th&#xEC; v&#x1EAB;n lu&#xF4;n c&#xF3; m&#x1ED9;t s&#x1EF1; l&#x1EF1;a ch&#x1ECD;n h&#xE0;ng &#x111;&#x1EA7;u &#x111;&#xF3; l&#xE0; Xamarin. B&#xE0;i vi&#x1EBF;t d&#x1B0;&#x1EDB;i &#x111;&#xE2;y m&#xEC;nh s&#x1EBD; chia s&#x1EBB; nh&#x1EEF;ng hi&#x1EC3;u bi&#x1EBF;t c&#x1EE7;a m&#xEC;nh v&#x1EC1; Xamarin trong seri <a href="https://blog.arrow-tech.vn/tag/xamarin/">L&#x1EAD;p tr&#xEC;nh Xamarin</a>. Hy v&#x1ECD;ng s&#x1EBD; gi&#xFA;p c&#xE1;c b&#x1EA1;n ph&#x1EA7;n n&#xE0;o trong qu&#xE1; tr&#xEC;nh h&#x1ECD;c t&#x1EAD;p v&#xE0; l&#xE0;m vi&#x1EC7;c v&#x1EDB;i Xamarin.</p><p><em>OK! Let&apos;s GO!!!</em></p><p><strong>Xamarin l&#xE0; g&#xEC;</strong></p><!--kg-card-begin: markdown--><p>Xamarin l&#xE0; m&#x1ED9;t framework &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng c&#xE1;c &#x1EE9;ng d&#x1EE5;ng di &#x111;&#x1ED9;ng &#x111;a n&#x1EC1;n t&#x1EA3;ng &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o ra b&#x1EDF;i h&#xE3;ng ph&#x1EA7;n m&#x1EC1;m di &#x111;&#x1ED9;ng c&#xF9;ng t&#xEA;n th&#xE0;nh l&#x1EAD;p v&#xE0;o ng&#xE0;y 16 th&#xE1;ng 5 n&#x103;m 2011 b&#x1EDF;i c&#xE1;c k&#x1EF9; s&#x1B0; &#x111;&#xE3; t&#x1EA1;o ra Mono, Mono cho Android v&#xE0; MonoTouch v&#x1EDB;i h&#x1A1;n 500 ngh&#xEC;n nh&#xE2;n l&#x1EF1;c. H&#xE3;ng n&#xE0;y s&#x1EED; d&#x1EE5;ng ng&#xF4;n ng&#x1EEF; C# &#x111;&#x1EC3; vi&#x1EBF;t c&#xE1;c &#x1EE9;ng d&#x1EE5;ng ch&#x1EA1;y tr&#xEA;n Mac, Android, &#xFD; t&#x1B0;&#x1EDF;ng tri&#x1EC3;n khai c&#xE1;c &#x1EE9;ng d&#x1EE5;ng &#x111;a n&#x1EC1;n t&#x1EA3;ng s&#x1EED; d&#x1EE5;ng Common Language Infrastructure (CLI) v&#xE0; Common Language Specifications (th&#x1B0;&#x1EDD;ng &#x111;&#x1B0;&#x1EE3;c g&#x1ECD;i l&#xE0; Microsoft .NET).<br>
&#x110;&#x1EBF;n th&#xE1;ng 11/2013, Microsoft &#x111;&#xE3; mua l&#x1EA1;i v&#xE0; t&#xED;ch h&#x1EE3;p ch&#x1EA1;y tr&#xEA;n m&#xF4;i tr&#x1B0;&#x1EDD;ng Windows 8. V&#x1EDB;i c&#x1A1; s&#x1EDF; m&#xE3; ngu&#x1ED3;n m&#x1EDF; c&#x1EE7;a C#, c&#xE1;c l&#x1EAD;p tr&#xEC;nh vi&#xEA;n c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng c&#xE1;c c&#xF4;ng c&#x1EE5; Xamarin &#x111;&#x1EC3; vi&#x1EBF;t c&#xE1;c &#x1EE9;ng d&#x1EE5;ng native Android, iOS v&#xE0; Windows v&#x1EDB;i giao di&#x1EC7;n ng&#x1B0;&#x1EDD;i d&#xF9;ng native v&#xE0; s&#x1EF1; chia s&#x1EBB; code tr&#xEA;n nhi&#x1EC1;u n&#x1EC1;n t&#x1EA3;ng, bao g&#x1ED3;m Windows v&#xE0; macOS.<br>
Theo nh&#x1B0; Xamarin c&#xF4;ng b&#x1ED1;, h&#x1A1;n 1.4 tri&#x1EC7;u l&#x1EAD;p tr&#xEC;nh vi&#xEA;n &#x111;ang s&#x1EED; d&#x1EE5;ng s&#x1EA3;n ph&#x1EA9;m c&#x1EE7;a Xamarin &#x1EDF; 120 qu&#x1ED1;c gia tr&#xEA;n to&#xE0;n th&#x1EBF; gi&#x1EDB;i t&#xED;nh &#x111;&#x1EBF;n th&#xE1;ng 4 n&#x103;m 2017</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-9.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"><figcaption>Qu&#xE1; tr&#xEC;nh ph&#xE1;t tri&#x1EC3;n c&#x1EE7;a Xamarin</figcaption></figure><!--kg-card-begin: markdown--><p>C&#xF4;ng c&#x1EE5; Xamarin &#x111;&#x1B0;&#x1EE3;c Microsoft gi&#x1EDB;i thi&#x1EC7;u v&#xE0;o th&#x1ECB; tr&#x1B0;&#x1EDD;ng Vi&#x1EC7;t Nam v&#xE0;o 18/04/2014 trong cho c&#x1ED9;ng &#x111;&#x1ED3;ng c&#xE1;c gi&#x1EA3;ng vi&#xEA;n c&#xE1;c tr&#x1B0;&#x1EDD;ng C&#x110;, &#x110;H t&#x1EA1;i TPHCM v&#xE0; &#x111;&#x1B0;&#x1EE3;c chuy&#x1EC3;n giao c&#xE1;c t&#xE0;i li&#x1EC7;u, b&#x1EA3;n quy&#x1EC1;n v&#x1EDB;i gi&#xE1; &#x1B0;u &#x111;&#xE3;i cho c&#xE1;c sinh vi&#xEA;n tr&#xEA;n n&#x1EC1;n Microsoft Visual Studio v&#xE0; &#x111;&#x1B0;&#x1EE3;c chuy&#xEA;n gia Microsoft demo l&#x1EAD;p tr&#xEC;nh Xamarin &#x111;&#x1EC3; app ch&#x1EA1;y tr&#xEA;n m&#xF4;i tr&#x1B0;&#x1EDD;ng iOS, Android, Windows Phone v&#xE0; Windows 8.1 v&#x1EDB;i c&#xE1;c Tools kh&#xE1;c nhau.<br>
T&#x1EA1;i s&#x1EF1; ki&#x1EC7;n Microsoft Build 2016, Microsoft c&#xF4;ng b&#xE1;o h&#x1ECD; s&#x1EBD; m&#xE3; ngu&#x1ED3;n m&#x1EDF; Xamarin SDK v&#xE0; cung c&#x1EA5;p c&#xE1;c c&#xF4;ng c&#x1EE5; &#x111;&#x1EC3; ph&#xE1;t tri&#x1EC3;n &#x1EE9;ng d&#x1EE5;ng s&#x1EED; d&#x1EE5;ng Xamarin mi&#x1EC5;n ph&#xED; tr&#xEA;n Visual Studio.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-10.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"><figcaption>T&#x1EA5;t c&#x1EA3; m&#x1ECD;i th&#x1EE9; l&#xE0;m &#x111;&#x1B0;&#x1EE3;c v&#x1EDB;i Java Android hay Swift iOS th&#xEC; &#x111;&#x1EC1;u l&#xE0;m &#x111;&#x1B0;&#x1EE3;c v&#x1EDB;i C# v&#xE0; VS v&#x1EDB;i Xamarin</figcaption></figure><p><strong>Xamarin.Forms</strong></p><!--kg-card-begin: markdown--><p>Xamarin.Forms l&#xE0; m&#x1ED9;t c&#xF4;ng c&#x1EE5; gi&#xFA;p code giao di&#x1EC7;n ng&#x1B0;&#x1EDD;i d&#xF9;ng c&#xF3; th&#x1EC3; &#x111;&#x1B0;&#x1EE3;c chia s&#x1EBB; tr&#xEA;n c&#xE1;c &#x1EE9;ng d&#x1EE5;ng iOS, Android v&#xE0; Universal Windows Platform v&#x1EDB;i 100% C#. Xamarin.Forms bao g&#x1ED3;m h&#x1A1;n 40 &#x111;i&#x1EC1;u khi&#x1EC3;n v&#xE0; b&#x1ED1; c&#x1EE5;c, &#x111;&#x1B0;&#x1EE3;c &#xE1;nh x&#x1EA1; t&#x1EDB;i c&#xE1;c &#x111;i&#x1EC1;u khi&#x1EC3;n g&#x1ED1;c trong qu&#xE1; tr&#xEC;nh ch&#x1EA1;y. N&#xF3; h&#x1ED7; tr&#x1EE3; c&#xE1;c n&#x1EC1;n t&#x1EA3;ng sau:</p>
<ul>
<li>Android 4.4 +</li>
<li>iOS 8+</li>
<li>Windows 10 Universal Windows Platform<br>
Ngo&#xE0;i ra, Xamarin Forms c&#xF2;n h&#x1ED7; tr&#x1EE3; c&#xE1;c n&#x1EC1;n t&#x1EA3;ng d&#x1B0;&#x1EDB;i &#x111;&#xE2;y nh&#x1B0;ng v&#x1EAB;n &#x111;ang &#x1EDF; ch&#x1EBF; &#x111;&#x1ED9; Preview ho&#x1EB7;c do b&#xEA;n th&#x1EE9; ba ph&#xE1;t tri&#x1EC3;n:</li>
<li>Samsung Tizen</li>
<li>macOS</li>
<li>GTK#</li>
<li>WPF</li>
</ul>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-11.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"><figcaption>Danh s&#xE1;ch c&#xE1;c n&#x1EC1;n t&#x1EA3;ng Xamarin h&#x1ED7; tr&#x1EE3;</figcaption></figure><!--kg-card-begin: markdown--><p>D&#x1B0;&#x1EDB;i &#x111;&#xE2;y l&#xE0; h&#xEC;nh &#x1EA3;nh so s&#xE1;nh v&#x1EC1; chia s&#x1EBB; code c&#x1EE7;a c&#xE1;ch s&#x1EED; d&#x1EE5;ng Xamarin truy&#x1EC1;n th&#x1ED1;ng v&#xE0; s&#x1EED; d&#x1EE5;ng Xamarin.Forms. R&#xF5; r&#xE0;ng khi s&#x1EED; d&#x1EE5;ng Xamarin.Forms, ch&#xFA;ng ta &#x111;&#xE3; s&#x1EED; d&#x1EE5;ng &#x111;&#x1B0;&#x1EE3;c h&#x1EA7;u h&#x1EBF;t code chung cho to&#xE0;n b&#x1ED9; &#x1EE9;ng d&#x1EE5;ng.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-12.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><!--kg-card-begin: markdown--><p>Giao di&#x1EC7;n c&#xE1;c &#x1EE9;ng d&#x1EE5;ng s&#x1EED; d&#x1EE5;ng Xamarin &#x111;&#x1B0;&#x1EE3;c vi&#x1EBF;t trong m&#x1ED9;t file XAML. N&#xF3; c&#xF3; c&#x1EA5;u tr&#xFA;c c&#x1EE7;a m&#x1ED9;t file XML, kh&#xE1; gi&#x1ED1;ng v&#x1EDB;i Winform hay XML c&#x1EE7;a Android.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-13.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><!--kg-card-begin: markdown--><p>V&#x1EDB;i 1 &#x111;o&#x1EA1;n code nh&#x1B0; n&#xE0;y ch&#xFA;ng ta c&#xF3; th&#x1EC3; build ra 3 n&#x1EC1;n t&#x1EA3;ng kh&#xE1;c nhau:</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-14.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><p><strong>&#x1AF;u &#x111;i&#x1EC3;m c&#x1EE7;a Xamarin</strong></p><p><em>Chia s&#x1EBB; code &#x1EDF; m&#x1ECD;i n&#x1A1;i</em></p><!--kg-card-begin: markdown--><p>Khi vi&#x1EBF;t m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng s&#x1EED; d&#x1EE5;ng b&#x1ED9; c&#xF4;ng c&#x1EE5; c&#x1EE7;a Xamarin th&#xEC; v&#x1EC1; c&#x1A1; b&#x1EA3;n b&#x1EA1;n &#x111;ang s&#x1EED; d&#x1EE5;ng m&#x1ED9;t l&#x1EDB;p tr&#x1EEB;u t&#x1B0;&#x1EE3;ng ph&#xED;a tr&#xEA;n c&#xE1;c SDK th&#x1EF1;c s&#x1EF1; c&#x1EE7;a iOS v&#xE0; Android. &#x110;i&#x1EC1;u n&#xE0;y c&#xF3; ngh&#x129;a l&#xE0; b&#x1EA1;n s&#x1EBD; thu &#x111;&#x1B0;&#x1EE3;c k&#x1EBF;t qu&#x1EA3; l&#xE0; m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng native ho&#xE0;n to&#xE0;n v&#x1EDB;i giao di&#x1EC7;n d&#xF9;ng native tr&#xEA;n m&#x1ED7;i n&#x1EC1;n t&#x1EA3;ng.<br>
Khi b&#x1EA1;n t&#x1EA1;o &#x1EE9;ng d&#x1EE5;ng tr&#xEA;n Xamarin, b&#x1EA1;n s&#x1EED; d&#x1EE5;ng c&#xF9;ng ng&#xF4;n ng&#x1EEF;, API v&#xE0; c&#x1EA5;u tr&#xFA;c d&#x1EEF; li&#x1EC7;u &#x111;&#x1EC3; chia s&#x1EBB; trung b&#xEC;nh 75% code tr&#xEA;n t&#x1EA5;t c&#x1EA3; c&#xE1;c n&#x1EC1;n t&#x1EA3;ng &#x111;i&#x1EC7;n tho&#x1EA1;i di &#x111;&#x1ED9;ng. Logic &#x1EE9;ng d&#x1EE5;ng n&#xE0;y c&#xF3; th&#x1EC3; d&#x1EC5; d&#xE0;ng chia s&#x1EBB; tr&#xEA;n nhi&#x1EC1;u n&#x1EC1;n t&#x1EA3;ng. Qua &#x111;&#xF3; c&#xF3; th&#x1EC3; gi&#x1EA3;m &#x111;&#xE1;ng k&#x1EC3; chi ph&#xED; v&#xE0; th&#x1EDD;i gian ph&#xE1;t tri&#x1EC3;n &#x1EE9;ng d&#x1EE5;ng di &#x111;&#x1ED9;ng cho 3 n&#x1EC1;n t&#x1EA3;ng ph&#x1ED5; bi&#x1EBF;n nh&#x1EA5;t.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-17.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><p><em>Performance nh&#x1B0; native</em></p><!--kg-card-begin: markdown--><p>Kh&#xF4;ng gi&#x1ED1;ng nh&#x1B0; ph&#x1B0;&#x1A1;ng ph&#xE1;p k&#x1EBF;t h&#x1EE3;p truy&#x1EC1;n th&#x1ED1;ng d&#x1EF1;a tr&#xEA;n c&#xE1;c c&#xF4;ng ngh&#x1EC7; web, m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng &#x111;a n&#x1EC1;n t&#x1EA3;ng &#x111;&#x1B0;&#x1EE3;c x&#xE2;y d&#x1EF1;ng v&#x1EDB;i Xamarin c&#x169;ng c&#xF3; th&#x1EC3; xem v&#xE0;o h&#xE0;ng native. C&#xE1;c s&#x1ED1; li&#x1EC7;u performances l&#xE0; t&#x1B0;&#x1A1;ng &#x111;&#x1B0;&#x1A1;ng khi so s&#xE1;nh v&#x1EDB;i c&#xE1;c s&#x1ED1; li&#x1EC7;u performance c&#x1EE7;a Java, Kotlin cho Android v&#xE0; Objective-C ho&#x1EB7;c Swift cho &#x1EE9;ng d&#x1EE5;ng ph&#xE1;t tri&#x1EC3;n &#x1EE9;ng d&#x1EE5;ng iOS native. H&#x1A1;n th&#x1EBF; n&#x1EEF;a, performance li&#xEA;n t&#x1EE5;c &#x111;&#x1B0;&#x1EE3;c c&#x1EA3;i thi&#x1EC7;n &#x111;&#x1EC3; ph&#xF9; h&#x1EE3;p ho&#xE0;n to&#xE0;n v&#x1EDB;i ti&#xEA;u chu&#x1EA9;n c&#x1EE7;a l&#x1EAD;p tr&#xEC;nh native. N&#x1EC1;n t&#x1EA3;ng Xamarin cung c&#x1EA5;p l&#xE0; gi&#x1EA3;i ph&#xE1;p &#x111;&#x1EC3; testing v&#xE0; theo d&#xF5;i ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a &#x1EE9;ng d&#x1EE5;ng. Xamarin Test Cloud k&#x1EBF;t h&#x1EE3;p v&#x1EDB;i c&#xF4;ng c&#x1EE5; Xamarin Test Recorder cho ph&#xE9;p b&#x1EA1;n ch&#x1EA1;y c&#xE1;c UI test t&#x1EF1; &#x111;&#x1ED9;ng v&#xE0; x&#xE1;c &#x111;&#x1ECB;nh c&#xE1;c v&#x1EA5;n &#x111;&#x1EC1; v&#x1EC1; performance tr&#x1B0;&#x1EDB;c khi &#x1EE9;ng d&#x1EE5;ng release. Tuy nhi&#xEA;n, d&#x1ECB;ch v&#x1EE5; n&#xE0;y c&#xF3; t&#xED;nh ph&#xED;.<br>
H&#xEC;nh d&#x1B0;&#x1EDB;i &#x111;&#xE2;y cho ch&#xFA;ng ta th&#x1EA5;y th&#x1EDD;i gian m&#x1EDF; m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng HelloWorld b&#x1EB1;ng &#x1EE9;ng d&#x1EE5;ng native, &#x1EE9;ng d&#x1EE5;ng vi&#x1EBF;t b&#x1EB1;ng Xamarin Native, &#x1EE9;ng d&#x1EE5;ng vi&#x1EBF;t b&#x1EB1;ng Xamarin.Forms:</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.arrow-tech.vn/content/images/2018/12/image-18.png" class="kg-image" alt="[Seri] L&#x1EAD;p tr&#xEC;nh Xamarin - B&#xE0;i 1: T&#x1ED5;ng quan v&#x1EC1; Xamarin" loading="lazy"></figure><p></p><p><em>M&#x1ED9;i s&#x1ED1; &#x1B0;u &#x111;i&#x1EC3;m kh&#xE1;c</em></p><!--kg-card-begin: markdown--><p>M&#x1ED9;t s&#x1ED1; &#x111;i&#x1EC3;m c&#x1ED9;ng cho Xamarin nh&#x1B0;:</p>
<ul>
<li>C&#xF3; kh&#x1EA3; n&#x103;ng l&#x1EF1;a ch&#x1ECD;n UI layout</li>
<li>T&#xED;ch h&#x1EE3;p OAuth</li>
<li>T&#xED;ch h&#x1EE3;p REST APIs t&#x1EEB; xa</li>
<li>C&#xF4;ng ngh&#x1EC7; d&#x1EAB;n &#x111;&#x1B0;&#x1EDD;ng v&#xE0; x&#x1EED; l&#xFD; t&#xED;n hi&#x1EC7;u th&#x1EDD;i gian th&#x1EF1;c cho &#x1EE9;ng d&#x1EE5;ng &#x111;&#x1ECB;nh v&#x1ECB;</li>
<li>T&#xED;ch h&#x1EE3;p m&#x1EA1;ng x&#xE3; h&#x1ED9;i</li>
<li>C&#xF3; b&#x1ED9; c&#x1A1; s&#x1EDF; d&#x1EEF; li&#x1EC7;u SQLite nh&#xFA;ng</li>
<li>Th&#x1B0; vi&#x1EC7;n XAML cho ph&#xE9;p x&#xE2;y d&#x1EF1;ng m&#x1ED9;t lo&#x1EA1;t &#x1EE9;ng d&#x1EE5;ng</li>
<li>H&#x1ED7; tr&#x1EE3; data binding</li>
</ul>
<!--kg-card-end: markdown--><p><strong>Nh&#x1B0;&#x1EE3;c &#x111;i&#x1EC3;m c&#x1EE7;a Xamarin</strong></p><p><em>&#x1EE8;ng d&#x1EE5;ng th&#x1EF1;c hi&#x1EC7;n ch&#x1EAD;m h&#x1A1;n v&#xE0; y&#xEA;u c&#x1EA7;u nhi&#x1EC1;u dung l&#x1B0;&#x1EE3;ng h&#x1A1;n tr&#xEA;n thi&#x1EBF;t b&#x1ECB;</em></p><!--kg-card-begin: markdown--><p>&#x1EE8;ng d&#x1EE5;ng Xamarin l&#x1EDB;n h&#x1A1;n, n&#x1EB7;ng h&#x1A1;n so v&#x1EDB;i &#x1EE9;ng d&#x1EE5;ng native. So s&#xE1;nh v&#x1EDB;i &#x1EE9;ng d&#x1EE5;ng native n&#xF3; chi&#x1EBF;m nhi&#x1EC1;u h&#x1A1;n v&#xE0;i Mb so v&#x1EDB;i Java/Objective C t&#x1B0;&#x1A1;ng &#x1EE9;ng. K&#xED;ch th&#x1B0;&#x1EDB;c c&#x1EE7;a m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng code b&#x1EB1;ng xamarin l&#xE0; 3Mb, trong khi code b&#x1EB1;ng Objective C ch&#x1EC9; chi&#x1EBF;m 172 Kb. C&#xE0;ng s&#x1EED; d&#x1EE5;ng nhi&#x1EC1;u API, c&#xE0;ng nhi&#x1EC1;u l&#x1B0;u tr&#x1EEF; b&#x1ECB; chi&#x1EBF;m tr&#xEA;n thi&#x1EBF;t b&#x1ECB;.</p>
<!--kg-card-end: markdown--><p><em>Khuy&#x1EBF;t &#x111;i&#x1EC3;m c&#x1EE7;a AOT Compiler</em></p><!--kg-card-begin: markdown--><p>Xamarin Forms c&#x169;ng c&#xF3; nh&#x1EEF;ng khuy&#x1EBF;t &#x111;i&#x1EC3;m AOT compliler. N&#xF3; kh&#xF4;ng &#x111;&#x1B0;&#x1EE3;c complie c&#xE1;c &#x111;o&#x1EA1;n code g&#x1ECD;n g&#xE0;ng nh&#x1B0; Xcode. H&#x1EA1;n ch&#x1EBF; c&#x1EE7;a Xamarin &#x1EA3;nh h&#x1B0;&#x1EDF;ng &#x111;&#x1EBF;n c&#x1EA3; ph&#xE1;t tri&#x1EC3;n, test t&#x1EA3;i app l&#xEA;n store. H&#x1EA1;n ch&#x1EBF; ch&#xED;nh &#x111;&#x1ED1;i v&#x1EDB;i iOS l&#xE0; n&#xF3; kh&#xF4;ng h&#x1ED7; tr&#x1EE3; sinh code t&#x1EF1; &#x111;&#x1ED9;ng. Visual Studio biuld code l&#xE2;u. C&#xE1;i n&#xE0;y t&#x1EA5;t c&#x1EA3; c&#xE1;c l&#x1EAD;p tr&#xEC;nh vi&#xEA;n Xamarin &#x111;&#x1EC1;u &#x111;ang ph&#x1EA3;i s&#x1ED1;ng chung v&#x1EDB;i l&#x169;, m&#x1ED9;t l&#x1EA7;n build s&#x1EBD; m&#x1EA5;t r&#x1EA5;t l&#xE2;u t&#x1EEB; 3 &#x111;&#x1EBF;n 10 ph&#xFA;t cho solution v&#x1EDB;i 30 project<br>
&#x110;&#xF4;i l&#xFA;c th&#xF4;ng b&#xE1;o l&#x1ED7;i kh&#xF4;ng r&#xF5; r&#xE0;ng ch&#x1EE7; y&#x1EBF;u tr&#xEA;n Android v&#xEC; n&#xF3; l&#xE0; 1 c&#xF4;ng ngh&#x1EC7; m&#x1EDB;i n&#xEA;n v&#x1EAB;n ch&#x1B0;a &#x111;&#x1B0;&#x1EE3;c ho&#xE0;n ho&#x1EA3;n mong r&#x1EB1;ng Microsoft s&#x1EBD; fix trong t&#x1B0;&#x1A1;ng lai.</p>
<!--kg-card-end: markdown--><p><em>C&#x1ED9;ng &#x111;&#x1ED3;ng h&#x1ED7; tr&#x1EE3; &#xED;t</em></p><!--kg-card-begin: markdown--><p>C&#x1ED9;ng &#x111;&#x1ED3;ng Xamarin &#xED;t h&#x1A1;n so v&#x1EDB;i c&#x1ED9;ng &#x111;&#x1ED3;ng c&#x1EE7;a iOS hay Android n&#xEA;n &#x111;&#x1EC3; t&#xEC;m ki&#x1EBF;m &#x111;&#x1B0;&#x1EE3;c 1 developer Xamarin c&#xF3; kinh nghi&#x1EC7;m l&#xE0; chuy&#x1EC7;n kh&#xF4;ng d&#x1EC5; d&#xE0;ng g&#xEC; d&#xF9; Xamarin l&#xE0; n&#x1EC1;n t&#x1EA3;ng &#x111;&#x1B0;&#x1EE3;c ph&#xE1;t tri&#x1EC3;n nh&#x1EDD; s&#x1EF1; h&#x1ED7; tr&#x1EE3; t&#x1EEB; Microsoft. Theo nhi&#x1EC1;u ngu&#x1ED3;n th&#xF4;ng tin, c&#x1ED9;ng &#x111;&#x1ED3;ng Xamarin chi&#x1EBF;m 10% c&#x1ED9;ng &#x111;&#x1ED9;ng l&#x1EAD;p tr&#xEC;nh mobile to&#xE0;n c&#x1EA7;u d&#x1EF1;a tr&#xEA;n th&#x1EF1;c t&#x1EBF; l&#xE0; n&#x1EC1;n t&#x1EA3;ng n&#xE0;y cung c&#x1EA5;p t&#x1ED1;i &#x111;a h&#x1ED7; tr&#x1EE3; cho c&#xE1;c developer. C&#x1EE5; th&#x1EC3;, c&#xF3; m&#x1ED9;t platform gi&#xE1;o d&#x1EE5;c chuy&#xEA;n bi&#x1EC7;t t&#x1EA1;i &#x110;H Xamarin, cung c&#x1EA5;p ki&#x1EBF;n th&#x1EE9;c v&#xE0; kho&#xE1; hu&#x1EA5;n luy&#x1EC7;n cho nh&#x1EEF;ng ai m&#x1EDB;i ti&#x1EBF;p c&#x1EAD;n c&#xF4;ng ngh&#x1EC7; n&#xE0;y. K&#x1EBF;t qu&#x1EA3; l&#xE0; learning curve c&#x1EE7;a 1 engineer C#/.Net kinh nghi&#x1EC7;m s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c t&#x1ED1;i thi&#x1EC3;u h&#xF3;a.</p>
<!--kg-card-end: markdown--><p><strong>K&#x1EBF;t lu&#x1EAD;n</strong></p><p>V&#x1EAD;y l&#xE0; m&#xEC;nh &#x111;&#xE3; gi&#x1EDB;i thi&#x1EC7;u v&#x1EDB;i c&#xE1;c b&#x1EA1;n m&#x1ED9;t c&#xE1;ch t&#x1ED5;ng quan v&#x1EC1; Xamarin. &#x1EDE; b&#xE0;i vi&#x1EBF;t ti&#x1EBF;p theo m&#xEC;nh s&#x1EBD; gi&#x1EDB;i thi&#x1EC7;u c&#x1EE5; th&#x1EC3; v&#x1EC1; c&#xE1;c th&#xE0;nh ph&#x1EA7;n trong gia &#x111;&#xEC;nh Xamarin. C&#xE1;c b&#x1EA1;n h&#xE3;y &#x111;&#xF3;n ch&#x1EDD; nh&#xE9;!</p>]]></content:encoded></item><item><title><![CDATA[Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><strong>1	T&#x1ED5;ng quan</strong></p>
<p>Cloud Vision API l&#xE0; b&#x1ED9; API &#x111;&#x1B0;&#x1EE3;c Google cung c&#x1EA5;p gi&#xFA;p c&#xE1;c l&#x1EAD;p tr&#xEC;nh vi&#xEA;n d&#x1EC5; d&#xE0;ng s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; detect</p>]]></description><link>https://blog.arrow-tech.vn/detect-labels-faces-and-landmarks-in-images-with-the-cloud-vision-api/</link><guid isPermaLink="false">63915acd7a2f410001205db8</guid><category><![CDATA[Google Cloud]]></category><category><![CDATA[Vision]]></category><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Wed, 03 Oct 2018 03:28:02 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/12/Picture27.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.arrow-tech.vn/content/images/2018/12/Picture27.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API"><p><strong>1	T&#x1ED5;ng quan</strong></p>
<p>Cloud Vision API l&#xE0; b&#x1ED9; API &#x111;&#x1B0;&#x1EE3;c Google cung c&#x1EA5;p gi&#xFA;p c&#xE1;c l&#x1EAD;p tr&#xEC;nh vi&#xEA;n d&#x1EC5; d&#xE0;ng s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; detect &#x1EA3;nh ch&#x1EC9; b&#x1EB1;ng m&#x1ED9;t request &#x111;&#x1A1;n gi&#x1EA3;n. B&#x1EA1;n kh&#xF4;ng c&#x1EA7;n ph&#x1EA3;i bi&#x1EBF;t Machine Learning c&#x169;ng c&#xF3; th&#x1EC3; nhanh ch&#xF3;ng t&#x1EA1;o &#x111;&#x1B0;&#x1EE3;c &#x1EE9;ng d&#x1EE5;ng detect &#x1EA3;nh b&#x1EB1;ng c&#xE1;ch s&#x1EED; d&#x1EE5;ng Cloud Vision API.</p>
<p>&quot;B&#x1EA1;n c&#x1EE9; vi&#x1EC7;c ph&#xE1;t tri&#x1EC3;n &#x1EE9;ng d&#x1EE5;ng, detect image c&#x1EE9; &#x111;&#x1EC3; Cloud Vision API lo!!!&quot;</p>
<p><strong>1.1 M&#x1EE5;c &#x111;&#xED;ch</strong></p>
<p>B&#xE0;i vi&#x1EBF;t s&#x1EBD; gi&#xFA;p b&#x1EA1;n bi&#x1EBF;t c&#xE1;c s&#x1EED; d&#x1EE5;ng Cloud Vision API &#x111;&#x1EC3; nh&#x1EAD;n d&#x1EA1;ng &#x1EA3;nh v&#x1EDB;i c&#xE1;c ch&#x1EE9;c n&#x103;ng: nh&#x1EAD;n d&#x1EA1;ng n&#x1ED9;i dung c&#x1EE7;a b&#x1EE9;c &#x1EA3;nh, nh&#x1EAD;n d&#x1EA1;ng khu&#xF4;n m&#x1EB7;t ng&#x1B0;&#x1EDD;i, nh&#x1EAD;n d&#x1EA1;ng c&#xF4;ng tr&#xEC;nh n&#x1ED5;i ti&#x1EBF;ng, nh&#x1EAD;n d&#x1EA1;ng ch&#x1EEF; vi&#x1EBF;t,...<br>
M&#xEC;nh s&#x1EBD; h&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE1;c b&#x1EA1;n s&#x1EED; d&#x1EE5;ng theo 2 c&#xE1;ch:</p>
<ul>
<li>C&#xE1;ch 1: S&#x1EED; d&#x1EE5;ng curl &#x111;&#x1EC3; t&#x1EA1;o request t&#x1EDB;i Cloud Vision API tr&#xEA;n terminal</li>
<li>C&#xE1;ch 2: S&#x1EED; d&#x1EE5;ng Postman &#x111;&#x1EC3; t&#x1EA1;o request t&#x1EDB;i Cloud Vision API<br>
Cu&#x1ED1;i b&#xE0;i vi&#x1EBF;t m&#xEC;nh s&#x1EBD; demo m&#x1ED9;t app Android s&#x1EED; d&#x1EE5;ng Cloud Vision API &#x111;&#x1EC3; nh&#x1EAD;n di&#x1EC7;n n&#x1ED9;i dung b&#x1EE9;c &#x1EA3;nh.</li>
</ul>
<p><strong>1.2 C&#xF4;ng c&#x1EE5; c&#x1EA7;n thi&#x1EBF;t</strong></p>
<ul>
<li>Project Google Cloud Platform: B&#x1EA1;n c&#x1EA7;n c&#xF3; t&#xE0;i kho&#x1EA3;n Google Cloud &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c th&#xEA;m th&#xF4;ng tin thanh to&#xE1;n (th&#x1EBB; VISA). N&#x1EBF;u b&#x1EA1;n ch&#x1B0;a c&#xF3; th&#xEC; c&#xF3; th&#x1EC3; tham gia Qwiklabs &#x111;&#x1EC3; nh&#x1EAD;n t&#xE0;i kho&#x1EA3;n s&#x1EED; d&#x1EE5;ng trong 45 ph&#xFA;t (<a href="https://qwiklabs.com/focuses/1841?parent=catalog&amp;ref=blog.arrow-tech.vn">https://qwiklabs.com/focuses/1841?parent=catalog</a>)<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture15.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"></li>
<li>Tr&#xEC;nh duy&#x1EC7;t Chrome ho&#x1EB7;c Firefox</li>
</ul>
<p><strong>2	C&#xE0;i &#x111;&#x1EB7;t chung</strong></p>
<p>&#x110;&#x1EA7;u ti&#xEA;n, b&#x1EA1;n m&#x1EDF; project c&#x1EE7;a b&#x1EA1;n. N&#x1EBF;u b&#x1EA1;n ch&#x1B0;a c&#xF3; th&#xEC; hay t&#x1EA1;o m&#x1ED9;t project m&#x1EDB;i nh&#xE9;.<br>
Giao di&#x1EC7;n project s&#x1EBD; nh&#x1B0; sau:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture16.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"></p>
<p><strong>2.1	Terminal</strong></p>
<p>&#x110;&#x1EC3; m&#x1EDF; terminal, b&#x1EA1;n nh&#x1EA5;n v&#xE0;o bi&#x1EC3;u t&#x1B0;&#x1EE3;ng d&#x1B0;&#x1EDB;i &#x111;&#xE2;y tr&#xEA;n thanh navigation:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture17.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
Sau &#x111;&#xF3; b&#x1EA1;n ch&#x1ECD;n START CLOUD SHELL &#x111;&#x1EC3; m&#x1EDF; terminal v&#xE0; vui l&#xF2;ng &#x111;&#x1EE3;i m&#x1ED9;t ch&#xFA;t &#x111;&#x1EC3; tr&#xEC;nh duy&#x1EC7;t c&#x1EE7;a b&#x1EA1;n k&#x1EBF;t n&#x1ED1;i v&#x1EDB;i server c&#x1EE7;a Google.<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture18.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
M&#xEC;nh s&#x1EBD; gi&#x1EDB;i thi&#x1EC7;u qua m&#x1ED9;t ch&#xFA;t v&#x1EC1; terminal n&#xE0;y. Terminal n&#xE0;y th&#x1EF1;c ch&#x1EA5;t gi&#x1ED1;ng nh&#x1B0; terminal (CMD, Windows Power Shell) tr&#xEA;n m&#xE1;y b&#x1EA1;n. Tr&#xEA;n &#x111;&#xF3; &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c Google c&#xE0;i &#x111;&#x1EB7;t s&#x1EB5;n c&#xE1;c m&#xF4;i tr&#x1B0;&#x1EDD;ng &#x111;&#x1EC3; b&#x1EA1;n s&#x1EED; d&#x1EE5;ng. B&#x1EA1;n c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng t&#x1EA5;t c&#x1EA3; c&#xE1;c l&#x1EC7;nh tr&#xEA;n ubuntu nh&#x1B0; tr&#xEA;n m&#xE1;y th&#x1EAD;t c&#x1EE7;a b&#x1EA1;n.<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture19.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
B&#x1EA1;n c&#x169;ng c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng tr&#x1EF1;c ti&#x1EBF;p Terminal th&#x1EAD;t tr&#xEA;n m&#xE1;y c&#x1EE7;a b&#x1EA1;n &#x111;&#x1EC3; th&#x1EF1;c h&#xE0;nh. Nh&#x1B0;ng b&#x1EA1;n c&#x1EA7;n ph&#x1EA3;i c&#xE0;i 1 s&#x1ED1; c&#xF4;ng c&#x1EE5; cho n&#xF3; n&#x1EBF;u ch&#x1B0;a c&#xF3; nh&#x1B0; curl, tr&#xEC;nh ch&#x1EC9;nh s&#x1EED;a v&#x103;n b&#x1EA3;n (nano, vim,...)</p>
<p><strong>2.2	API Key</strong></p>
<p>&#x110;&#x1EC3; s&#x1EED; d&#x1EE5;ng b&#x1EA5;t k&#x1EF3; d&#x1ECB;ch v&#x1EE5; n&#xE0;o c&#x1EE7;a Google, b&#x1EA1;n c&#x169;ng &#x111;&#x1EC1;u c&#x1EA7;n ph&#x1EA3;i c&#xF3; API Key.<br>
&#x110;&#x1EC3; t&#x1EA1;o API Key, b&#x1EA1;n v&#xE0;o menu ch&#x1ECD;n APIs &amp; Services r&#x1ED3;i ch&#x1ECD;n Credentials nh&#x1B0; h&#xEC;nh d&#x1B0;&#x1EDB;i &#x111;&#xE2;y:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture20.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
Sau &#x111;&#xF3; b&#x1EA1;n click Create credentials:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture21.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
Trong menu x&#x1ED5; xu&#x1ED1;ng, b&#x1EA1;n ch&#x1ECD;n API key:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture22.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
M&#x1ED9;t h&#x1ED9;p tho&#x1EA1;i hi&#x1EC7;n ra, b&#x1EA1;n ch&#x1ECD;n RESTRICT KEY &#x111;&#x1EC3; l&#x1B0;u l&#x1EA1;i.<br>
Ti&#x1EBF;p theo b&#x1EA1;n c&#x1EA7;n t&#x1EA1;o bi&#x1EBF;n m&#xF4;i tr&#x1B0;&#x1EDD;ng API_KEY &#x111;&#x1EC3; sau n&#xE0;y b&#x1EA1;n g&#x1ECD;i &#x111;&#x1EBF;n Cloud API th&#xEC; ch&#x1EC9; c&#x1EA7;n g&#x1ECD;i bi&#x1EBF;n &#x111;&#xF3; ra th&#xF4;i kh&#xF4;ng c&#x1EA7;n v&#xE0;o copy &#x111;o&#x1EA1;n key d&#xE0;i d&#xE0;i n&#xE0;y n&#x1EEF;a.<br>
&#x110;&#x1EC3; t&#x1EA1;o bi&#x1EBF;n m&#xF4;i tr&#x1B0;&#x1EDD;ng API_KEY, tr&#xEA;n terminal, b&#x1EA1;n g&#xF5;: export API_KEY=xxx<br>
(Trong &#x111;&#xF3; xxx l&#xE0; key m&#xE0; b&#x1EA1;n v&#x1EEB;a t&#x1EA1;o)<br>
B&#x1EA1;n c&#xF3; th&#x1EC3; check xem bi&#x1EBF;n &#x111;&#xF3; &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o &#x111;&#xFA;ng ch&#x1B0;a b&#x1EB1;ng l&#x1EC7;nh sau: echo $API_KEY<br>
Nh&#x1B0; v&#x1EAD;y &#x111;&#xE3; xong, ch&#xFA;ng ta chuy&#x1EC3;n sang b&#x1B0;&#x1EDB;c ti&#x1EBF;p theo.</p>
<p><strong>2.3	T&#x1EA1;o file request.json</strong></p>
<p>File request.json n&#xE0;y s&#x1EBD; l&#xE0; body c&#x1EE7;a request t&#x1EDB;i Cloud API &#x1EDF; b&#x1B0;&#x1EDB;c ti&#x1EBF;p theo.<br>
&#x110;&#x1EC3; t&#x1EA1;o file n&#xE0;y, tr&#xEA;n terminal c&#xE1;c b&#x1EA1;n g&#xF5; touch request.json<br>
&#x110;&#x1EC3; ch&#x1EC9;nh s&#x1EED;a c&#xE1;c b&#x1EA1;n c&#xF3; th&#x1EC3; d&#xF9;ng l&#x1EC7;nh: nano request.json<br>
File n&#xE0;y s&#x1EBD; c&#xF3; d&#x1EA1;ng json nh&#x1B0; sau:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture23.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
M&#xEC;nh s&#x1EBD; gi&#x1EA3;i th&#xED;ch m&#x1ED9;t s&#x1ED1; tr&#x1B0;&#x1EDD;ng trong file n&#xE0;y:</p>
<ul>
<li>requests: l&#xE0; m&#x1ED9;t m&#x1EA3;ng. Nh&#x1B0; v&#x1EAD;y Cloud API cho ph&#xE9;p b&#x1EA1;n c&#xF9;ng l&#xFA;c detect nhi&#x1EC1;u &#x1EA3;nh trong 1 request.</li>
<li>image: l&#xE0; &#x1EA3;nh c&#x1EE7;a b&#x1EA1;n. B&#x1EA1;n c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng 3 c&#xE1;ch:</li>
</ul>
<ul>
<li>C&#xE1;ch 1: D&#xF9;ng &#x1EA3;nh base64:<br>
B&#x1EA1;n c&#xF3; th&#x1EC3; v&#xE0;o c&#xE1;c trang gi&#xFA;p m&#xE3; h&#xF3;a &#x1EA3;nh c&#x1EE7;a b&#x1EA1;n d&#x1B0;&#x1EDB;i d&#x1EA1;ng base64, sau &#x111;&#xF3; b&#x1EA1;n copy &#x111;o&#x1EA1;n text k&#x1EBF;t qu&#x1EA3; &#x111;&#xF3; v&#xE0;o ph&#x1EA7;n value c&#x1EE7;a content nh&#x1B0; h&#xEC;nh sau:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture24.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
N&#x1EBF;u &#x111;o&#x1EA1;n text m&#xE0; c&#xF3; data:image/jpeg;base64, &#x1EDF; &#x111;&#x1EA7;u th&#xEC; b&#x1EA1;n nh&#x1EDB; b&#x1ECF; &#x111;i nh&#xE9;!</li>
<li>C&#xE1;ch 2: D&#xF9;ng Google Cloud Storage:<br>
Ph&#x1EA7;n n&#xE0;y kh&#xE1; ph&#x1EE9;c t&#x1EA1;p n&#xEA;n b&#x1EA1;n c&#xF3; th&#x1EC3; tham kh&#x1EA3;o t&#x1EA1;i link sau: <a href="https://cloud.google.com/vision/docs?ref=blog.arrow-tech.vn">https://cloud.google.com/vision/docs</a><br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture25.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"></li>
<li>C&#xE1;ch 3: D&#xF9;ng tr&#x1EF1;c ti&#x1EBF;p &#x111;&#x1B0;&#x1EDD;ng link &#x1EA3;nh<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture26.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"></li>
</ul>
<ul>
<li>features: l&#xE0; m&#x1ED9;t m&#x1EA3;ng c&#xE1;c thu&#x1ED9;c t&#xED;nh. V&#xED; d&#x1EE5; type l&#xE0; ki&#x1EC3;u detect, maxResults l&#xE0; s&#x1ED1; k&#x1EBF;t qu&#x1EA3; t&#x1ED1;i &#x111;a tr&#x1EA3; v&#x1EC1;,&#x2026;</li>
<li>type l&#xE0; ki&#x1EC3;u m&#xE0; b&#x1EA1;n mu&#x1ED1;n Google detect. Hi&#x1EC7;n t&#x1EA1;i, Google h&#x1ED7; tr&#x1EE3; c&#xE1;c ki&#x1EC3;u sau:</li>
</ul>
<ul>
<li>TEXT_DETECTION: nh&#x1EAD;n d&#x1EA1;ng text, c&#xF3; h&#x1ED7; tr&#x1EE3; d&#x1ECB;ch sang ng&#xF4;n ng&#x1EEF; kh&#xE1;c</li>
<li>DOCUMENT_TEXT_DETECTION: nh&#x1EAD;n d&#x1EA1;ng &#x111;o&#x1EA1;n text</li>
<li>LABEL_DETECTION: nh&#x1EAD;n d&#x1EA1;ng n&#x1ED9;i dung c&#x1EE7;a b&#x1EE9;c &#x1EA3;nh</li>
<li>CROP_HINTS: crop b&#x1EE9;c &#x1EA3;nh t&#x1EAD;p trung v&#xE0;o v&#x1EAD;t tr&#x1ECD;ng t&#xE2;m hay khu&#xF4;n m&#x1EB7;t</li>
<li>FACE_DETECTION: nh&#x1EAD;n d&#x1EA1;ng khu&#xF4;n m&#x1EB7;t</li>
<li>IMAGE_PROPERTIES: c&#xE1;c thu&#x1ED9;c t&#xED;nh c&#x1EE7;a b&#x1EE9;c &#x1EA3;nh nh&#x1B0; RGB, pixcel,...</li>
<li>LANDMARK_DETECTION: nh&#x1EAD;n d&#x1EA1;ng c&#xF4;ng tr&#xEC;nh n&#x1ED5;i ti&#x1EBF;ng</li>
<li>LOGO_DETECTION: nh&#x1EAD;n d&#x1EA1;ng logo, s&#x1EA3;n ph&#x1EA9;m n&#x1ED5;i ti&#x1EBF;ng</li>
<li>SAFE_SEARCH_DETECTION: nh&#x1EAD;n d&#x1EA1;ng xem b&#x1EE9;c &#x1EA3;nh c&#xF3; n&#x1ED9;i dung an to&#xE0;n hay kh&#xF4;ng</li>
<li>WEB_DETECTION: ph&#x1EA7;n n&#xE0;y gi&#x1ED1;ng nh&#x1B0; search google b&#x1EB1;ng h&#xEC;nh &#x1EA3;nh<br>
Chi ti&#x1EBF;t v&#x1EC1; c&#xE1;c tr&#x1B0;&#x1EDD;ng, c&#xE1;c ki&#x1EC3;u detect v&#xE0; c&#xE1;ch s&#x1EED; d&#x1EE5;ng c&#xE1;c b&#x1EA1;n c&#xF3; th&#x1EC3; &#x111;&#x1ECD;c trong t&#xE0;i li&#x1EC7;u Cloud VisionAPI: <a href="https://cloud.google.com/vision/docs?ref=blog.arrow-tech.vn">https://cloud.google.com/vision/docs</a></li>
</ul>
<p><strong>2.4	T&#x1EA1;o request t&#x1EDB;i Cloud API b&#x1EB1;ng curl</strong></p>
<p>&#x110;&#x1EBF;n ph&#x1EA7;n th&#xFA; v&#x1ECB; nh&#x1EA5;t c&#x1EE7;a Cloud API r&#x1ED3;i.<br>
Sau khi &#x111;&#xE3; t&#x1EA1;o xong file request.json, tr&#xEA;n c&#x1EED;a s&#x1ED5; terminal, b&#x1EA1;n th&#x1EF1;c hi&#x1EC7;n l&#x1EC7;nh:<br>
curl -s -X POST -H &quot;Content-Type: application/json&quot; --data-binary @request.json <a href="https://vision.googleapis.com/v1/images:annotate?key=%24%7BAPI_KEY%7D&amp;ref=blog.arrow-tech.vn">https://vision.googleapis.com/v1/images:annotate?key=${API_KEY}</a><br>
V&#xED; d&#x1EE5; m&#xEC;nh s&#x1EBD; th&#x1EED; detect &#x1EA3;nh sau xem n&#x1ED9;i dung nh&#x1EAD;n &#x111;&#x1B0;&#x1EE3;c l&#xE0; g&#xEC; nh&#xE9;!<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture27.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
N&#x1ED9;i dung file request.json c&#x1EE7;a m&#xEC;nh s&#x1EBD; l&#xE0;:</p>
<pre><code>{
  &quot;requests&quot;:[
    {
      &quot;image&quot;:{
        &quot;source&quot;:{
          &quot;imageUri&quot;:
            &quot;https://znews-photo-td.zadn.vn/w1024/Uploaded/ohunuai/2018_07_19/NGUYEN_BA_NGOC1166_Zing.jpg&quot;
        }
      },
      &quot;features&quot;:[
        {
          &quot;type&quot;:&quot;LABEL_DETECTION&quot;,
          &quot;maxResults&quot;:10
        }
      ]
    }
  ]
}
</code></pre>
<p>V&#xE0; k&#x1EBF;t qu&#x1EA3; tr&#x1EA3; v&#x1EC1;:</p>
<pre><code>{
  &quot;responses&quot;: [
    {
      &quot;labelAnnotations&quot;: [
        {
          &quot;mid&quot;: &quot;/m/088fh&quot;,
          &quot;description&quot;: &quot;yellow&quot;,
          &quot;score&quot;: 0.951962,
          &quot;topicality&quot;: 0.951962
        },
        {
          &quot;mid&quot;: &quot;/m/06z04&quot;,
          &quot;description&quot;: &quot;skin&quot;,
          &quot;score&quot;: 0.9510442,
          &quot;topicality&quot;: 0.9510442
        },
        {
          &quot;mid&quot;: &quot;/m/01k74n&quot;,
          &quot;description&quot;: &quot;facial expression&quot;,
          &quot;score&quot;: 0.9331107,
          &quot;topicality&quot;: 0.9331107
        },
        {
          &quot;mid&quot;: &quot;/m/01f43&quot;,
          &quot;description&quot;: &quot;beauty&quot;,
          &quot;score&quot;: 0.91344154,
          &quot;topicality&quot;: 0.91344154
        },
        {
          &quot;mid&quot;: &quot;/m/05r655&quot;,
          &quot;description&quot;: &quot;girl&quot;,
          &quot;score&quot;: 0.8986084,
          &quot;topicality&quot;: 0.8986084
        },
        {
          &quot;mid&quot;: &quot;/m/02pkb8&quot;,
          &quot;description&quot;: &quot;lady&quot;,
          &quot;score&quot;: 0.8730116,
          &quot;topicality&quot;: 0.8730116
        },
        {
          &quot;mid&quot;: &quot;/m/019nj4&quot;,
          &quot;description&quot;: &quot;smile&quot;,
          &quot;score&quot;: 0.84830636,
          &quot;topicality&quot;: 0.84830636
        },
        {
          &quot;mid&quot;: &quot;/m/06pg22&quot;,
          &quot;description&quot;: &quot;snapshot&quot;,
          &quot;score&quot;: 0.8176745,
          &quot;topicality&quot;: 0.8176745
        },
        {
          &quot;mid&quot;: &quot;/m/015c4z&quot;,
          &quot;description&quot;: &quot;sitting&quot;,
          &quot;score&quot;: 0.81240934,
          &quot;topicality&quot;: 0.81240934
        },
        {
          &quot;mid&quot;: &quot;/m/05wkw&quot;,
          &quot;description&quot;: &quot;photography&quot;,
          &quot;score&quot;: 0.7999211,
          &quot;topicality&quot;: 0.7999211
        }
      ]
    }
  ]
}
</code></pre>
<p>Danh s&#xE1;ch k&#x1EBF;t qu&#x1EA3; tr&#x1EA3; v&#x1EC1; &#x111;&#x1B0;&#x1EE3;c s&#x1EAF;p x&#x1EBF;p theo score gi&#x1EA3;m d&#x1EA7;n. M&#xEC;nh th&#x1EA5;y Google nh&#x1EAD;n d&#x1EA1;ng kh&#xE1; ch&#xED;nh x&#xE1;c.</p>
<p><strong>2.5	T&#x1EA1;o request t&#x1EDB;i Cloud API b&#x1EB1;ng Postman</strong></p>
<p>Ti&#x1EBF;p theo m&#xEC;nh s&#x1EBD; h&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE1;c b&#x1EA1;n s&#x1EED; d&#x1EE5;ng Postman &#x111;&#x1EC3; t&#x1EA1;o request detect &#x1EA3;nh.<br>
Cloud Vision API l&#xE0; m&#x1ED9;t REST API v&#x1EDB;i method l&#xE0; POST. Body ch&#xED;nh l&#xE0; n&#x1ED9;i dung c&#x1EE7;a file request.json &#x1EDF; tr&#xEA;n.<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture28.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
(Tr&#xEA;n URL c&#xE1;c b&#x1EA1;n thay xxx b&#x1EB1;ng API Key t&#x1EA1;o &#x1EDF; tr&#xEA;n nh&#xE9;)<br>
Sau &#x111;&#xF3; b&#x1EA1;n nh&#x1EA5;n n&#xFA;t Send v&#xE0; k&#x1EBF;t qu&#x1EA3; b&#x1EA1;n nh&#x1EAD;n &#x111;&#x1B0;&#x1EE3;c:<br>
<img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture29.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
Google Cloud Vision API l&#xE0; m&#x1ED9;t API n&#xEA;n b&#x1EA1;n ho&#xE0;n to&#xE0;n c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; detect &#x1EA3;nh &#x1EDF; trong app c&#x1EE7;a m&#xEC;nh. &#x1EDE; ph&#x1EA7;n ti&#x1EBF;p theo m&#xEC;nh s&#x1EBD; demo m&#x1ED9;t app android s&#x1EED; d&#x1EE5;ng Google Cloud Vision API &#x111;&#x1EC3; nh&#x1EAD;n d&#x1EA1;ng c&#xE1;c v&#x1EAD;t th&#x1EC3; tr&#xEA;n camera m&#x1ED9;t c&#xE1;ch real-time.</p>
<p><strong>3	App demo</strong></p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture30.png" alt="Detect Labels, Faces, and Landmarks in Images with the Cloud Vision API" loading="lazy"><br>
Trong app n&#xE0;y, c&#x1EE9; 5 gi&#xE2;y m&#xEC;nh l&#x1EA1;i ch&#x1EE5;p &#x1EA3;nh r&#x1ED3;i encode &#x1EA3;nh &#x111;&#xF3; sang base64 r&#x1ED3;i d&#xF9;ng Google Vision API v&#x1EDB;i request &#x1EA3;nh &#x1EDF; d&#x1EA1;ng base64 &#x111;&#x1EC3; l&#x1EA5;y v&#x1EC1; k&#x1EBF;t qu&#x1EA3;.<br>
Source code: <a href="https://github.com/quanghd96/GoogleCloudVision?ref=blog.arrow-tech.vn">https://github.com/quanghd96/GoogleCloudVision</a></p>
<p><strong>4	T&#x1ED5;ng k&#x1EBF;t</strong></p>
<p>V&#x1EAD;y l&#xE0; m&#xEC;nh &#x111;&#xE3; h&#x1B0;&#x1EDB;ng d&#x1EAB;n xong c&#xE1;c b&#x1EA1;n c&#xE1;ch s&#x1EED; d&#x1EE5;ng Google Cloud Vision API &#x111;&#x1EC3; detect &#x1EA3;nh. Hy v&#x1ECD;ng s&#x1EBD; gi&#xFA;p &#xED;ch cho c&#xE1;c b&#x1EA1;n ph&#x1EA7;n n&#xE0;o trong vi&#x1EC7;c h&#x1ECD;c t&#x1EAD;p, ph&#xE1;t tri&#x1EC3;n s&#x1EA3;n ph&#x1EA9;m,&#x2026; C&#x1EA3;m &#x1A1;n c&#xE1;c b&#x1EA1;n &#x111;&#xE3; theo d&#xF5;i b&#xE0;i vi&#x1EBF;t c&#x1EE7;a m&#xEC;nh!<br>
T&#xE0;i li&#x1EC7;u tham kh&#x1EA3;o:</p>
<ul>
<li><a href="https://qwiklabs.com/focuses/1841?parent=catalog&amp;ref=blog.arrow-tech.vn">https://qwiklabs.com/focuses/1841?parent=catalog</a></li>
<li><a href="https://cloud.google.com/vision/docs?ref=blog.arrow-tech.vn">https://cloud.google.com/vision/docs</a></li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Lập trình ứng dụng chat đơn giản trên di động với Flutter]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><strong>Gi&#x1EDB;i thi&#x1EC7;u &#x1EE9;ng d&#x1EE5;ng</strong></p>
<p>&#x1EE8;ng d&#x1EE5;ng chat gi&#xFA;p m&#x1ECD;i ng&#x1B0;&#x1EDD;i chat nh&#xF3;m realtime, chia s&#x1EBB; h&#xEC;nh &#x1EA3;nh. Tuy nhi&#xEA;n, trong b&#xE0;i vi&#x1EBF;</p>]]></description><link>https://blog.arrow-tech.vn/lap-trinh-ung-dung-chat-don-gian-tren-di-dong-voi-flutter/</link><guid isPermaLink="false">63915acd7a2f410001205db7</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Android]]></category><category><![CDATA[iOS]]></category><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Wed, 03 Oct 2018 02:52:05 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/12/flutter_blog-2-750x400.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.arrow-tech.vn/content/images/2018/12/flutter_blog-2-750x400.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter"><p><strong>Gi&#x1EDB;i thi&#x1EC7;u &#x1EE9;ng d&#x1EE5;ng</strong></p>
<p>&#x1EE8;ng d&#x1EE5;ng chat gi&#xFA;p m&#x1ECD;i ng&#x1B0;&#x1EDD;i chat nh&#xF3;m realtime, chia s&#x1EBB; h&#xEC;nh &#x1EA3;nh. Tuy nhi&#xEA;n, trong b&#xE0;i vi&#x1EBF;t n&#xE0;y m&#xEC;nh s&#x1EBD; ch&#x1EC9; h&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE1;c b&#x1EA1;n c&#xE1;ch t&#x1EA1;o m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng chat local. C&#xF2;n c&#xE1;c ch&#x1EE9;c n&#x103;ng &#x111;&#x103;ng nh&#x1EAD;p, chat online realtime, chia s&#x1EBB; h&#xEC;nh &#x1EA3;nh m&#xEC;nh s&#x1EBD; h&#x1B0;&#x1EDB;ng d&#x1EAB;n &#x1EDF; c&#xE1;c b&#xE0;i vi&#x1EBF;t ti&#x1EBF;p theo.</p>
<p><strong>C&#xE0;i &#x111;&#x1EB7;t m&#xF4;i tr&#x1B0;&#x1EDD;ng</strong></p>
<p>&#x110;&#x1EC3; b&#x1EAF;t &#x111;&#x1EA7;u, b&#x1EA1;n c&#x1EA7;n c&#xE0;i &#x111;&#x1EB7;t Flutter SDK v&#xE0; m&#x1ED9;t editor c&#xF3; c&#xE0;i s&#x1EB5;n plugin Flutter (trong b&#xE0;i vi&#x1EBF;t n&#xE0;y m&#xEC;nh s&#x1EED; d&#x1EE5;ng IntelliJ v&#xEC; n&#xF3; r&#x1EA5;t ti&#x1EC7;n l&#x1EE3;i v&#xE0; th&#xF4;ng minh). Vi&#x1EC7;c c&#xE0;i &#x111;&#x1EB7;t Flutter SDK b&#x1EA1;n c&#xF3; th&#x1EC3; tham kh&#x1EA3;o &#x1EDF; &#x111;&#x1B0;&#x1EDD;ng link sau: <a href="https://flutter.io/get-started/install/?ref=blog.arrow-tech.vn">https://flutter.io/get-started/install/</a></p>
<p>Ngo&#xE0;i ra b&#x1EA1;n c&#x1EA7;n th&#xEA;m m&#x1ED9;t thi&#x1EBF;t b&#x1ECB; th&#x1EAD;t ho&#x1EB7;c m&#xE1;y &#x1EA3;o (Android ho&#x1EB7;c iOS) &#x111;&#x1EC3; test.</p>
<p><strong>T&#x1EA1;o project</strong></p>
<p>B&#x1EA1;n m&#x1EDF; IntelliJ, ch&#x1ECD;n Create New Project, sau &#x111;&#xF3; ch&#x1ECD;n Flutter nh&#x1B0; h&#xEC;nh d&#x1B0;&#x1EDB;i:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture1.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>N&#x1EBF;u Flutter SDK Path b&#x1ECB; tr&#x1ED1;ng th&#xEC; b&#x1EA1;n tr&#x1ECF; &#x111;&#x1B0;&#x1EDD;ng d&#x1EAB;n t&#x1EDB;i th&#x1B0; m&#x1EE5;c ch&#x1EE9;a Flutter nh&#xE9;. Sau &#x111;&#xF3; nh&#x1EA5;n Next. C&#xE1;c b&#x1EA1;n c&#xF3; th&#x1EC3; thay &#x111;&#x1ED5;i th&#xF4;ng tin project ho&#x1EB7;c &#x111;&#x1EC3; m&#x1EB7;c &#x111;&#x1ECB;nh. Cu&#x1ED1;i c&#xF9;ng nh&#x1EA5;n Finish. Nh&#x1B0; v&#x1EAD;y l&#xE0; c&#xE1;c b&#x1EA1;n &#x111;&#xE3; t&#x1EA1;o th&#xE0;nh c&#xF4;ng &#x1EE9;ng d&#x1EE5;ng s&#x1EED; d&#x1EE5;ng Flutter.</p>
<p>D&#x1B0;&#x1EDB;i &#x111;&#xE2;y l&#xE0; h&#xEC;nh &#x1EA3;nh to&#xE0;n b&#x1ED9; project sau khi &#x111;&#xE3; t&#x1EA1;o xong.</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture2.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Th&#x1B0; m&#x1EE5;c lib ch&#x1EE9;a to&#xE0;n b&#x1ED9; source code c&#x1EE7;a project. Hi&#x1EC7;n t&#x1EA1;i c&#xE1;c b&#x1EA1;n ch&#x1EC9; c&#x1EA7;n quan t&#xE2;m &#x111;&#x1EBF;n th&#x1B0; m&#x1EE5;c n&#xE0;y. &#x110;&#x1EC3; ch&#x1EA1;y th&#x1EED; c&#xE1;c b&#x1EA1;n nh&#x1EA5;n v&#xE0;o n&#xFA;t Run tr&#xEA;n thanh c&#xF4;ng c&#x1EE5;.</p>
<p>M&#x1ED9;t t&#xED;nh n&#x103;ng r&#x1EA5;t th&#xFA; v&#x1ECB; c&#x1EE7;a Flutter l&#xE0; Hot reload. &#x110;&#xF3; l&#xE0; khi b&#x1EA1;n s&#x1EED;a code v&#xE0; l&#x1B0;u l&#x1EA1;i, &#x1EE9;ng d&#x1EE5;ng s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c reload m&#xE0; b&#x1EA1;n kh&#xF4;ng c&#x1EA7;n ph&#x1EA3;i build l&#x1EA1;i. B&#x1EA1;n c&#xF3; th&#x1EC3; tr&#x1EA3;i nghi&#x1EC7;m ngay t&#xED;nh n&#x103;ng n&#xE0;y b&#x1EB1;ng c&#xE1;ch tr&#xEA;n file main.dart, b&#x1EA1;n s&#x1EED;a primarySwatch: Colors.blue th&#xE0;nh primarySwatch: Colors.red sau &#x111;&#xF3; l&#x1B0;u l&#x1EA1;i. &#x1EE8;ng d&#x1EE5;ng s&#x1EBD; t&#x1EF1; &#x111;&#x1ED9;ng chuy&#x1EC3;n giao di&#x1EC7;n t&#x1EEB; m&#xE0;u xanh sang m&#xE0;u &#x111;&#x1ECF;. R&#x1EA5;t th&#xFA; v&#x1ECB; ph&#x1EA3;i kh&#xF4;ng?</p>
<p>Sau &#x111;&#xE2;y ch&#xFA;ng ta s&#x1EBD; ti&#x1EBF;n h&#xE0;nh t&#x1EA1;o giao di&#x1EC7;n cho &#x1EE9;ng d&#x1EE5;ng chat.</p>
<p><strong>T&#x1EA1;o giao di&#x1EC7;n</strong></p>
<p>Ch&#xFA;ng ta c&#x1EA7;n t&#x1EA1;o giao di&#x1EC7;n g&#x1ED3;m:</p>
<ul>
<li>M&#x1ED9;t list &#x111;&#x1EC3; hi&#x1EC3;n th&#x1ECB; tin nh&#x1EAF;n</li>
<li>M&#x1ED9;t &#xF4; &#x111;&#x1EC3; nh&#x1EAD;p tin nh&#x1EAF;n</li>
<li>M&#x1ED9;t n&#xFA;t &#x111;&#x1EC3; g&#x1EED;i tin nh&#x1EAF;n</li>
</ul>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture3.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Sau &#x111;&#xE2;y ch&#xFA;ng ta s&#x1EBD; t&#x1EA1;o l&#x1EA7;n l&#x1B0;&#x1EE3;t t&#x1EEB;ng &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng tr&#xEA;n v&#xE0; gh&#xE9;p ch&#xFA;ng l&#x1EA1;i th&#xE0;nh m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng ho&#xE0;n ch&#x1EC9;nh ch&#x1EA1;y tr&#xEA;n thi&#x1EBF;t b&#x1ECB; th&#x1EAD;t.</p>
<p><strong>T&#x1EA1;o giao di&#x1EC7;n c&#x1A1; b&#x1EA3;n cho &#x1EE9;ng d&#x1EE5;ng</strong></p>
<p>Khi t&#x1EA1;o m&#x1EDB;i m&#x1ED9;t project, trong &#x111;&#xF3; &#x111;&#xE3; c&#xF3; s&#x1EB5;n m&#x1ED9;t s&#x1ED1; th&#xE0;nh ph&#x1EA7;n. Ch&#xFA;ng ta c&#x1EA7;n x&#xF3;a &#x111;i nh&#x1EEF;ng th&#x1EE9; kh&#xF4;ng li&#xEA;n quan &#x111;&#x1EBF;n &#x1EE9;ng d&#x1EE5;ng chat. B&#x1EA1;n s&#x1EED;a l&#x1EA1;i class _MyHomePageState nh&#x1B0; h&#xEC;nh d&#x1B0;&#x1EDB;i &#x111;&#xE2;y.</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture4.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>V&#xE0; &#x111;&#xE2;y l&#xE0; h&#xEC;nh &#x1EA3;nh &#x1EE9;ng d&#x1EE5;ng tr&#x1EAF;ng ch&#x1B0;a c&#xF3; g&#xEC;. Ch&#xFA;ng ta c&#x1EA7;n ph&#x1EA3;i x&#xE2;y d&#x1EF1;ng c&#xE1;c th&#xE0;nh ph&#x1EA7;n &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c li&#x1EC7;t k&#xEA; &#x1EDF; tr&#xEA;n.</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture5.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p><strong>T&#x1EA1;o &#xF4; &#x111;&#x1EC3; nh&#x1EAD;p tin nh&#x1EAF;n</strong></p>
<p>&#x110;&#x1EC3; t&#x1EA1;o &#xF4; nh&#x1EAD;p tin nh&#x1EAF;n, b&#x1EA1;n t&#x1EA1;o h&#xE0;m sau &#x111;&#xE2;y b&#xEA;n trong class _MyHomePageState:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture6.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>M&#xEC;nh s&#x1EBD; gi&#x1EA3;i th&#xED;ch qua v&#x1EC1; h&#xE0;m n&#xE0;y:</p>
<p>H&#xE0;m n&#xE0;y s&#x1EBD; tr&#x1EA3; v&#x1EC1; cho ch&#xFA;ng ta m&#x1ED9;t widget g&#x1ED3;m m&#x1ED9;t TextField (l&#xE0; &#xF4; ch&#xFA;ng ta nh&#x1EAD;p tin nh&#x1EAF;n) v&#x1EDB;i c&#xE1;c &#x111;&#x1ECB;nh d&#x1EA1;ng giao di&#x1EC7;n c&#x1EE7;a n&#xF3;. B&#x1EA1;n c&#xF3; th&#x1EC3; thay &#x111;&#x1ED5;i m&#x1ED9;t s&#x1ED1; th&#xF4;ng s&#x1ED1; v&#xE0; xem s&#x1EF1; thay &#x111;&#x1ED5;i tr&#xEA;n app.</p>
<p>controller l&#xE0; th&#xE0;nh ph&#x1EA7;n qu&#x1EA3;n l&#xFD; TextField nh&#x1B0; vi&#x1EC7;c l&#x1EA5;y tin nh&#x1EAF;n, x&#xF3;a tin nh&#x1EAF;n,... tr&#xEA;n TextField</p>
<p>onSubmitted l&#xE0; th&#xE0;nh ph&#x1EA7;n x&#x1EED; l&#xFD; khi ng&#x1B0;&#x1EDD;i d&#xF9;ng submit tin nh&#x1EAF;n</p>
<p>decoration l&#xE0; th&#xE0;nh ph&#x1EA7;n gi&#xFA;p &#x111;&#x1ECB;nh d&#x1EA1;ng cho TextField nh&#x1B0; text hint,&#x2026;</p>
<p>Ti&#x1EBF;p theo b&#x1EA1;n c&#x1EA7;n t&#x1EA1;o &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng _textController &#x111;&#x1EC3; qu&#x1EA3;n l&#xFD; TextField</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture7.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>T&#x1EA1;o h&#xE0;m _handleSubmitted &#x111;&#x1EC3; x&#x1EED; l&#xFD; khi ng&#x1B0;&#x1EDD;i d&#xF9;ng submit:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture8.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>H&#xE0;m n&#xE0;y s&#x1EBD; nh&#x1EAD;n v&#xE0;o tin nh&#x1EAF;n sau &#x111;&#xF3; x&#x1EED; l&#xFD;. T&#x1EA1;m th&#x1EDD;i ch&#xFA;ng ta s&#x1EBD; th&#x1EF1;c hi&#x1EC7;n vi&#x1EC7;c x&#xF3;a tin nh&#x1EAF;n tr&#xEA;n &#xF4; TextField</p>
<p>Nh&#x1B0; v&#x1EAD;y vi&#x1EC7;c t&#x1EA1;o &#xF4; nh&#x1EAD;p tin nh&#x1EAF;n &#x111;&#xE3; ho&#xE0;n th&#xE0;nh. Ti&#x1EBF;p theo ch&#xFA;ng ta s&#x1EBD; t&#x1EA1;o n&#xFA;t g&#x1EED;i tin nh&#x1EAF;n.</p>
<p><strong>T&#x1EA1;o n&#xFA;t g&#x1EED;i tin nh&#x1EAF;n</strong></p>
<p>Ch&#xFA;ng ta s&#x1EBD; vi&#x1EBF;t l&#x1EA1;i h&#xE0;m _buildTextComposer nh&#x1B0; sau:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture9.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>B&#x1EA1;n th&#x1EA5;y h&#xE0;m c&#x1EE7;a ch&#xFA;ng ta &#x111;&#xE3; ph&#x1EE9;c t&#x1EA1;p h&#x1A1;n r&#x1EA5;t nhi&#x1EC1;u r&#x1ED3;i &#x111;&#xFA;ng kh&#xF4;ng?</p>
<p>Nh&#x1B0;ng s&#x1EBD; r&#x1EA5;t d&#x1EC5; hi&#x1EC3;u th&#xF4;i, IconTheme ch&#xFA;ng l&#xE0; Widget m&#xE0; gi&#xFA;p c&#xE1;c ph&#x1EA7;n t&#x1EED; b&#xEA;n trong n&#xF3; nh&#x1B0; n&#xFA;t g&#x1EED;i tin nh&#x1EAF;n c&#x1EE7;a ch&#xFA;ng ta hi&#x1EC3;n th&#x1ECB; m&#xE0;u theo theme hi&#x1EC7;n t&#x1EA1;i.</p>
<p>Do ch&#xFA;ng ta t&#x1EA1;o th&#xEA;m m&#x1ED9;t n&#xFA;t n&#x1EEF;a n&#xEA;n c&#x1EA7;n ph&#x1EA3;i &#x111;&#x1B0;a ch&#xFA;ng v&#xE0;o 1 Row (row s&#x1EBD; hi&#x1EC3;n th&#x1ECB; c&#xE1;c ph&#x1EA7;n t&#x1EED; theo chi&#x1EC1;u ngang).</p>
<p>TextField &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1B0;a v&#xE0;o b&#xEA;n trong widget Flexible &#x111;&#x1EC3; l&#xFA;c n&#xE0;o chi&#x1EC1;u d&#xE0;i c&#x1EE7;a n&#xF3; c&#x169;ng k&#xED;n m&#xE0;n h&#xEC;nh.</p>
<p>N&#xFA;t g&#x1EED;i ch&#xFA;ng ta s&#x1EBD; s&#x1EED; d&#x1EE5;ng Widget IconButton v&#x1EDB;i:</p>
<p>icon l&#xE0; icon c&#x1EE7;a n&#xFA;t</p>
<p>onPressed l&#xE0; s&#x1EF1; ki&#x1EC7;n nh&#x1EA5;n n&#xFA;t. Ch&#xFA;ng ta s&#x1EBD; x&#x1EED; l&#xFD; trong h&#xE0;m _handleSubmitted &#x1EDF; tr&#xEA;n v&#x1EDB;i tham s&#x1ED1; truy&#x1EC1;n v&#xE0;o l&#xE0; tin nh&#x1EAF;n l&#x1EA5;y t&#x1EEB; &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng _textController &#x1EDF; tr&#xEA;n.</p>
<p>Nh&#x1B0; v&#x1EAD;y l&#xE0; &#x111;&#xE3; xong. Ch&#xFA;ng ta l&#xE0;m ph&#x1EA7;n cu&#x1ED1;i c&#xF9;ng l&#xE0; list tin nh&#x1EAF;n.</p>
<p><strong>T&#x1EA1;o list hi&#x1EC3;n th&#x1ECB; tin nh&#x1EAF;n</strong></p>
<p>&#x110;&#x1EA7;u ti&#xEA;n ch&#xFA;ng ta s&#x1EBD; t&#x1EA1;o ra widget &#x111;&#x1EC3; hi&#x1EC3;n th&#x1ECB; 1 tin nh&#x1EAF;n</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture10.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Widget n&#xE0;y s&#x1EBD; g&#x1ED3;m c&#xF3; 1 icon l&#xE0; avatar c&#x1EE7;a ng&#x1B0;&#x1EDD;i g&#x1EED;i v&#xE0; b&#xEA;n c&#x1EA1;nh l&#xE0; m&#x1ED9;t Text &#x111;&#x1EC3; hi&#x1EC3;n th&#x1ECB; tin nh&#x1EAF;n c&#x1EE7;a ng&#x1B0;&#x1EDD;i &#x111;&#xF3;.</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture11.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Sau &#x111;&#xF3; ch&#xFA;ng ta s&#x1EBD; t&#x1EA1;o ra list ch&#x1EE9;a c&#xE1;c ChatMessage tr&#xEA;n:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture12.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Ch&#xFA;ng ta s&#x1EBD; s&#x1EED; d&#x1EE5;ng ListView v&#x1EDB;i:</p>
<p>itemBuilder l&#xE0; th&#xE0;nh ph&#x1EA7;n build ra t&#x1EEB;ng d&#xF2;ng tin nh&#x1EAF;n</p>
<p>itemCount l&#xE0; s&#x1ED1; l&#x1B0;&#x1EE3;ng tin nh&#x1EAF;n hi&#x1EC3;n th&#x1ECB; tr&#xEA;n list</p>
<p>&#x1EDE; &#x111;&#xE2;y ch&#xFA;ng ta c&#x1EA7;n t&#x1EA1;o ra m&#x1ED9;t bi&#x1EBF;n _messages ch&#x1EE9;a c&#xE1;c ChatMessage:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture13.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>Khi l&#x1B0;u l&#x1EA1;i b&#x1EA1;n s&#x1EBD; th&#x1EA5;y &#xF4; nh&#x1EAD;p tin nh&#x1EAF;n v&#xE0; n&#xFA;t g&#x1EED;i &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c di chuy&#x1EC3;n xu&#x1ED1;ng ph&#xED;a d&#x1B0;&#x1EDB;i m&#xE0;n h&#xEC;nh. &#x110;&#xF3; ch&#xED;nh l&#xE0; do widget Flexiable.</p>
<p>Cu&#x1ED1;i c&#xF9;ng ch&#xFA;ng ta c&#x1EA7;n x&#x1EED; l&#xFD; khi ng&#x1B0;&#x1EDD;i d&#xF9;ng nh&#x1EA5;n n&#xFA;t g&#x1EED;i s&#x1EBD; hi&#x1EC3;n th&#x1ECB; tin nh&#x1EAF;n &#x111;&#xF3; v&#xE0;o list trong h&#xE0;m _handleSubmitted nh&#x1B0; sau:</p>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/10/Picture14.png" alt="L&#x1EAD;p tr&#xEC;nh &#x1EE9;ng d&#x1EE5;ng chat &#x111;&#x1A1;n gi&#x1EA3;n tr&#xEA;n di &#x111;&#x1ED9;ng v&#x1EDB;i Flutter" loading="lazy"></p>
<p>H&#xE0;m setState tr&#xEA;n s&#x1EBD; set l&#x1EA1;i bi&#x1EBF;n _messages v&#xE0; c&#x1EAD;p nh&#x1EAD;t l&#x1EA1;i giao di&#x1EC7;n m&#x1ED9;t c&#xE1;ch realtime. &#x110;&#xE2;y c&#x169;ng ch&#xED;nh l&#xE0; m&#x1ED9;t t&#xED;nh n&#x103;ng r&#x1EA5;t hay c&#x1EE7;a Flutter. N&#x1EBF;u b&#x1EA1;n n&#xE0;o &#x111;&#xE3; t&#x1EEB;ng bi&#x1EBF;t React Native th&#xEC; ch&#x1EAF;c h&#x1EB3;n s&#x1EBD; r&#x1EA5;t quen thu&#x1ED9;c v&#x1EDB;i state v&#xE0; h&#xE0;m n&#xE0;y.</p>
<p>Nh&#x1B0; v&#x1EAD;y &#x111;&#xE3; xong.</p>
<p>Source code: <a href="https://github.com/quanghd96/chat_flutter?ref=blog.arrow-tech.vn">https://github.com/quanghd96/chat_flutter</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Giới thiệu về ReactJS - một thư viện Javascript hỗ trợ xây dựng giao diện]]></title><description><![CDATA[ React là một thư viện JavaScript mã nguồn mở, được xây dựng và phát triển bởi Facebook, giúp xây dựng giao diện người dùng. Rất nhiều thương hiệu lớn hàng đầu trên thế giới sử dụng React như Facebook, Instagram, Lazada, Mashable, Twitter,…]]></description><link>https://blog.arrow-tech.vn/gioi-thieu-react-mot-thu-vien-javascript-ho-tro-xay-dung-giao-dien/</link><guid isPermaLink="false">63915acd7a2f410001205da4</guid><category><![CDATA[React]]></category><dc:creator><![CDATA[Quang Dang]]></dc:creator><pubDate>Wed, 24 Jan 2018 10:03:53 GMT</pubDate><media:content url="https://blog.arrow-tech.vn/content/images/2018/01/1_HSisLuifMO6KbLfPOKtLow-1.jpeg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id="1reactjslg">1 ReactJS l&#xE0; g&#xEC;</h2>
<ul>
<li>
<img src="https://blog.arrow-tech.vn/content/images/2018/01/1_HSisLuifMO6KbLfPOKtLow-1.jpeg" alt="Gi&#x1EDB;i thi&#x1EC7;u v&#x1EC1; ReactJS - m&#x1ED9;t th&#x1B0; vi&#x1EC7;n Javascript h&#x1ED7; tr&#x1EE3; x&#xE2;y d&#x1EF1;ng giao di&#x1EC7;n"><p>React l&#xE0; m&#x1ED9;t th&#x1B0; vi&#x1EC7;n JavaScript m&#xE3; ngu&#x1ED3;n m&#x1EDF;, &#x111;&#x1B0;&#x1EE3;c x&#xE2;y d&#x1EF1;ng v&#xE0; ph&#xE1;t tri&#x1EC3;n b&#x1EDF;i Facebook, gi&#xFA;p x&#xE2;y d&#x1EF1;ng giao di&#x1EC7;n ng&#x1B0;&#x1EDD;i d&#xF9;ng. R&#x1EA5;t nhi&#x1EC1;u th&#x1B0;&#x1A1;ng hi&#x1EC7;u l&#x1EDB;n h&#xE0;ng &#x111;&#x1EA7;u tr&#xEA;n th&#x1EBF; gi&#x1EDB;i s&#x1EED; d&#x1EE5;ng React nh&#x1B0; Facebook, Instagram, Lazada, Mashable, Twitter,&#x2026;</p>
</li>
<li>
<p>React JS l&#xE0; m&#x1ED9;t th&#xE0;nh ph&#x1EA7;n trong ng&#xF4;i nh&#xE0; React, n&#xF3; gi&#xFA;p x&#xE2;y d&#x1EF1;ng giao di&#x1EC7;n cho c&#xE1;c &#x1EE9;ng d&#x1EE5;ng tr&#xEA;n n&#x1EC1;n t&#x1EA3;ng web. Ngo&#xE0;i ra, c&#xF2;n nhi&#x1EC1;u th&#xE0;nh ph&#x1EA7;n kh&#xE1;c nh&#x1B0; React native &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng x&#xE2;y d&#x1EF1;ng c&#xE1;c &#x1EE9;ng d&#x1EE5;ng di &#x111;&#x1ED9;ng, React VR &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng c&#xE1;c website v&#xE0; t&#x1B0;&#x1A1;ng t&#xE1;c 360 &#x111;&#x1ED9;, React Desktop x&#xE2;y d&#x1EF1;ng c&#xE1;c &#x1EE9;ng d&#x1EE5;ng tr&#xEA;n desktop,&#x2026; V&#xEC; th&#x1EBF; &#x111;&#xE2;y l&#xE0; m&#x1ED9;t th&#x1B0; vi&#x1EC7;n gi&#xFA;p ta h&#x1ECD;c m&#x1ED9;t l&#x1EA7;n vi&#x1EBF;t m&#x1ECD;i n&#x1A1;i</p>
</li>
<li>
<p>React JS ch&#x1EC9; l&#xE0; m&#x1ED9;t th&#x1B0; vi&#x1EC7;n, kh&#xF4;ng ph&#x1EA3;i l&#xE0; m&#x1ED9;t framework v&#xE0; trong m&#xF4; h&#xEC;nh MVC n&#xF3; &#x1EE9;ng v&#x1EDB;i t&#x1EA7;ng View (V)</p>
</li>
</ul>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/01/integrating-reactjs-into-a-php-application-10-638.jpg" alt="Gi&#x1EDB;i thi&#x1EC7;u v&#x1EC1; ReactJS - m&#x1ED9;t th&#x1B0; vi&#x1EC7;n Javascript h&#x1ED7; tr&#x1EE3; x&#xE2;y d&#x1EF1;ng giao di&#x1EC7;n" loading="lazy"></p>
<h2 id="2dnglmgkhinothdng">2 D&#xF9;ng &#x111;&#x1EC3; l&#xE0;m g&#xEC;, khi n&#xE0;o th&#xEC; d&#xF9;ng</h2>
<h3 id="21dnglmg">2.1	D&#xF9;ng &#x111;&#x1EC3; l&#xE0;m g&#xEC;</h3>
<ul>
<li>React JS d&#xF9;ng &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng c&#xE1;c &#x1EE9;ng d&#x1EE5;ng tr&#xEA;n n&#x1EC1;n t&#x1EA3;ng web</li>
<li>React JS c&#xF3; th&#x1EC3; d&#xF9;ng x&#xE2;y d&#x1EF1;ng giao di&#x1EC7;n ho&#x1EB7;c d&#xF9;ng &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng c&#xE1;c server</li>
</ul>
<h3 id="22khinothdng">2.2	Khi n&#xE0;o th&#xEC; d&#xF9;ng</h3>
<ul>
<li>React JS d&#x1EC5; d&#xE0;ng qu&#x1EA3;n l&#xFD; khi quy m&#xF4; m&#x1EDF; r&#x1ED9;ng, l&#x1EDB;n, d&#x1EEF; li&#x1EC7;u thay &#x111;&#x1ED5;i li&#xEA;n t&#x1EE5;c theo th&#x1EDD;i gian, n&#xF3; kh&#xF4;ng d&#xE0;nh cho nh&#x1EEF;ng &#x1EE9;ng d&#x1EE5;ng nh&#x1ECF; c&#x1EA7;n ho&#xE0;n th&#xE0;nh s&#x1EDB;m</li>
<li>React JS h&#x1ED7; tr&#x1EE3; r&#x1EA5;t t&#x1ED1;t cho vi&#x1EC7;c x&#xE2;y d&#x1EF1;ng c&#xE1;c &#x1EE9;ng d&#x1EE5;ng web Single Page</li>
</ul>
<p><img src="https://blog.arrow-tech.vn/content/images/2018/01/do-you-react.jpg" alt="Gi&#x1EDB;i thi&#x1EC7;u v&#x1EC1; ReactJS - m&#x1ED9;t th&#x1B0; vi&#x1EC7;n Javascript h&#x1ED7; tr&#x1EE3; x&#xE2;y d&#x1EF1;ng giao di&#x1EC7;n" loading="lazy"></p>
<h2 id="3cutrcthnhphncareactjs">3 C&#x1EA5;u tr&#xFA;c, th&#xE0;nh ph&#x1EA7;n c&#x1EE7;a ReactJS</h2>
<p>React &#x111;&#x1B0;&#x1EE3;c x&#xE2;y d&#x1EF1;ng xung quanh c&#xE1;c th&#xE0;nh ph&#x1EA7;n nh&#x1ECF; g&#x1ECD;i l&#xE0; component nh&#x1EB1;m m&#x1EE5;c &#x111;&#xED;ch d&#x1EC5; qu&#x1EA3;n l&#xFD; v&#xE0; t&#xE1;i s&#x1EED; d&#x1EE5;ng. D&#x1B0;&#x1EDB;i &#x111;&#xE2;y l&#xE0; c&#xE1;c th&#xE0;nh ph&#x1EA7;n c&#x1EE7;a m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng ReactJS</p>
<h3 id="31component">3.1	Component</h3>
<p>Trong React JS, ch&#xFA;ng ta x&#xE2;y d&#x1EF1;ng trang web s&#x1EED; d&#x1EE5;ng c&#xE1;c component nh&#x1ECF;. Ch&#xFA;ng ta c&#xF3; th&#x1EC3; t&#xE1;i s&#x1EED; d&#x1EE5;ng l&#x1EA1;i c&#xE1;c component &#x111;&#xF3; &#x1EDF; nhi&#x1EC1;u n&#x1A1;i m&#x1ED9;t c&#xE1;ch linh ho&#x1EA1;t v&#x1EDB;i c&#xE1;c tr&#x1EA1;ng th&#xE1;i ho&#x1EB7;c c&#xE1;c thu&#x1ED9;c t&#xED;nh kh&#xE1;c nhau, trong m&#x1ED9;t component l&#x1EA1;i c&#xF3; th&#x1EC3; c&#xF3; nhi&#x1EC1;u th&#xE0;nh ph&#x1EA7;n kh&#xE1;c. M&#x1ED7;i component c&#xF3; m&#x1ED9;t tr&#x1EA1;ng th&#xE1;i ri&#xEA;ng c&#xF3; th&#x1EC3; thay &#x111;&#x1ED5;i &#x111;&#x1B0;&#x1EE3;c g&#x1ECD;i l&#xE0; state. Tr&#x1EA1;ng th&#xE1;i c&#x1EE7;a component thay &#x111;&#x1ED5;i th&#xEC; component c&#x169;ng &#x111;&#x1B0;&#x1EE3;c render l&#x1EA1;i m&#x1ED9;t c&#xE1;ch real-time.<br>
V&#xED; d&#x1EE5;: M&#x1ED9;t trang web s&#x1EBD; c&#xF3; c&#xE1;c component nh&#x1B0; Header, Content, Footer. Trong component Header c&#xF3; c&#xE1;c component nh&#x1B0; Title, SearchBar,&#x2026; Trong Content c&#xF3; c&#xE1;c component nh&#x1B0; Form, Button,&#x2026;</p>
<h3 id="32props">3.2	Props</h3>
<p>Props ch&#xED;nh l&#xE0; c&#xE1;c thu&#x1ED9;c t&#xED;nh c&#x1EE7;a m&#x1ED9;t component. Props gi&#xFA;p c&#xE1;c component t&#x1B0;&#x1A1;ng t&#xE1;c v&#x1EDB;i nhau, component nh&#x1EAD;n input g&#x1ECD;i l&#xE0; props v&#xE0; tr&#x1EA3; thu&#x1ED9;c t&#xED;nh m&#xF4; t&#x1EA3; nh&#x1EEF;ng g&#xEC; component con s&#x1EBD; render. Props gi&#x1ED1;ng nh&#x1B0; h&#x1EB1;ng s&#x1ED1;, kh&#xF4;ng thay &#x111;&#x1ED5;i &#x111;&#x1B0;&#x1EE3;c gi&#xE1; tr&#x1ECB;.</p>
<h3 id="33state">3.3	State</h3>
<p>State l&#xE0; tr&#x1EA1;ng th&#xE1;i c&#x1EE7;a component, khi state thay &#x111;&#x1ED5;i th&#xEC; component c&#x169;ng &#x111;&#x1B0;&#x1EE3;c render l&#x1EA1;i m&#x1ED9;t c&#xE1;ch &#x111;&#x1ED3;ng th&#x1EDD;i &#x111;&#x1EC3; c&#x1EAD;p nh&#x1EAD;t UI.</p>
<h2 id="4citthno">4 C&#xE0;i &#x111;&#x1EB7;t th&#x1EBF; n&#xE0;o</h2>
<p>C&#xF3; nhi&#x1EC1;u c&#xE1;ch c&#xE0;i &#x111;&#x1EB7;t, d&#x1B0;&#x1EDB;i &#x111;&#xE2;y l&#xE0; c&#xE1;ch &#x111;&#x1A1;n gi&#x1EA3;n nh&#x1EA5;t &#x111;&#x1EC3; b&#x1EAF;t &#x111;&#x1EA7;u x&#xE2;y d&#x1EF1;ng m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng React m&#x1EDB;i. Tr&#x1B0;&#x1EDB;c h&#x1EBF;t, ch&#xFA;ng ta c&#x1EA7;n c&#xE0;i &#x111;&#x1EB7;t NodeJS phi&#xEA;n b&#x1EA3;n m&#x1EDB;i nh&#x1EA5;t, c&#xF3; th&#x1EC3; c&#xE0;i th&#xEA;m Yarn v&#xE0; m&#x1ED9;t c&#xF4;ng c&#x1EE5; &#x111;&#x1EC3; vi&#x1EBF;t code nh&#x1B0; Sublime Text, Atom, Visual Studio Code,&#x2026;</p>
<h3 id="41citcreatereactapp">4.1	C&#xE0;i &#x111;&#x1EB7;t create-react-app</h3>
<p>Create-react-app l&#xE0; m&#x1ED9;t c&#xE2;u l&#x1EC7;nh gi&#xFA;p b&#x1EA1;n kh&#x1EDF;i t&#x1EA1;o m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng web reactjs &#x1EDF; b&#x1EA5;t c&#x1EE9; &#x111;&#xE2;u, b&#x1EA5;t c&#x1EE9; h&#x1EC7; &#x111;i&#x1EC1;u h&#xE0;nh n&#xE0;o tr&#xEA;n m&#xE1;y t&#xED;nh. &#x110;&#x1EC3; s&#x1EED; d&#x1EE5;ng &#x111;&#x1B0;&#x1EE3;c l&#x1EC7;nh n&#xE0;y, r&#x1EA5;t &#x111;&#x1A1;n gi&#x1EA3;n, b&#x1EA1;n ti&#x1EBF;n h&#xE0;nh: M&#x1EDF; c&#xF4;ng c&#x1EE5; d&#xF2;ng l&#x1EC7;nh &#x1B0;a th&#xED;ch c&#x1EE7;a b&#x1EA1;n (Command Line, Windows Power Shell,&#x2026;) v&#xE0; th&#x1EF1;c hi&#x1EC7;n c&#xE2;u l&#x1EC7;nh: npm install -g create-react-app.<br>
Sau khi c&#xE0;i &#x111;&#x1EB7;t xong, ch&#xFA;ng ta c&#xF3; th&#x1EC3; d&#xF9;ng l&#x1EC7;nh create-react-app &#x111;&#x1EC3; t&#x1EA1;o m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng web s&#x1EED; d&#x1EE5;ng react &#x1EDF; b&#x1EA5;t k&#x1EF3; &#x111;&#xE2;u.</p>
<h3 id="42tongdng">4.2	T&#x1EA1;o &#x1EE9;ng d&#x1EE5;ng</h3>
<p>S&#x1EED; d&#x1EE5;ng c&#xE2;u l&#x1EC7;nh create-react-app &lt;t&#xEA;n app&gt; v&#xE0; &#x111;&#x1EE3;i cho t&#x1EDB;i khi c&#xE0;i &#x111;&#x1EB7;t xong. Sau &#x111;&#xF3;, th&#x1EF1;c hi&#x1EC7;n c&#xE2;u l&#x1EC7;nh cd &lt;t&#xEA;n app&gt; &#x111;&#x1EC3; di chuy&#x1EC3;n v&#xE0;o th&#x1B0; m&#x1EE5;c c&#x1EE7;a &#x1EE9;ng d&#x1EE5;ng.</p>
<p>S&#x1EED; d&#x1EE5;ng c&#xE2;u l&#x1EC7;nh npm start &#x111;&#x1EC3; ch&#x1EA1;y &#x1EE9;ng d&#x1EE5;ng. Sau khi th&#x1EF1;c hi&#x1EC7;n c&#xE2;u l&#x1EC7;nh, c&#xE1;c m&#xE3; ngu&#x1ED3;n c&#x1EE7;a &#x1EE9;ng d&#x1EE5;ng s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c build ra c&#xE1;c file th&#x1EF1;c thi v&#xE0; &#x111;&#x1B0;&#x1EE3;c m&#x1EDF; tr&#x1EF1;c ti&#x1EBF;p ngay tr&#xEA;n tr&#xEC;nh duy&#x1EC7;t tr&#xEA;n &#x111;&#x1ECB;a ch&#x1EC9;: <a href="http://localhost:3000/?ref=blog.arrow-tech.vn">http://localhost:3000</a><br>
D&#x1B0;&#x1EDB;i &#x111;&#xE2;y l&#xE0; c&#x1EA5;u tr&#xFA;c c&#xE1;c th&#xE0;nh ph&#x1EA7;n c&#x1EE7;a m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng reactjs</p>
<ul>
<li>Th&#x1B0; m&#x1EE5;c node_modules ch&#x1EE9;a c&#xE1;c th&#x1B0; vi&#x1EC7;n, c&#xE1;c th&#xE0;nh ph&#x1EA7;n c&#x1EA7;n thi&#x1EBF;t cTh&#x1B0; m&#x1EE5;c public ch&#x1EE9;a c&#xE1;c file t&#xE0;i nguy&#xEA;n m&#xE0; ng&#x1B0;&#x1EDD;i d&#xF9;ng c&#xF3; th&#x1EC3; t&#x1EA3;i tr&#x1EF1;c ti&#x1EBF;p v&#x1EC1; m&#xE1;y</li>
<li>Th&#x1B0; m&#x1EE5;c src ch&#x1EE9;a source code c&#x1EE7;a &#x1EE9;ng d&#x1EE5;ng</li>
<li>File package.json ch&#x1EE9;a c&#xE1;c c&#x1EA5;u h&#xEC;nh cho &#x1EE9;ng d&#x1EE5;ng</li>
</ul>
<h3 id="43xutbnngdng">4.3	Xu&#x1EA5;t b&#x1EA3;n &#x1EE9;ng d&#x1EE5;ng</h3>
<p>Sau m&#x1ED9;t th&#x1EDD;i gian ph&#xE1;t tri&#x1EC3;n &#x1EE9;ng d&#x1EE5;ng, b&#x1EA1;n mu&#x1ED1;n &#x111;&#x1B0;a &#x1EE9;ng d&#x1EE5;ng c&#x1EE7;a b&#x1EA1;n l&#xEA;n host &#x111;&#x1EC3; m&#x1ECD;i ng&#x1B0;&#x1EDD;i c&#xF9;ng s&#x1EED; d&#x1EE5;ng. Khi &#x111;&#xF3;, b&#x1EA1;n c&#x1EA7;n xu&#x1EA5;t b&#x1EA3;n &#x1EE9;ng d&#x1EE5;ng c&#x1EE7;a m&#xEC;nh. &#x110;&#x1EC3; xu&#x1EA5;t b&#x1EA3;n, b&#x1EA1;n th&#x1EF1;c hi&#x1EC7;n c&#xE2;u l&#x1EC7;nh npm run build. Sau khi th&#x1EF1;c hi&#x1EC7;n xong, &#x1EE9;ng d&#x1EE5;ng c&#x1EE7;a b&#x1EA1;n &#x111;&#x1B0;&#x1EE3;c l&#x1B0;u trong th&#x1B0; m&#x1EE5;c build, b&#x1EA1;n c&#xF3; th&#x1EC3; up c&#xE1;c file n&#xE0;y l&#xEA;n host &#x111;&#x1EC3; ti&#x1EBF;n h&#xE0;nh s&#x1EED; d&#x1EE5;ng.</p>
<h2 id="5demo">5 Demo</h2>
<p>D&#x1B0;&#x1EDB;i &#x111;&#xE2;y l&#xE0; h&#xEC;nh &#x1EA3;nh c&#x1EE7;a trang login s&#x1EED; d&#x1EE5;ng react js:</p>
<p>&#x110;&#x1EC3; ki&#x1EC3;m tra xem &#x1EE9;ng d&#x1EE5;ng c&#x1EE7;a b&#x1EA1;n hay m&#x1ED9;t trang web n&#xE0;o &#x111;&#xF3; b&#x1EA1;n &#x111;ang xem c&#xF3; s&#x1EED; d&#x1EE5;ng reactjs kh&#xF4;ng, b&#x1EA1;n c&#xF3; th&#x1EC3; c&#xE0;i &#x111;&#x1EB7;t ti&#x1EC7;n &#xED;ch React Developer Tools tr&#xEA;n tr&#xEC;nh duy&#x1EC7;t. Ti&#x1EC7;n &#xED;ch n&#xE0;y do ch&#xED;nh Facebook ph&#xE1;t tri&#x1EC3;n v&#xE0; c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng tr&#xEA;n tr&#xEC;nh duy&#x1EC7;t Chrome v&#xE0; Firefox. Sau khi c&#xE0;i &#x111;&#x1EB7;t ti&#x1EC7;n &#xED;ch n&#xE0;y, b&#x1EA1;n v&#xE0;o m&#x1ED9;t trang web n&#xE0;o &#x111;&#xF3;, n&#x1EBF;u bi&#x1EC3;u t&#x1B0;&#x1EE3;ng c&#x1EE7;a ti&#x1EC7;n &#xED;ch c&#xF3; m&#xE0;u:</p>
<ul>
<li>Tr&#x1EAF;ng: trang web &#x111;&#xF3; kh&#xF4;ng s&#x1EED; d&#x1EE5;ng reactjs</li>
<li>V&#xE0;ng: trang web &#x111;&#xF3; &#x111;ang trong ch&#x1EBF; &#x111;&#x1ED9; ph&#xE1;t tri&#x1EC3;n, ch&#x1B0;a xu&#x1EA5;t b&#x1EA3;n phi&#xEA;n b&#x1EA3;n ch&#xED;nh th&#x1EE9;c</li>
<li>Xanh: trang web &#x111;&#xF3; &#x111;&#xE3; &#x1EDF; ch&#x1EBF; &#x111;&#x1ED9; xu&#x1EA5;t b&#x1EA3;n ch&#xED;nh th&#x1EE9;c</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>