<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Archive on Trevor's Blog</title><link>http://mings.in/en/tags/archive/</link><description>Recent content in Archive on Trevor's Blog</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Wed, 10 Apr 2019 09:00:00 +0800</lastBuildDate><atom:link href="http://mings.in/en/tags/archive/index.xml" rel="self" type="application/rss+xml"/><item><title>flutter_boost Integration on Android: What It Took</title><link>http://mings.in/en/posts/flutter-boost/</link><pubDate>Wed, 10 Apr 2019 09:00:00 +0800</pubDate><guid>http://mings.in/en/posts/flutter-boost/</guid><description>flutter_boost integration on Android: what it took</description><content:encoded><![CDATA[<blockquote>
<p>How to add flutter_boost to an existing Android project. This demo was done on macOS. On Windows, change the paths to Windows format.</p>
</blockquote>
<h2 id="the-flutter-side">The Flutter side</h2>
<ol>
<li>
<p>Create a new flutter module</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">flutter create -t module flutter_module
</span></span></code></pre></div></li>
<li>
<p>Add the flutter_boost dependency in <code>pubspec.yaml</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">dependencies</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">flutter_boost</span><span class="p">:</span><span class="w">
</span></span></span></code></pre></div></li>
<li>
<p>Run <code>flutter build apk</code>
With flutter_boost 0.400 this throws an error. The key part is:</p>
<pre tabindex="0"><code>* What went wrong:
A problem occurred evaluating project &#39;:flutter_boost&#39;.
&gt; Plugin with id &#39;kotlin-android-extensions&#39; not found.
</code></pre><p>It&rsquo;s not hard to see it&rsquo;s a missing <code>kotlin</code> dependency. Let&rsquo;s fix that.</p>
</li>
<li>
<p>From the project root run <code>flutter make-host-app-editable</code>
When it finishes you&rsquo;ll see <code>android</code> and <code>ios</code> folders appear.</p>
</li>
<li>
<p>Add the <code>kotlin</code> dependency in <code>android/build.gralde</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl"> buildscript {
</span></span><span class="line"><span class="cl"><span class="gi">+    ext.kotlin_version = &#39;1.3.21&#39;
</span></span></span><span class="line"><span class="cl">	repositories {
</span></span><span class="line"><span class="cl">		google()
</span></span><span class="line"><span class="cl">		jcenter()
</span></span><span class="line"><span class="cl"><span class="gu">@@ -8,6 +9,7 @@ buildscript {
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	dependencies {
</span></span><span class="line"><span class="cl">		classpath &#39;com.android.tools.build:gradle:3.2.1&#39;
</span></span><span class="line"><span class="cl"><span class="gi">+        classpath &#34;org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version&#34;
</span></span></span><span class="line"><span class="cl">	}
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></div><p>Run <code>flutter build apk</code> again and it succeeds.</p>
</li>
<li>
<p>Copy the files under <code>flutter_boost/example/lib</code> into the <code>lib</code> directory</p>
</li>
</ol>
<p>That&rsquo;s the Flutter side prepared.</p>
<h2 id="the-android-side">The Android side</h2>
<ol>
<li>
<p>Create a project with Android Studio</p>
<p>If you already have a project you can skip this step</p>
</li>
<li>
<p>Add kotlin support to the App module, and add the following to <code>settings.gradle</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-groovy" data-lang="groovy"><span class="line"><span class="cl"><span class="n">setBinding</span><span class="o">(</span><span class="k">new</span> <span class="n">Binding</span><span class="o">([</span><span class="nl">gradle:</span> <span class="k">this</span><span class="o">]))</span>
</span></span><span class="line"><span class="cl"><span class="n">evaluate</span><span class="o">(</span><span class="k">new</span> <span class="n">File</span><span class="o">(</span><span class="s1">&#39;../flutter_module/.android/include_flutter.groovy&#39;</span><span class="o">))</span>   <span class="c1">// keep the Android project and the flutter module in the same directory
</span></span></span></code></pre></div><p>Run <code>gralde sync</code>. You should now see three new projects in your build: <code>Flutter-flutter</code>, <code>flutter_boost</code> and <code>xservice_kit</code></p>
<p>If you hit the error below, change the gradle version to <strong>4.10.2</strong></p>
<pre tabindex="0"><code>ERROR: Unable to resolve dependency for &#39;:flutter@dynamicProfile/compileClasspath&#39;: Could not resolve project :xservice_kit.
 Show Details
 Affected Modules: flutter

 ERROR: Unable to resolve dependency for &#39;:flutter@dynamicProfile/compileClasspath&#39;: Could not resolve project :flutter_boost.
 Show Details
 Affected Modules: flutter
</code></pre></li>
<li>
<p>Add the dependencies below to the <code>build.gradle</code> file in the <code>flutterservice</code> directory</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-groovy" data-lang="groovy"><span class="line"><span class="cl"><span class="n">implementation</span> <span class="nf">project</span><span class="o">(</span><span class="nl">path:</span> <span class="s1">&#39;:flutter&#39;</span><span class="o">)</span>
</span></span><span class="line"><span class="cl"><span class="n">implementation</span> <span class="nf">project</span><span class="o">(</span><span class="s2">&#34;:flutter_boost&#34;</span><span class="o">)</span>
</span></span></code></pre></div></li>
<li>
<p>Copy everything from <code>flutter_boost/example/android</code> and create a new <code>MyApplication</code> class:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MyApplication</span> <span class="p">:</span> <span class="n">FlutterApplication</span><span class="p">(),</span> <span class="n">IPlatform</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreate</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">super</span><span class="p">.</span><span class="n">onCreate</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="nc">FlutterBoostPlugin</span><span class="p">.</span><span class="k">init</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="k">override</span> <span class="k">fun</span> <span class="nf">getApplication</span><span class="p">():</span> <span class="n">Application</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="k">this</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">override</span> <span class="k">fun</span> <span class="nf">getMainActivity</span><span class="p">():</span> <span class="n">Activity</span><span class="p">?</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nc">MainActivity</span><span class="p">.</span><span class="n">sRef</span><span class="p">.</span><span class="k">get</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">override</span> <span class="k">fun</span> <span class="nf">isDebug</span><span class="p">():</span> <span class="n">Boolean</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="k">true</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">override</span> <span class="k">fun</span> <span class="nf">startActivity</span><span class="p">(</span><span class="n">context</span><span class="p">:</span> <span class="n">Context</span><span class="p">?,</span> <span class="n">url</span><span class="p">:</span> <span class="n">String</span><span class="p">?,</span> <span class="n">requestCode</span><span class="p">:</span> <span class="n">Int</span><span class="p">):</span> <span class="n">Boolean</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="k">false</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">override</span> <span class="k">fun</span> <span class="nf">getSettings</span><span class="p">():</span> <span class="n">MutableMap</span><span class="p">&lt;</span><span class="n">Any</span><span class="p">?,</span> <span class="n">Any</span><span class="p">?&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="n">HashMap</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Then point the manifest at this Application</p>
</li>
<li>
<p>Add a weak reference in MainActivity to hold <code>MainActivity</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MainActivity</span> <span class="p">:</span> <span class="n">AppCompatActivity</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">:</span> <span class="n">Bundle</span><span class="p">?)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">super</span><span class="p">.</span><span class="n">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="n">setContentView</span><span class="p">(</span><span class="nc">R</span><span class="p">.</span><span class="n">layout</span><span class="p">.</span><span class="n">activity_main</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="n">sRef</span> <span class="p">=</span> <span class="n">WeakReference</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">companion</span> <span class="k">object</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="k">var</span> <span class="py">sRef</span><span class="p">:</span> <span class="n">WeakReference</span><span class="p">&lt;</span><span class="n">Activity</span><span class="p">?&gt;</span> <span class="p">=</span> <span class="n">WeakReference</span><span class="p">(</span><span class="k">null</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></li>
<li>
<p>Create FlutterPageActivity, and remember to add it to the manifest</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">FlutterPageActivity</span><span class="p">:</span><span class="n">BoostFlutterActivity</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">override</span> <span class="k">fun</span> <span class="nf">getContainerParams</span><span class="p">():</span> <span class="n">MutableMap</span><span class="p">&lt;</span><span class="n">Any</span><span class="p">?,</span> <span class="n">Any</span><span class="p">?&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="n">HashMap</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">override</span> <span class="k">fun</span> <span class="nf">onRegisterPlugins</span><span class="p">(</span><span class="n">registry</span><span class="p">:</span> <span class="n">PluginRegistry</span><span class="p">?)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nc">GeneratedPluginRegistrant</span><span class="p">.</span><span class="n">registerWith</span><span class="p">(</span><span class="n">registry</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">override</span> <span class="k">fun</span> <span class="nf">getContainerName</span><span class="p">():</span> <span class="n">String</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="s2">&#34;flutterPage&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></li>
<li>
<p>Give the textview an id in the layout</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl">        android:text=&#34;Hello World!&#34;
</span></span><span class="line"><span class="cl">        android:id=&#34;@+id/tvHello&#34;
</span></span><span class="line"><span class="cl">        app:layout_constraintBottom_toBottomOf=&#34;parent&#34;
</span></span></code></pre></div></li>
<li>
<p>Add a click listener in MainActivity</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="n">tvHello</span><span class="p">.</span><span class="n">setOnClickListener</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">startActivity</span><span class="p">(</span><span class="n">Intent</span><span class="p">(</span><span class="n">applicationContext</span><span class="p">,</span> <span class="n">FlutterPageActivity</span><span class="o">::</span><span class="k">class</span><span class="p">.</span><span class="n">java</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></li>
<li>
<p>Run the Android project. If you hit errors, fix them following the prompts.</p>
</li>
<li>
<p>Click <code>Hello world</code> and a Flutter page opens. At this point you&rsquo;ve gone from a native page to a Flutter page.</p>
</li>
<li>
<p>Change the startActivity function in MyApplication to the code below:</p>
</li>
</ol>
<pre tabindex="0"><code> override fun startActivity(context: Context?, url: String?, requestCode: Int): Boolean {
        if (url?.contains(&#34;sample://nativePage&#34;) == true) {
            context?.startActivity(Intent(context, MainActivity::class.java))
            return true
        }
        return false
    }
</code></pre><p>Click <code>open native page</code> in the Flutter page and the activity reopens.</p>
<p>That&rsquo;s the round trip between both sides done. Welcome to the Flutter pit.</p>
]]></content:encoded></item><item><title>Flutter Plugin Development -- The Android Edition</title><link>http://mings.in/en/posts/flutter-plugin-development-for-android/</link><pubDate>Sat, 16 Jun 2018 09:00:00 +0800</pubDate><guid>http://mings.in/en/posts/flutter-plugin-development-for-android/</guid><description>A walkthrough of plugin development using QR code scanning as the example</description><content:encoded><![CDATA[<p>Flutter is not fully featured yet, and many common third-party libraries have no equivalent in Flutter. So how do you use an existing native library from Flutter? This post walks through Flutter plugin development using QR code scanning as the example.</p>
<h2 id="creating-a-plugin-project">Creating a Plugin project</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">flutter create --org mingsin.scan --template<span class="o">=</span>plugin  -i swift -a kotlin scan
</span></span></code></pre></div><p>Open the newly created project and you will see this code:</p>
<p><code>lib/scan.dart</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-dart" data-lang="dart"><span class="line"><span class="cl"><span class="k">import</span> <span class="s1">&#39;dart:async&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">import</span> <span class="s1">&#39;package:flutter/services.dart&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">Scan</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kd">static</span> <span class="kd">const</span> <span class="n">MethodChannel</span> <span class="n">_channel</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">      <span class="kd">const</span> <span class="n">MethodChannel</span><span class="p">(</span><span class="s1">&#39;scan&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">static</span> <span class="n">Future</span><span class="o">&lt;</span><span class="kt">String</span><span class="o">&gt;</span> <span class="kd">get</span> <span class="n">platformVersion</span> <span class="kd">async</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">final</span> <span class="kt">String</span> <span class="n">version</span> <span class="o">=</span> <span class="kd">await</span> <span class="n">_channel</span><span class="p">.</span><span class="n">invokeMethod</span><span class="p">(</span><span class="s1">&#39;getPlatformVersion&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">version</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><code>android/src/..../ScanPlugin.kt</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">ScanPlugin</span><span class="p">():</span> <span class="n">MethodCallHandler</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">companion</span> <span class="k">object</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nd">@JvmStatic</span>
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">registerWith</span><span class="p">(</span><span class="n">registrar</span><span class="p">:</span> <span class="n">Registrar</span><span class="p">):</span> <span class="n">Unit</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">val</span> <span class="py">channel</span> <span class="p">=</span> <span class="n">MethodChannel</span><span class="p">(</span><span class="n">registrar</span><span class="p">.</span><span class="n">messenger</span><span class="p">(),</span> <span class="s2">&#34;scan&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="n">channel</span><span class="p">.</span><span class="n">setMethodCallHandler</span><span class="p">(</span><span class="n">ScanPlugin</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">override</span> <span class="k">fun</span> <span class="nf">onMethodCall</span><span class="p">(</span><span class="n">call</span><span class="p">:</span> <span class="n">MethodCall</span><span class="p">,</span> <span class="n">result</span><span class="p">:</span> <span class="n">Result</span><span class="p">):</span> <span class="n">Unit</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">call</span><span class="p">.</span><span class="n">method</span><span class="p">.</span><span class="n">equals</span><span class="p">(</span><span class="s2">&#34;getPlatformVersion&#34;</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">result</span><span class="p">.</span><span class="n">success</span><span class="p">(</span><span class="s2">&#34;Android </span><span class="si">${android.os.Build.VERSION.RELEASE}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">result</span><span class="p">.</span><span class="n">notImplemented</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>From that code you can see clearly that Flutter does cross-language calls by providing a <code>MethodChannel</code>.
In the Kotlin code there is a class called <code>ScanPlugin</code> that inherits from <code>MethodCallHandler</code>. It first registers a channel called scan with Flutter, then in <code>onMethodCall</code> checks whether the method name is <code>getPlatformVersion</code> and returns the Android OS version if so.</p>
<p>In Dart, get a <code>MethodChannel</code> registered under the name <code>scan</code>. Then use <code>_channel.invokeMethod('getPlatformVersion');</code> to get the result of the corresponding function.</p>
<p>From that analysis you can already see that adding a function called <code>codescan</code> is all it takes.</p>
<h2 id="adding-the-codescan-function">Adding the <code>codescan</code> function</h2>
<h3 id="run-this-command-first">Run this command first</h3>
<pre><code>```shell
cd example; 
flutter build apk
```
</code></pre>
<h3 id="import-the-android-plugin-project">Import the Android Plugin project</h3>
<ol>
<li>Open Android Studio</li>
<li>Choose Import project, then select the <code>example/android/build.gradle</code> file</li>
<li>In the Gradle Sync window, choose OK</li>
<li>In the Android Gradle Plugin Update window, choose Don’t remind me again for this project</li>
</ol>
<p>Now you can run the example project.</p>
<h3 id="add-the-function-in-libscandart">Add the function in <code>lib/scan.dart</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-dart" data-lang="dart"><span class="line"><span class="cl">  <span class="kd">static</span> <span class="n">Future</span> <span class="n">codeScan</span><span class="p">()</span> <span class="kd">async</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">await</span> <span class="n">_channel</span><span class="p">.</span><span class="n">invokeMethod</span><span class="p">(</span><span class="s1">&#39;codeScan&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span></code></pre></div><h3 id="implement-it-in-scanpluginkt">Implement it in <code>ScanPlugin.kt</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">ScanPlugin</span><span class="p">(</span><span class="k">private</span> <span class="k">val</span> <span class="py">registrar</span><span class="p">:</span> <span class="n">Registrar</span><span class="p">)</span> <span class="p">:</span> <span class="n">MethodCallHandler</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">companion</span> <span class="k">object</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nd">@JvmStatic</span>
</span></span><span class="line"><span class="cl">        <span class="k">fun</span> <span class="nf">registerWith</span><span class="p">(</span><span class="n">registrar</span><span class="p">:</span> <span class="n">Registrar</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">val</span> <span class="py">channel</span> <span class="p">=</span> <span class="n">MethodChannel</span><span class="p">(</span><span class="n">registrar</span><span class="p">.</span><span class="n">messenger</span><span class="p">(),</span> <span class="s2">&#34;scan&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">channel</span><span class="p">.</span><span class="n">setMethodCallHandler</span><span class="p">(</span><span class="n">ScanPlugin</span><span class="p">(</span><span class="n">registrar</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onMethodCall</span><span class="p">(</span><span class="n">call</span><span class="p">:</span> <span class="n">MethodCall</span><span class="p">,</span> <span class="n">result</span><span class="p">:</span> <span class="n">Result</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">when</span> <span class="p">(</span><span class="n">call</span><span class="p">.</span><span class="n">method</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;getPlatformVersion&#34;</span> <span class="o">-&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">result</span><span class="p">.</span><span class="n">success</span><span class="p">(</span><span class="s2">&#34;Android </span><span class="si">${android.os.Build.VERSION.RELEASE}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;codeScan&#34;</span> <span class="o">-&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">IntentIntegrator</span><span class="p">(</span><span class="n">registrar</span><span class="p">.</span><span class="n">activity</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">                        <span class="p">.</span><span class="n">setDesiredBarcodeFormats</span><span class="p">(</span><span class="nc">IntentIntegrator</span><span class="p">.</span><span class="n">ONE_D_CODE_TYPES</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                        <span class="p">.</span><span class="n">initiateScan</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">else</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">                <span class="n">result</span><span class="p">.</span><span class="n">notImplemented</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="call-it-from-examplelibmaindart">Call it from <code>example/lib/main.dart</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl">         body: new Center(
</span></span><span class="line"><span class="cl"><span class="gd">-          child: new Text(&#39;Running on: $_platformVersion\n&#39;),
</span></span></span><span class="line"><span class="cl"><span class="gi">+          child: RaisedButton(
</span></span></span><span class="line"><span class="cl"><span class="gi">+            onPressed: () async {
</span></span></span><span class="line"><span class="cl"><span class="gi">+              await Scan.codeScan();
</span></span></span><span class="line"><span class="cl"><span class="gi">+            },
</span></span></span><span class="line"><span class="cl"><span class="gi">+            child: Text(&#34;Scan&#34;),
</span></span></span><span class="line"><span class="cl"><span class="gi">+          ),
</span></span></span><span class="line"><span class="cl">         ),
</span></span><span class="line"><span class="cl">       ),
</span></span></code></pre></div><p>Reload the project and you should see this screen:
<img alt="flutter code scan" loading="lazy" src="/images/flutter-scan-button.png">
Tap the Scan button and the QR code scanning screen appears.</p>
<p><img alt="flutter scan camera" loading="lazy" src="/images/flutter-scan-camera.png"></p>
<p>At this point you can call a third-party library from Dart to do real work.</p>
<p>How do you get a return value back from the third-party library? MethodHandler provides a result class to pass values back, and you only need to pass what you need in the success function. If you also need the return value from onActivity, you can do it with PluginRegistry.ActivityResultListener.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onMethodCall</span><span class="p">(</span><span class="n">call</span><span class="p">:</span> <span class="n">MethodCall</span><span class="p">,</span> <span class="n">result</span><span class="p">:</span> <span class="n">Result</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">when</span> <span class="p">(</span><span class="n">call</span><span class="p">.</span><span class="n">method</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;getPlatformVersion&#34;</span> <span class="o">-&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">result</span><span class="p">.</span><span class="n">success</span><span class="p">(</span><span class="s2">&#34;Android </span><span class="si">${android.os.Build.VERSION.RELEASE}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;codeScan&#34;</span> <span class="o">-&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">listener</span><span class="p">.</span><span class="n">result</span> <span class="o">==</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="n">registrar</span><span class="p">.</span><span class="n">addActivityResultListener</span><span class="p">(</span><span class="n">listener</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="n">listener</span><span class="p">.</span><span class="n">result</span> <span class="p">=</span> <span class="n">result</span>
</span></span><span class="line"><span class="cl">                <span class="n">IntentIntegrator</span><span class="p">(</span><span class="n">registrar</span><span class="p">.</span><span class="n">activity</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">                        <span class="p">.</span><span class="n">setDesiredBarcodeFormats</span><span class="p">(</span><span class="nc">IntentIntegrator</span><span class="p">.</span><span class="n">ONE_D_CODE_TYPES</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                        <span class="p">.</span><span class="n">initiateScan</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">else</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">                <span class="n">result</span><span class="p">.</span><span class="n">notImplemented</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">private</span> <span class="k">val</span> <span class="py">listener</span> <span class="p">=</span> <span class="k">object</span> <span class="err">: </span><span class="nc">PluginRegistry</span><span class="p">.</span><span class="n">ActivityResultListener</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">var</span> <span class="py">result</span><span class="p">:</span> <span class="n">Result</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span>
</span></span><span class="line"><span class="cl">        <span class="k">override</span> <span class="k">fun</span> <span class="nf">onActivityResult</span><span class="p">(</span><span class="n">requestCode</span><span class="p">:</span> <span class="n">Int</span><span class="p">,</span> <span class="n">resultCode</span><span class="p">:</span> <span class="n">Int</span><span class="p">,</span> <span class="n">intent</span><span class="p">:</span> <span class="n">Intent</span><span class="p">?):</span> <span class="n">Boolean</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">val</span> <span class="py">intentResult</span> <span class="p">=</span> <span class="nc">IntentIntegrator</span><span class="p">.</span><span class="n">parseActivityResult</span><span class="p">(</span><span class="n">requestCode</span><span class="p">,</span> <span class="n">intent</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">result</span><span class="o">?.</span><span class="n">success</span><span class="p">(</span><span class="n">intentResult</span><span class="p">.</span><span class="n">contents</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="k">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span></code></pre></div>]]></content:encoded></item><item><title>An Introduction to the Flutter Widgets Framework</title><link>http://mings.in/en/posts/flutter-widgets-framework/</link><pubDate>Mon, 11 Jun 2018 09:00:00 +0800</pubDate><guid>http://mings.in/en/posts/flutter-widgets-framework/</guid><description>A quick introduction to the Flutter widgets framework, and how Flutter builds complex UI by composing widgets.</description><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Flutter widgets were inspired by <a href="http://facebook.github.io/react/">React</a>, and turned into the reactive framework everyone uses today. The core idea is that all UI is created with widgets. Every widget provides its current configuration and state. When a widget changes, the system computes the smallest change in the render tree behind that widget from the previous state to the current one, and rebuilds accordingly. So in Flutter, all UI is built by composing widgets. <strong><a href="https://flutter.io/widgets/">See all the widgets</a></strong></p>
<h2 id="a-hello-world">A Hello World</h2>
<p>Copy the code below into <code>lib/main.dart</code> in a new project and run it to see the result. <strong>(If you have not created a project yet, follow <a href="/en/posts/how-to-setup-development-environment/">the steps here</a> to create one)</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-dart" data-lang="dart"><span class="line"><span class="cl"><span class="k">import</span> <span class="s1">&#39;package:flutter/material.dart&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">runApp</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="k">new</span> <span class="n">Text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="s1">&#39;Hello, world!&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nl">textDirection:</span> <span class="n">TextDirection</span><span class="p">.</span><span class="n">ltr</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><img alt="Hello world" loading="lazy" src="/images/flutter-hello-world-1.png">
In the main function we pass a text widget to <code>runApp</code> and get the result above.
What if we want <code>Hello, world!</code> centered? As I said earlier, in Flutter we compose widgets. Here we need a widget called <code>Center</code>, and whatever component sits inside it shows up in the middle of that component. Let&rsquo;s change the code:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-dart" data-lang="dart"><span class="line"><span class="cl"><span class="k">import</span> <span class="s1">&#39;package:flutter/material.dart&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">runApp</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">   <span class="n">Center</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="nl">child:</span> <span class="n">Text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;Hello, world!&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nl">textDirection:</span> <span class="n">TextDirection</span><span class="p">.</span><span class="n">ltr</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The result:
<img alt="Hello world 2" loading="lazy" src="/images/flutter-hello-world-2.png">
<em>Sharp-eyed readers may have noticed that the <code>new</code> keyword on <code>Center</code> and <code>Text</code> disappeared in this snippet. That is Dart 2 syntactic sugar letting us drop <code>new</code>.</em></p>
<p>We put <code>Text</code> in the <code>child</code> property of the <code>Center</code> widget, and now the text is centered. Could not be simpler. At this point we have touched two kinds of widgets: <code>Text</code>, which displays content, and <code>Center</code>, which handles layout. In Flutter development we use this kind of composition heavily to get the effect we want. Next we want a white background and blue text. <strong><a href="https://flutter.io/widgets/layout/">More layout widgets</a></strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-dart" data-lang="dart"><span class="line"><span class="cl"><span class="k">import</span> <span class="s1">&#39;package:flutter/material.dart&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">runApp</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">Container</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="nl">color:</span> <span class="n">Colors</span><span class="p">.</span><span class="n">white</span><span class="p">,</span> <span class="c1">// background color
</span></span></span><span class="line"><span class="cl">      <span class="nl">child:</span> <span class="n">Center</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="nl">child:</span> <span class="n">Text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">          <span class="s1">&#39;Hello, world!&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nl">textDirection:</span> <span class="n">TextDirection</span><span class="p">.</span><span class="n">ltr</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nl">style:</span> <span class="n">TextStyle</span><span class="p">(</span><span class="nl">color:</span> <span class="n">Colors</span><span class="p">.</span><span class="n">red</span><span class="p">),</span>  <span class="c1">// text color
</span></span></span><span class="line"><span class="cl">        <span class="p">),</span>
</span></span><span class="line"><span class="cl">      <span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><img alt="Hello world 3" loading="lazy" src="/images/flutter-hello-world-3.png">
To get a white background we add a <code>Container</code> widget and set its color to white. As you can see, Text has no color property but it does have style, so we build a TextStyle to turn the text red. TextStyle can change other font properties too — dig into it yourself.</p>
<p>How do we put a button under the text?</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-dart" data-lang="dart"><span class="line"><span class="cl"><span class="k">import</span> <span class="s1">&#39;package:flutter/material.dart&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">runApp</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">Container</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="nl">color:</span> <span class="n">Colors</span><span class="p">.</span><span class="n">white</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nl">child:</span> <span class="n">Center</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">          <span class="nl">child:</span> <span class="n">Column</span><span class="p">(</span> <span class="c1">// vertical layout
</span></span></span><span class="line"><span class="cl">        <span class="nl">mainAxisAlignment:</span> <span class="n">MainAxisAlignment</span><span class="p">.</span><span class="n">center</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nl">mainAxisSize:</span> <span class="n">MainAxisSize</span><span class="p">.</span><span class="n">min</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nl">children:</span> <span class="o">&lt;</span><span class="n">Widget</span><span class="o">&gt;</span><span class="p">[</span>
</span></span><span class="line"><span class="cl">          <span class="n">Text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="s1">&#39;Hello, world!&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nl">textDirection:</span> <span class="n">TextDirection</span><span class="p">.</span><span class="n">ltr</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nl">style:</span> <span class="n">TextStyle</span><span class="p">(</span><span class="nl">color:</span> <span class="n">Colors</span><span class="p">.</span><span class="n">red</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">          <span class="p">),</span>
</span></span><span class="line"><span class="cl">          <span class="n">RaisedButton</span><span class="p">(</span> <span class="c1">// button
</span></span></span><span class="line"><span class="cl">            <span class="nl">child:</span> <span class="n">Text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">              <span class="s1">&#39;Say Hello&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">              <span class="nl">textDirection:</span> <span class="n">TextDirection</span><span class="p">.</span><span class="n">ltr</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="nl">onPressed:</span> <span class="kc">null</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">],</span>
</span></span><span class="line"><span class="cl">      <span class="p">)),</span>
</span></span><span class="line"><span class="cl">    <span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><img alt="Hello world 4" loading="lazy" src="/images/flutter-hello-world-4.png">
From the code you can see we added a <code>Column</code> to stack multiple widgets vertically, which is why its child property becomes a List called <code>children</code>. Then the button: we want a label on it, so we add a <code>Text</code> widget for that too. If you have read this far patiently, you basically have a foothold in Flutter development. Even more complex pages are built the same way, by composing widgets — maybe with more complicated widgets.</p>
<p>Notice anything? We did not use an <code>xml</code> or <code>xib</code> file, and we got this interface built with no effort. If we built the same screen in Java or Swift, how much code would that take?</p>
]]></content:encoded></item><item><title>Flutter Project Structure</title><link>http://mings.in/en/posts/flutter-project-structure/</link><pubDate>Sat, 09 Jun 2018 09:00:00 +0800</pubDate><guid>http://mings.in/en/posts/flutter-project-structure/</guid><description>The project directory layout, and what the main files contain</description><content:encoded><![CDATA[<h1 id="flutter-project-structure">Flutter Project Structure</h1>
<h2 id="main-directories-and-files">Main directories and files</h2>
<p><img loading="lazy" src="/images/pic-flutter-project-structure.png"></p>
<ol>
<li><code>android</code> Android platform code</li>
<li><code>ios</code> iOS platform code</li>
<li><code>build</code> produced by the build, ignore it</li>
<li><code>lib</code> cross-platform code, the directory you actually care about in a Flutter project</li>
<li><code>test</code> test code</li>
<li><code>pubspec.yaml</code> the project manifest, equivalent to <code>package.json</code> in a Node.js project. It holds the project description and the libraries it depends on</li>
</ol>
<h2 id="the-main-files">The main files</h2>
<h3 id="pubspecyaml"><code>pubspec.yaml</code></h3>
<p><img loading="lazy" src="/images/pic-flutter-pubspec.png"></p>
<h3 id="maindart"><code>main.dart</code></h3>
<p>Flutter is written in <code>dart</code> (later chapters will add more on dart). The image below shows the code after simplification. Three classes are enough for one app screen, and it runs on both iOS and Android at the same time. That simple. And <code>main.dart</code> is the entry file for every Flutter project: it cannot be deleted or renamed.
<img alt="pic-flutter-main" loading="lazy" src="/images/pic-flutter-main.png"></p>
]]></content:encoded></item><item><title>Setting Up Your Flutter Development Environment</title><link>http://mings.in/en/posts/how-to-setup-development-environment/</link><pubDate>Sun, 03 Jun 2018 09:00:00 +0800</pubDate><guid>http://mings.in/en/posts/how-to-setup-development-environment/</guid><description>Setting up the Flutter development environment</description><content:encoded><![CDATA[<h2 id="system-requirements">System requirements</h2>
<p>OS: macOS (64-bit). This walkthrough uses macOS as the example.<br>
Tools: <code>bash</code>,<code>git</code>,<code>curl</code>,<code>unzip</code></p>
<h2 id="get-the-flutter-sdk">Get the Flutter SDK</h2>
<ol>
<li>
<p>Download the latest SDK from the <a href="https://flutter.io/sdk-archive/#macos">Flutter SDK Archive</a> page.
Click <a href="https://storage.googleapis.com/flutter_infra/releases/beta/macos/flutter_macos_v0.4.4-beta.zip">flutter_macos_v0.4.4-beta.zip</a> to download, or</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"></code></pre></div></li>
</ol>
<p>curl -o ~/Downloads/flutter_macos_v0.4.4-beta.zip <a href="https://storage.googleapis.com/flutter_infra/releases/beta/macos/flutter_macos_v0.4.4-beta.zip">https://storage.googleapis.com/flutter_infra/releases/beta/macos/flutter_macos_v0.4.4-beta.zip</a></p>
<pre tabindex="0"><code>    
    **P.S. If the links above give you trouble, use the China mirror.**
    
    ```shell 
curl -o ~/Downloads/flutter_macos_v0.4.4-beta.zip  https://storage.flutter-io.cn/flutter_infra/releases/beta/macos/flutter_macos_v0.4.4-beta.zip
</code></pre><ol start="2">
<li>
<p>Unzip into whatever path you want</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"></code></pre></div></li>
</ol>
<p>cd ~/development
unzip ~/Downloads/flutter_macos_v0.4.4-beta.zip</p>
<pre tabindex="0"><code>3. Add `flutter` to PATH

    ```shell
export PATH=`pwd`/flutter/bin:$PATH
</code></pre><ol start="4">
<li>
<p>Run flutter doctor</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"></code></pre></div></li>
</ol>
<p>flutter doctor</p>
<pre tabindex="0"><code>
***If the steps above did not get you a working install, use these commands instead:***

```shell
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
git clone -b dev https://github.com/flutter/flutter.git
export PATH=&#34;$PWD/flutter/bin:$PATH&#34;
cd ./flutter
flutter doctor

####alternate mirror sites####
# export FLUTTER_STORAGE_BASE_URL=https://mirrors.sjtug.sjtu.edu.cn/
# export PUB_HOSTED_URL=https://dart-pub.mirrors.sjtug.sjtu.edu.cn/
</code></pre><h2 id="set-up-a-development-platform">Set up a development platform</h2>
<h3 id="ios">iOS</h3>
<h4 id="install-xcode">Install Xcode</h4>
<ol>
<li>
<p>Install Xcode from the <a href="https://itunes.apple.com/us/app/xcode/id497799835">App Store</a>.</p>
</li>
<li>
<p>Point the command line at the latest Xcode</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
</span></span></code></pre></div></li>
<li>
<p>Make sure you have accepted the Xcode license agreement</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">sudo xcodebuild -license
</span></span></code></pre></div></li>
</ol>
<h4 id="set-up-the-simulator">Set up the simulator</h4>
<ol>
<li>
<p>Launch the simulator from Launchpad, or with the command below</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"></code></pre></div></li>
</ol>
<p>open -a Simulator</p>
<pre tabindex="0"><code>
2. `flutter run` to run your app


### Android
#### Install Android Studio
Download and install [Android Studio](https://developer.android.com/studio/index.html)
#### Android device (Android 4.1 or newer)
1. Follow [this link](https://developer.android.com/studio/debug/dev-options.html) to enable developer mode and turn debugging on
2. Plug your phone into the computer
3. `flutter run` to run your app
</code></pre>]]></content:encoded></item><item><title>Continuous Delivery System Based on Gitlab</title><link>http://mings.in/en/posts/continuous-delivery-system-based-on-gitlab/</link><pubDate>Mon, 10 Apr 2017 09:00:00 +0800</pubDate><guid>http://mings.in/en/posts/continuous-delivery-system-based-on-gitlab/</guid><description>How to setup a Continuous delivery system</description><content:encoded><![CDATA[<h2 id="setup-gitlab"><a href="https://docs.gitlab.com/omnibus/docker/README.html">Setup Gitlab</a></h2>
<p><strong>Run the following command to install gitlab on your machine.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">sudo docker run -d --hostname 10.211.55.5 <span class="se">\
</span></span></span><span class="line"><span class="cl">-p 80:80 -p 443:443 -p 22:22 <span class="se">\
</span></span></span><span class="line"><span class="cl">--restart always gitlab/gitlab-ce
</span></span></code></pre></div><blockquote>
<p>Please follow <a href="https://docs.docker.com/engine/installation/">official installation docs</a> to install docker if it&rsquo;s not been installed.
Do NOT forget change <code>10.211.55.5</code> and <code>/srv/gitlab/</code> to your own.(I have a virtual machine with that ip.)
If your docker is behind a proxy, please see <a href="https://www.google.com/webhp?sourceid=chrome-instant&amp;ion=1&amp;espv=2&amp;ie=UTF-8#newwindow=1&amp;q=docker&#43;behind&#43;corporate&#43;proxy">the search results from Google</a>.</p>
</blockquote>
<p><strong>After several mins, access <code>http://10.211.55.5</code> (the host you set above), you will the following picture.</strong>
<img alt="pic-create-password" loading="lazy" src="/images/pic-create-password.png"></p>
<p><strong>Set your admin password, and login again.</strong></p>
<p><img alt="Gitlab Home Page" loading="lazy" src="/images/pic-gitlab-homepage.png"></p>
<p><strong>Create new project <code>hello-world</code> as the following:</strong></p>
<p><img alt="Create new project" loading="lazy" src="/images/pic-gitlab-create-project.png"></p>
<p>Once you create the project, follow the instruction to upload demo code to the repo. When you finish you will see a similar picture.</p>
<p><img alt="Gitlab project setup ci" loading="lazy" src="/images/pic-gitlab-project-setup-ci.png"></p>
<p>Click the <code>Set up CI</code> button, add the following code and commit.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">test</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">script</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">echo &#39;hello world&#39;</span><span class="w">
</span></span></span></code></pre></div><p>A pending icon will appear on the result page.</p>
<p><img alt="Gitlab commit pending to run" loading="lazy" src="/images/pic-gitlab-commit-pending-to-run.png"></p>
<p>Click the icon, you will see a <code>stuk</code> tag on your commit. That means you have to add gitlab-runner to this project.</p>
<p><img loading="lazy" src="/images/pic-gitlab-pipeline-stuk.png"></p>
<h2 id="setup-gitlab-runner">Setup Gitlab Runner</h2>
<ol>
<li>
<p>Open <code>CI/CD Pipeline</code> tab in project settings
<img alt="Gitlab project runner setup" loading="lazy" src="/images/pic-gitlab-project-ruuner-setup.png"></p>
</li>
<li>
<p>Install setup runner on your local machine</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">brew install gitlab-ci-multi-runner
</span></span></code></pre></div></li>
<li>
<p>Register your local machine as a runner to the gitlab</p>
<p><img alt="Gitlab runner register" loading="lazy" src="/images/pic-gitlab-runner-register.png"></p>
</li>
<li>
<p>Runner list</p>
<p><img alt="Project runner list" loading="lazy" src="/images/pic-gitlab-project-runner-list.png"></p>
</li>
<li>
<p>Go back to the <code>Pipelines</code> of your project and click the <code>retry</code> button</p>
<p><img loading="lazy" src="/images/pic-gitlab-pipelies-state.png"></p>
</li>
<li>
<p>You runner has been set up successfully when you see the picture
<img loading="lazy" src="/images/pic-gitlab-pipeline-passed.png"></p>
</li>
<li>
<p>Change the <code>.gitlab-ci.yml</code> to the following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">test</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">script</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">./gradlew aR</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">artifacts</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">paths</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">app/build/outputs/apk/app-release*.apk</span><span class="w">
</span></span></span></code></pre></div></li>
<li>
<p>Now you will get the release apk file from the download button.
<img loading="lazy" src="/images/pic-gitlab-pipeline-with-artifats.png"></p>
</li>
</ol>
]]></content:encoded></item><item><title>Kotlin &amp; Dagger2</title><link>http://mings.in/en/posts/kotlin-with-dagger2/</link><pubDate>Fri, 17 Feb 2017 09:00:00 +0800</pubDate><guid>http://mings.in/en/posts/kotlin-with-dagger2/</guid><description>Integrate rxjava to kotlin project</description><content:encoded><![CDATA[<blockquote>
<p><em><strong>The project is based on the code complete in last article. You can download from <a href="https://github.com/trevorwang/android-kotlin-example/tree/rxjava-retrofit">here</a></strong></em></p>
</blockquote>
<h3 id="add-dependencies-to-your-buildgradle">Add Dependencies to your <code>build.gradle</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gradle" data-lang="gradle"><span class="line"><span class="cl"> <span class="n">kapt</span> <span class="s1">&#39;com.google.dagger:dagger-compiler:2.9&#39;</span>
</span></span><span class="line"><span class="cl"> <span class="n">compile</span> <span class="s1">&#39;com.google.dagger:dagger:2.9&#39;</span>
</span></span></code></pre></div><h3 id="create-your-application-instead-of-default">Create your application instead of default</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">App</span> <span class="p">:</span> <span class="n">Application</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreate</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="update-your-manifest-file-to-enable-your-app">Update your manifest file to enable your App</h3>
<p>Add the following to your <code>application</code> tag</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl">     &lt;application
</span></span><span class="line"><span class="cl"><span class="gi">+        android:name=&#34;.App&#34;
</span></span></span><span class="line"><span class="cl">         android:allowBackup=&#34;true&#34;
</span></span><span class="line"><span class="cl">         android:icon=&#34;@mipmap/ic_launcher&#34;
</span></span><span class="line"><span class="cl">         android:label=&#34;@string/app_name&#34;
</span></span></code></pre></div><h3 id="create-application-module">Create Application module</h3>
<p>Create a <code>AppModule.kt</code> file and add the following code</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="nd">@Module</span>
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">AppModule</span><span class="p">(</span><span class="k">val</span> <span class="py">app</span><span class="p">:</span> <span class="n">App</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nd">@Provides</span>
</span></span><span class="line"><span class="cl">    <span class="nd">@Singleton</span>
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">app</span><span class="p">():</span> <span class="n">App</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">app</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nd">@Provides</span>
</span></span><span class="line"><span class="cl">    <span class="nd">@Singleton</span>
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">context</span><span class="p">():</span> <span class="n">Context</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">app</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nd">@Provides</span>
</span></span><span class="line"><span class="cl">    <span class="nd">@Singleton</span>
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">connectivity</span><span class="p">():</span> <span class="n">ConnectivityManager</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">service</span> <span class="p">=</span> <span class="n">app</span><span class="p">.</span><span class="n">getSystemService</span><span class="p">(</span><span class="nc">Context</span><span class="p">.</span><span class="n">CONNECTIVITY_SERVICE</span><span class="p">)</span> <span class="k">as</span> <span class="n">ConnectivityManager</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">service</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="create-component">Create component</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="nd">@Singleton</span>
</span></span><span class="line"><span class="cl"><span class="nd">@Component</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">modules</span> <span class="p">=</span> <span class="n">arrayOf</span><span class="p">(</span><span class="n">AppModule</span><span class="o">::</span><span class="k">class</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">interface</span> <span class="nc">AppComponent</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">inject</span><span class="p">(</span><span class="n">app</span><span class="p">:</span> <span class="n">App</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="update-your-code-in-appkt-to-enable-the-injection">Update your code in <code>App.kt</code> to enable the injection</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">  <span class="k">lateinit</span> <span class="k">var</span> <span class="py">component</span><span class="p">:</span> <span class="n">AppComponent</span>
</span></span><span class="line"><span class="cl">    <span class="k">lateinit</span> <span class="nd">@Inject</span> <span class="k">var</span> <span class="py">cm</span><span class="p">:</span> <span class="n">ConnectivityManager</span>
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreate</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">super</span><span class="p">.</span><span class="n">onCreate</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">component</span> <span class="p">=</span> <span class="nc">DaggerAppComponent</span><span class="p">.</span><span class="n">builder</span><span class="p">().</span><span class="n">appModule</span><span class="p">(</span><span class="n">AppModule</span><span class="p">(</span><span class="k">this</span><span class="p">)).</span><span class="n">build</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">component</span><span class="p">.</span><span class="n">inject</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nc">Logger</span><span class="p">.</span><span class="n">d</span><span class="p">(</span><span class="s2">&#34;connectivity manager : </span><span class="si">${cm}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span></code></pre></div><p>Now you can run your code in IDE, you will see the following in your console. You have completed your first injection for Application.</p>
<pre tabindex="0"><code>02-17 10:03:20.492 10572-10572/? D/PRETTYLOGGER: ╔════════════════════════════════════════════════════════════════════════════════════════
02-17 10:03:20.493 10572-10572/? D/PRETTYLOGGER: ║ Thread: main
02-17 10:03:20.493 10572-10572/? D/PRETTYLOGGER: ╟────────────────────────────────────────────────────────────────────────────────────────
02-17 10:03:20.493 10572-10572/? D/PRETTYLOGGER: ║ BootstrapApplication.onCreate  (BootstrapApplication.java:370)
02-17 10:03:20.493 10572-10572/? D/PRETTYLOGGER: ║    App.onCreate  (App.kt:21)
02-17 10:03:20.493 10572-10572/? D/PRETTYLOGGER: ╟────────────────────────────────────────────────────────────────────────────────────────
02-17 10:03:20.493 10572-10572/? D/PRETTYLOGGER: ║ connectivity manager : android.net.ConnectivityManager@39309b5
02-17 10:03:20.494 10572-10572/? D/PRETTYLOGGER: ╚════════════════════════════════════════════════════════════════════════════════════════
</code></pre><h3 id="follow-above-guide-to-create-activitymodule-and-activitycomponent">Follow above guide to create <code>ActivityModule</code> and <code>ActivityComponent</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="nd">@Module</span>
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">ActivityModule</span><span class="p">(</span><span class="k">val</span> <span class="py">activity</span><span class="p">:</span> <span class="n">DaggerActivity</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nd">@Provides</span>
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">activity</span><span class="p">():</span> <span class="n">DaggerActivity</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">activity</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nd">@Provides</span>
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">progressDialog</span><span class="p">():</span> <span class="n">ProgressDialog</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">progress</span> <span class="p">=</span> <span class="n">ProgressDialog</span><span class="p">(</span><span class="n">activity</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">progress</span><span class="p">.</span><span class="n">setMessage</span><span class="p">(</span><span class="n">activity</span><span class="p">.</span><span class="n">getString</span><span class="p">(</span><span class="nc">R</span><span class="p">.</span><span class="n">string</span><span class="p">.</span><span class="n">loading</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">progress</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="nd">@ForActivity</span>
</span></span><span class="line"><span class="cl"><span class="nd">@Component</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">modules</span> <span class="p">=</span> <span class="n">arrayOf</span><span class="p">(</span><span class="n">ActivityModule</span><span class="o">::</span><span class="k">class</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="n">dependencies</span> <span class="p">=</span> <span class="n">arrayOf</span><span class="p">(</span><span class="n">AppComponent</span><span class="o">::</span><span class="k">class</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">interface</span> <span class="nc">ActivityComponent</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">inject</span><span class="p">(</span><span class="n">activity</span><span class="p">:</span> <span class="n">MainActivity</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>You definately find there&rsquo;s a <code>@ForActivity</code> above the <code>ActivityComponent</code>. Dagger need you to set a scope to define the lifecycle for any component. Activity cannot be the singleton. So we define a scrope annotation called &lsquo;ForActivity&rsquo;.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="nd">@Qualifier</span>
</span></span><span class="line"><span class="cl"><span class="nd">@Retention</span><span class="p">(</span><span class="k">value</span> <span class="p">=</span> <span class="nc">AnnotationRetention</span><span class="p">.</span><span class="n">RUNTIME</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nd">@Scope</span>
</span></span><span class="line"><span class="cl"><span class="k">annotation</span> <span class="k">class</span> <span class="nc">ForActivity</span>
</span></span></code></pre></div><h3 id="use-activity-component-in-your-code">Use activity component in your code</h3>
<p>Create a base class called <code>DaggerActivity</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">abstract</span> <span class="k">class</span> <span class="nc">DaggerActivity</span> <span class="p">:</span> <span class="n">AppCompatActivity</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">var</span> <span class="py">component</span><span class="p">:</span> <span class="n">ActivityComponent</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span>
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">:</span> <span class="n">Bundle</span><span class="p">?)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">super</span><span class="p">.</span><span class="n">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">app</span> <span class="p">=</span> <span class="n">application</span> <span class="k">as</span> <span class="n">App</span>
</span></span><span class="line"><span class="cl">        <span class="n">component</span> <span class="p">=</span> <span class="nc">DaggerActivityComponent</span><span class="p">.</span><span class="n">builder</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="n">activityModule</span><span class="p">(</span><span class="n">ActivityModule</span><span class="p">(</span><span class="k">this</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="n">appComponent</span><span class="p">(</span><span class="n">app</span><span class="p">.</span><span class="n">component</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="n">build</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">onInject</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">abstract</span> <span class="k">fun</span> <span class="nf">onInject</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onDestroy</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">component</span> <span class="p">=</span> <span class="k">null</span>
</span></span><span class="line"><span class="cl">        <span class="k">super</span><span class="p">.</span><span class="n">onDestroy</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Update your <code>MainActivity</code> to extends <code>DaggerActivity</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MainActivity</span> <span class="p">:</span> <span class="n">DaggerActivity</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nd">@Inject</span> <span class="k">lateinit</span> <span class="k">var</span> <span class="py">apiService</span><span class="p">:</span> <span class="n">ApiService</span>
</span></span><span class="line"><span class="cl">    <span class="nd">@Inject</span> <span class="k">lateinit</span> <span class="k">var</span> <span class="py">cm</span><span class="p">:</span> <span class="n">ConnectivityManager</span>
</span></span><span class="line"><span class="cl">    <span class="nd">@Inject</span> <span class="k">lateinit</span> <span class="k">var</span> <span class="py">progressDialog</span><span class="p">:</span> <span class="n">ProgressDialog</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">private</span> <span class="k">val</span> <span class="py">subscriptions</span> <span class="p">=</span> <span class="n">CompositeSubscription</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">:</span> <span class="n">Bundle</span><span class="p">?)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">super</span><span class="p">.</span><span class="n">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">setContentView</span><span class="p">(</span><span class="nc">R</span><span class="p">.</span><span class="n">layout</span><span class="p">.</span><span class="n">activity_main</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">binding</span> <span class="p">=</span> <span class="nc">DataBindingUtil</span><span class="p">.</span><span class="n">setContentView</span><span class="p">&lt;</span><span class="n">ActivityMainBinding</span><span class="p">&gt;(</span><span class="k">this</span><span class="p">,</span> <span class="nc">R</span><span class="p">.</span><span class="n">layout</span><span class="p">.</span><span class="n">activity_main</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">binding</span><span class="p">.</span><span class="n">greating</span> <span class="p">=</span> <span class="s2">&#34;Hello Kotlin Data Binding!!!&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">toolbar</span> <span class="p">=</span> <span class="n">findViewById</span><span class="p">(</span><span class="nc">R</span><span class="p">.</span><span class="n">id</span><span class="p">.</span><span class="n">toolbar</span><span class="p">)</span> <span class="k">as</span> <span class="n">Toolbar</span>
</span></span><span class="line"><span class="cl">        <span class="n">setSupportActionBar</span><span class="p">(</span><span class="n">toolbar</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nc">Logger</span><span class="p">.</span><span class="n">d</span><span class="p">(</span><span class="n">cm</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onInject</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">component</span><span class="o">?.</span><span class="n">inject</span><span class="p">(</span><span class="k">this</span><span class="p">)</span> <span class="c1">// must call this
</span></span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onResume</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">super</span><span class="p">.</span><span class="n">onResume</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">progressDialog</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onStart</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">super</span><span class="p">.</span><span class="n">onStart</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">subscriptions</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">apiService</span><span class="p">.</span><span class="n">ip</span><span class="p">().</span><span class="n">subscribeOn</span><span class="p">(</span><span class="nc">Schedulers</span><span class="p">.</span><span class="n">io</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="n">observeOn</span><span class="p">(</span><span class="nc">AndroidSchedulers</span><span class="p">.</span><span class="n">mainThread</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="n">subscribe</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">                    <span class="n">ip</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">                    <span class="nc">Logger</span><span class="p">.</span><span class="n">d</span><span class="p">(</span><span class="s2">&#34;get result </span><span class="si">$ip</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                    <span class="n">progressDialog</span><span class="p">.</span><span class="n">hide</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">                <span class="p">})</span> <span class="p">{</span> <span class="n">error</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">                    <span class="nc">Logger</span><span class="p">.</span><span class="n">e</span><span class="p">(</span><span class="n">error</span><span class="p">,</span> <span class="s2">&#34;Aha.. got error message&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                    <span class="n">progressDialog</span><span class="p">.</span><span class="n">hide</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">                <span class="p">})</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onStop</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">super</span><span class="p">.</span><span class="n">onStop</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">subscriptions</span><span class="p">.</span><span class="n">clear</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Run code from you IDE, you will see the fowlloing error</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">Error:mingsin.androidkotlinexample.data.ApiService cannot be provided without an @Provides-annotated method.
</span></span><span class="line"><span class="cl">Error:mingsin.androidkotlinexample.data.ApiService cannot be provided without an @Provides- or @Produces-annotated method.
</span></span><span class="line"><span class="cl">Error:android.net.ConnectivityManager cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
</span></span></code></pre></div><p>Because <code>ConnectivityManager </code> and <code>ApiService </code> are provided in you app component, So we must tell the dagger that we provide the two instance.
Update your <code>AppComponent</code> code as following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="nd">@Singleton</span>
</span></span><span class="line"><span class="cl"><span class="nd">@Component</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">modules</span> <span class="p">=</span> <span class="n">arrayOf</span><span class="p">(</span><span class="n">AppModule</span><span class="o">::</span><span class="k">class</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">interface</span> <span class="nc">AppComponent</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">inject</span><span class="p">(</span><span class="n">app</span><span class="p">:</span> <span class="n">App</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">connectivity</span><span class="p">():</span> <span class="n">ConnectivityManager</span>
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">api</span><span class="p">():</span> <span class="n">ApiService</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Now you have complete a project integrated with dagger2. You can chekcout the whole project from <a href="https://github.com/trevorwang/android-kotlin-example/tree/kotlin-dagger">here</a></p>
<h4 id="references">References</h4>
<ol>
<li><a href="https://google.github.io/dagger/">Dagger2</a></li>
<li><a href="https://medium.com/@methodsignature/dagger-2-dependency-injection-for-android-developers-51d60e7397e6#.f4yp32sbb">Dagger 2 Dependency Injection for Android Developers</a></li>
<li><a href="https://github.com/codepath/android_guides/wiki/Dependency-Injection-with-Dagger-2">Dependency Injection with Dagger 2</a></li>
</ol>
]]></content:encoded></item><item><title>Kotlin &amp; RxJava &amp; Retrofit</title><link>http://mings.in/en/posts/kotlin-with-rxjava-and-retrofit/</link><pubDate>Thu, 16 Feb 2017 09:00:00 +0800</pubDate><guid>http://mings.in/en/posts/kotlin-with-rxjava-and-retrofit/</guid><description>Integrate rxjava to kotlin project</description><content:encoded><![CDATA[<h3 id="add-dependecies">Add Dependecies</h3>
<p>Add the following code into the <code>dependencies</code> block in your <code>build.gradle</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gradle" data-lang="gradle"><span class="line"><span class="cl"><span class="n">compile</span> <span class="s1">&#39;io.reactivex:rxkotlin:0.60.0&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">compile</span> <span class="s1">&#39;io.reactivex:rxandroid:1.2.1&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">compile</span> <span class="s1">&#39;com.squareup.retrofit2:retrofit:2.1.0&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">compile</span> <span class="s1">&#39;com.squareup.retrofit2:adapter-rxjava:2.1.0&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">compile</span> <span class="s1">&#39;com.squareup.retrofit2:converter-gson:2.1.0&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">compile</span> <span class="s1">&#39;com.orhanobut:logger:1.15&#39;</span>
</span></span></code></pre></div><h3 id="add-internet-permission-for-you-application">Add internet permission for you application</h3>
<p>Open you <code>AndroidManifest.xml</code> file and add the following line above your applicaiton tag.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"> <span class="nt">&lt;uses-permission</span> <span class="na">android:name=</span><span class="s">&#34;android.permission.INTERNET&#34;</span> <span class="nt">/&gt;</span>
</span></span></code></pre></div><h3 id="create-the-service-interface">Create the service interface</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">interface</span> <span class="nc">ApiService</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nd">@GET</span><span class="p">(</span><span class="s2">&#34;/ip&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">ip</span><span class="p">():</span> <span class="n">Observable</span><span class="p">&lt;</span><span class="n">Ip</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="create-model">Create model</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">data</span> <span class="k">class</span> <span class="nc">Ip</span><span class="p">(</span><span class="k">val</span> <span class="py">origin</span><span class="p">:</span> <span class="n">String</span><span class="p">)</span>
</span></span></code></pre></div><h3 id="create-retrofit-client">Create Retrofit client</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">RestClient</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">val</span> <span class="py">BASE</span><span class="n">_URL</span> <span class="p">=</span> <span class="s2">&#34;http://httpbin.org&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">fun</span> <span class="nf">createApi</span><span class="p">():</span> <span class="n">ApiService</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">retrofit</span> <span class="p">=</span> <span class="nc">Retrofit</span><span class="p">.</span><span class="n">Builder</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="n">baseUrl</span><span class="p">(</span><span class="n">BASE_URL</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="n">addCallAdapterFactory</span><span class="p">(</span><span class="nc">RxJavaCallAdapterFactory</span><span class="p">.</span><span class="n">create</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="n">addConverterFactory</span><span class="p">(</span><span class="nc">GsonConverterFactory</span><span class="p">.</span><span class="n">create</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="n">build</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">retrofit</span><span class="p">.</span><span class="n">create</span><span class="p">(</span><span class="n">ApiService</span><span class="o">::</span><span class="k">class</span><span class="p">.</span><span class="n">java</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="integrate-code-into-your-activity">Integrate code into your activity</h3>
<p>Init <code>ApiService</code> in your class</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl">	 class MainActivity : AppCompatActivity() {
</span></span><span class="line"><span class="cl">	+    lateinit var apiService: ApiService
</span></span><span class="line"><span class="cl">	+
</span></span><span class="line"><span class="cl">	+    private val subscriptions = CompositeSubscription()
</span></span><span class="line"><span class="cl">	 
</span></span><span class="line"><span class="cl">	     override fun onCreate(savedInstanceState: Bundle?) {
</span></span><span class="line"><span class="cl">	         super.onCreate(savedInstanceState)
</span></span><span class="line"><span class="cl">	@@ -27,25 +32,21 @@ class MainActivity : AppCompatActivity() {
</span></span><span class="line"><span class="cl">	             Snackbar.make(view, &#34;Replace with your own action&#34;, Snackbar.LENGTH_LONG)
</span></span><span class="line"><span class="cl">	                     .setAction(&#34;Action&#34;, null).show()
</span></span><span class="line"><span class="cl">	         }
</span></span><span class="line"><span class="cl">	+        apiService = RestClient().createApi()
</span></span><span class="line"><span class="cl">	     } 
</span></span></code></pre></div><p>Update the code in your <code>onStart</code> and <code>onStop</code> method.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onStart</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">super</span><span class="p">.</span><span class="n">onStart</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">subscriptions</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">apiService</span><span class="p">.</span><span class="n">ip</span><span class="p">().</span><span class="n">subscribeOn</span><span class="p">(</span><span class="nc">Schedulers</span><span class="p">.</span><span class="n">io</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="n">observeOn</span><span class="p">(</span><span class="nc">AndroidSchedulers</span><span class="p">.</span><span class="n">mainThread</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="n">subscribe</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="nc">Logger</span><span class="p">.</span><span class="n">d</span><span class="p">(</span><span class="k">it</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">})</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onStop</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">super</span><span class="p">.</span><span class="n">onStop</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">subscriptions</span><span class="p">.</span><span class="n">clear</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span></code></pre></div><h3 id="run-you-application-you-will-see-the-message-on-console">Run you application you will see the message on console</h3>
<pre tabindex="0"><code class="language-sonsole" data-lang="sonsole">02-16 15:03:32.529 15858-15858/mingsin.androidkotlinexample D/PRETTYLOGGER: ╔════════════════════════════════════════════════════════════════════════════════════════
02-16 15:03:32.530 15858-15858/mingsin.androidkotlinexample D/PRETTYLOGGER: ║ Thread: main
02-16 15:03:32.530 15858-15858/mingsin.androidkotlinexample D/PRETTYLOGGER: ╟────────────────────────────────────────────────────────────────────────────────────────
02-16 15:03:32.530 15858-15858/mingsin.androidkotlinexample D/PRETTYLOGGER: ║ MainActivity$onStart$1.call  (MainActivity.kt:15)
02-16 15:03:32.530 15858-15858/mingsin.androidkotlinexample D/PRETTYLOGGER: ║    MainActivity$onStart$1.call  (MainActivity.kt:44)
02-16 15:03:32.530 15858-15858/mingsin.androidkotlinexample D/PRETTYLOGGER: ╟────────────────────────────────────────────────────────────────────────────────────────
02-16 15:03:32.530 15858-15858/mingsin.androidkotlinexample D/PRETTYLOGGER: ║ Ip(origin=20x.xx.xx.xx, 20x.xx.xx.xx)
02-16 15:03:32.530 15858-15858/mingsin.androidkotlinexample D/PRETTYLOGGER: ╚════════════════════════════════════════════════════════════════════════════════════════
02-16 15:03:33.025 15858-15858/mingsin.androidkotlinexample D/KeyEvent: obtain, mHwFlags=0
</code></pre><p>You can find the full version code from <a href="https://github.com/trevorwang/android-kotlin-example/tree/rxjava-retrofit">here</a></p>
]]></content:encoded></item><item><title>Kotlin &amp; Databinding</title><link>http://mings.in/en/posts/kotlin-data-binding/</link><pubDate>Sun, 05 Feb 2017 09:00:00 +0800</pubDate><guid>http://mings.in/en/posts/kotlin-data-binding/</guid><description>Enable Databinding in a Kotlin Android Project</description><content:encoded><![CDATA[<h1 id="kotlin--databinding">Kotlin  DataBinding</h1>
<h3 id="create-android-kotlin-project">Create Android Kotlin Project</h3>
<p>Please following[Dancing with kotlin] to create a new project. Or  clone the project [https://github.com/trevorwang/android-kotlin-example], checkout <code>kotlin-init</code></p>
<h3 id="update-buildgradle">Update <code>build.gradle</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl"> buildscript {
</span></span><span class="line"><span class="cl">	 ext.kotlin_version = &#39;1.0.6&#39;
</span></span><span class="line"><span class="cl"><span class="gi">+    ext.gradle_version = &#39;2.2.3&#39;
</span></span></span><span class="line"><span class="cl">	 repositories {
</span></span><span class="line"><span class="cl">		 jcenter()
</span></span><span class="line"><span class="cl">	 }
</span></span><span class="line"><span class="cl">	 dependencies {
</span></span><span class="line"><span class="cl"><span class="gd">- 	   classpath &#39;com.android.tools.build:gradle:2.2.3&#39;
</span></span></span><span class="line"><span class="cl"><span class="gi">+ 	   classpath &#34;com.android.tools.build:gradle:$gradle_version&#34;
</span></span></span><span class="line"><span class="cl">		 classpath &#34;org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version&#34;
</span></span></code></pre></div><h3 id="update-appbuildgradle-to-enable-data-binding">update <code>app/build.gradle</code> to enable data binding</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="cl">     sourceSets {
</span></span><span class="line"><span class="cl">         main.java.srcDirs += &#39;src/main/kotlin&#39;
</span></span><span class="line"><span class="cl">     }
</span></span><span class="line"><span class="cl"><span class="gi">+
</span></span></span><span class="line"><span class="cl"><span class="gi">+    dataBinding {
</span></span></span><span class="line"><span class="cl"><span class="gi">+        enabled = true
</span></span></span><span class="line"><span class="cl"><span class="gi">+    }
</span></span></span><span class="line"><span class="cl"><span class="gi">+}
</span></span></span><span class="line"><span class="cl"><span class="gi">+kapt {
</span></span></span><span class="line"><span class="cl"><span class="gi">+    generateStubs = true
</span></span></span><span class="line"><span class="cl"> }
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">  dependencies {
</span></span><span class="line"><span class="cl"><span class="gu">@@ -32,6 +39,7 @@ dependencies {
</span></span></span><span class="line"><span class="cl">     compile &#39;com.android.support:design:25.1.1&#39;
</span></span><span class="line"><span class="cl">     testCompile &#39;junit:junit:4.12&#39;
</span></span><span class="line"><span class="cl">     compile &#34;org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version&#34;
</span></span><span class="line"><span class="cl"><span class="gi">+    kapt &#34;com.android.databinding:compiler:$gradle_version&#34;
</span></span></span><span class="line"><span class="cl"> }
</span></span></code></pre></div><h3 id="update-mainactivitykt">update <code>MainActivity.kt</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MainActivity</span> <span class="p">:</span> <span class="n">AppCompatActivity</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">:</span> <span class="n">Bundle</span><span class="p">?)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">super</span><span class="p">.</span><span class="n">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">binding</span> <span class="p">=</span> <span class="nc">DataBindingUtil</span><span class="p">.</span><span class="n">setContentView</span><span class="p">&lt;</span><span class="n">ActivityMainBinding</span><span class="p">&gt;(</span><span class="k">this</span><span class="p">,</span> <span class="nc">R</span><span class="p">.</span><span class="n">layout</span><span class="p">.</span><span class="n">activity_main</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">binding</span><span class="p">.</span><span class="n">greeting</span> <span class="p">=</span> <span class="s2">&#34;Hello Kotlin Data Binding!!!&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="update-activity_mainxml">update <code>activity_main.xml</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="cp">&lt;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;layout&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;data&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;variable</span>
</span></span><span class="line"><span class="cl">            <span class="na">name=</span><span class="s">&#34;greeting&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">type=</span><span class="s">&#34;String&#34;</span> <span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/data&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;android.support.design.widget.CoordinatorLayout</span> <span class="na">xmlns:android=</span><span class="s">&#34;http://schemas.android.com/apk/res/android&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="na">xmlns:app=</span><span class="s">&#34;http://schemas.android.com/apk/res-auto&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="na">xmlns:tools=</span><span class="s">&#34;http://schemas.android.com/tools&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="na">android:layout_width=</span><span class="s">&#34;match_parent&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="na">android:layout_height=</span><span class="s">&#34;match_parent&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="na">android:fitsSystemWindows=</span><span class="s">&#34;true&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="na">tools:context=</span><span class="s">&#34;mingsin.androidkotlinexample.MainActivity&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;android.support.design.widget.AppBarLayout</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:layout_width=</span><span class="s">&#34;match_parent&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:layout_height=</span><span class="s">&#34;wrap_content&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:theme=</span><span class="s">&#34;@style/AppTheme.AppBarOverlay&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;android.support.v7.widget.Toolbar</span>
</span></span><span class="line"><span class="cl">                <span class="na">android:id=</span><span class="s">&#34;@+id/toolbar&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="na">android:layout_width=</span><span class="s">&#34;match_parent&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="na">android:layout_height=</span><span class="s">&#34;?attr/actionBarSize&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="na">android:background=</span><span class="s">&#34;?attr/colorPrimary&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="na">app:popupTheme=</span><span class="s">&#34;@style/AppTheme.PopupOverlay&#34;</span> <span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;/android.support.design.widget.AppBarLayout&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;RelativeLayout</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:id=</span><span class="s">&#34;@+id/content_main&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:layout_width=</span><span class="s">&#34;match_parent&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:layout_height=</span><span class="s">&#34;match_parent&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:paddingBottom=</span><span class="s">&#34;@dimen/activity_vertical_margin&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:paddingLeft=</span><span class="s">&#34;@dimen/activity_horizontal_margin&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:paddingRight=</span><span class="s">&#34;@dimen/activity_horizontal_margin&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:paddingTop=</span><span class="s">&#34;@dimen/activity_vertical_margin&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">app:layout_behavior=</span><span class="s">&#34;@string/appbar_scrolling_view_behavior&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">tools:context=</span><span class="s">&#34;mingsin.androidkotlinexample.MainActivity&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">tools:showIn=</span><span class="s">&#34;@layout/activity_main&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;TextView</span>
</span></span><span class="line"><span class="cl">                <span class="na">android:layout_width=</span><span class="s">&#34;wrap_content&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="na">android:layout_height=</span><span class="s">&#34;wrap_content&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="na">android:text=</span><span class="s">&#34;@{greeting}&#34;</span> <span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;/RelativeLayout&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;android.support.design.widget.FloatingActionButton</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:id=</span><span class="s">&#34;@+id/fab&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:layout_width=</span><span class="s">&#34;wrap_content&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:layout_height=</span><span class="s">&#34;wrap_content&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:layout_gravity=</span><span class="s">&#34;bottom|end&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">android:layout_margin=</span><span class="s">&#34;@dimen/fab_margin&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">app:srcCompat=</span><span class="s">&#34;@android:drawable/ic_dialog_email&#34;</span> <span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/android.support.design.widget.CoordinatorLayout&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/layout&gt;</span>
</span></span></code></pre></div><p>You can checkout whole source code from <a href="https://github.com/trevorwang/android-kotlin-example/tree/kotlin-databinding">here</a></p>
<h2 id="references">References</h2>
<p><a href="http://stackoverflow.com/questions/41213765/issue-with-databinding-using-kotlin-for-android">Issue with databinding using Kotlin for Android</a></p>
]]></content:encoded></item><item><title>Dancing with Kotlin</title><link>http://mings.in/en/posts/android-development-with-kotlin/</link><pubDate>Wed, 25 Jan 2017 09:00:00 +0800</pubDate><guid>http://mings.in/en/posts/android-development-with-kotlin/</guid><description>Develop Android application with kotlin</description><content:encoded><![CDATA[<h3 id="whats-kotlin">What&rsquo;s Kotlin?</h3>
<p>Statically typed programming language for the JVM, Android and the browser. <em><strong>100% interoperable with Java™</strong></em></p>
<h3 id="why-kotlin">Why Kotlin?</h3>
<ul>
<li><strong>Concise</strong><br>
Drastically reduce the amount of boilerplate code you need to write.</li>
<li><strong>Safe</strong><br>
Avoid entire classes of errors such as null pointer exceptions.</li>
<li><strong>Versatile</strong><br>
Build server-side applications, Android apps or frontend code running in the browser.</li>
<li><strong>Interoperable</strong><br>
Leverage existing frameworks and libraries of the JVM with 100% Java Interoperability.</li>
<li><strong>Tooling</strong><br>
Command Line Compiler or First Class IDE Support. Freedom to choose.</li>
</ul>
<h3 id="how-to">How to?</h3>
<h4 id="install-kotlin-plugin">Install kotlin plugin</h4>
<p>First, if using Android Studio, you&rsquo;ll need to install the Kotlin plugin. Go to File | Settings | Plugins | Install JetBrains plugin… and then search for and install Kotlin. You&rsquo;ll need to restart the IDE after this completes.</p>
<p><img alt="How to install plugin" loading="lazy" src="/images/pic-install-kotlin-plugin.png#center"></p>
<h4 id="creating-a-project">Creating a project</h4>
<p>Just create an Android project from the IDE.</p>
<h4 id="converting-java-code-to-kotlin">Converting Java code to Kotlin</h4>
<ul>
<li>Setup kotlin runtime, select &ldquo;Confure Kotlin in Project&rdquo;<br>
<img alt="Setup Kotlin runtime" loading="lazy" src="/images/pic-configure-kotlin-sdk.png#center"></li>
<li>Select All modules<br>
<img alt="Select modules" loading="lazy" src="/images/pic-select-modules.png#center"></li>
<li>Convert Java file to Kotlin file<br>
<img alt="Convert Java File to Kotlin File" loading="lazy" src="/images/pic-convert-java-files-kotlin-files.png#center"></li>
<li>The final code will be as following:</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">MainActivity</span> <span class="p">:</span> <span class="n">AppCompatActivity</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">:</span> <span class="n">Bundle</span><span class="p">?)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">super</span><span class="p">.</span><span class="n">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">setContentView</span><span class="p">(</span><span class="nc">R</span><span class="p">.</span><span class="n">layout</span><span class="p">.</span><span class="n">activity_main</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">toolbar</span> <span class="p">=</span> <span class="n">findViewById</span><span class="p">(</span><span class="nc">R</span><span class="p">.</span><span class="n">id</span><span class="p">.</span><span class="n">toolbar</span><span class="p">)</span> <span class="k">as</span> <span class="n">Toolbar</span>
</span></span><span class="line"><span class="cl">        <span class="n">setSupportActionBar</span><span class="p">(</span><span class="n">toolbar</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">fab</span> <span class="p">=</span> <span class="n">findViewById</span><span class="p">(</span><span class="nc">R</span><span class="p">.</span><span class="n">id</span><span class="p">.</span><span class="n">fab</span><span class="p">)</span> <span class="k">as</span> <span class="n">FloatingActionButton</span>
</span></span><span class="line"><span class="cl">        <span class="n">fab</span><span class="p">.</span><span class="n">setOnClickListener</span> <span class="p">{</span> <span class="n">view</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="nc">Snackbar</span><span class="p">.</span><span class="n">make</span><span class="p">(</span><span class="n">view</span><span class="p">,</span> <span class="s2">&#34;Replace with your own action&#34;</span><span class="p">,</span> <span class="nc">Snackbar</span><span class="p">.</span><span class="n">LENGTH_LONG</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                    <span class="p">.</span><span class="n">setAction</span><span class="p">(</span><span class="s2">&#34;Action&#34;</span><span class="p">,</span> <span class="k">null</span><span class="p">).</span><span class="n">show</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreateOptionsMenu</span><span class="p">(</span><span class="n">menu</span><span class="p">:</span> <span class="n">Menu</span><span class="p">):</span> <span class="n">Boolean</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// Inflate the menu; this adds items to the action bar if it is present.
</span></span></span><span class="line"><span class="cl">        <span class="n">menuInflater</span><span class="p">.</span><span class="n">inflate</span><span class="p">(</span><span class="nc">R</span><span class="p">.</span><span class="n">menu</span><span class="p">.</span><span class="n">menu_main</span><span class="p">,</span> <span class="n">menu</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="k">true</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">override</span> <span class="k">fun</span> <span class="nf">onOptionsItemSelected</span><span class="p">(</span><span class="n">item</span><span class="p">:</span> <span class="n">MenuItem</span><span class="p">):</span> <span class="n">Boolean</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// Handle action bar item clicks here. The action bar will
</span></span></span><span class="line"><span class="cl">        <span class="c1">// automatically handle clicks on the Home/Up button, so long
</span></span></span><span class="line"><span class="cl">        <span class="c1">// as you specify a parent activity in AndroidManifest.xml.
</span></span></span><span class="line"><span class="cl">        <span class="k">val</span> <span class="py">id</span> <span class="p">=</span> <span class="n">item</span><span class="p">.</span><span class="n">itemId</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">id</span> <span class="o">==</span> <span class="nc">R</span><span class="p">.</span><span class="n">id</span><span class="p">.</span><span class="n">action_settings</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="k">true</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="k">super</span><span class="p">.</span><span class="n">onOptionsItemSelected</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="you-can-run-the-application-with-kotlin-now">You can run the application with kotlin now</h3>
<p>All the code you can find <a href="https://github.com/trevorwang/android-kotlin-example/tree/kotlin-init">trevorwang/android-kotlin-example</a></p>
]]></content:encoded></item></channel></rss>