<?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>旧文 on Trevor's Blog</title><link>http://mings.in/tags/%E6%97%A7%E6%96%87/</link><description>Recent content in 旧文 on Trevor's Blog</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Wed, 10 Apr 2019 09:00:00 +0800</lastBuildDate><atom:link href="http://mings.in/tags/%E6%97%A7%E6%96%87/index.xml" rel="self" type="application/rss+xml"/><item><title>flutter_boost 集成体验之Android</title><link>http://mings.in/posts/flutter-boost/</link><pubDate>Wed, 10 Apr 2019 09:00:00 +0800</pubDate><guid>http://mings.in/posts/flutter-boost/</guid><description>flutter_boost 集成体验之Android</description><content:encoded><![CDATA[<blockquote>
<p>如何将 flutter_boost 添加到已有的Android工程，此 demo 在 MacOS 下完成，如果使用 Windows， 请修改对应的路径为 Windows 的格式。</p>
</blockquote>
<h2 id="flutter-端">flutter 端</h2>
<ol>
<li>
<p>新建 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>在 <code>pubspec.yaml</code> 中添加 flutter_boost 依赖</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>运行 <code>flutter build apk</code>
在 flutter_boost 0.400版本会有错误抛出，找出其中关键信息如下：</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>不难发现是因为没有 <code>kotlin</code> 依赖导致, 下面我们就来修复这个问题</p>
</li>
<li>
<p>在项目根目录下执行，<code>flutter make-host-app-editable</code>
执行完成后，发现目录下面出现了 <code>android</code> 以及 <code>ios</code> 文件夹</p>
</li>
<li>
<p>在 <code>android/build.gralde</code> 中添加 <code>kotlin</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>再一次运行 <code>flutter build apk</code> 发现成功了</p>
</li>
<li>
<p>把 <code>flutter_boost/example/lib</code> 下的文件复制到 <code>lib</code> 目录</p>
</li>
</ol>
<p>这样 flutter 这一端的工作就准备完成了</p>
<h2 id="android-端">Android 端</h2>
<ol>
<li>
<p>使用Android Studio新建一个工程</p>
<p>如果你有现成的项目，可以跳过这一步</p>
</li>
<li>
<p>在 App module 中添加kotlin支持，并在 <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">//保证Android项目和flutter module在同一目录下
</span></span></span></code></pre></div><p>运行一下 <code>gralde sync</code>，这时候你的工程里应该会出现三个新的项目 <code>Flutter-flutter</code>, <code>flutter_boost</code> 和 <code>xservice_kit</code></p>
<p>如果碰到一下错误，请把gradle的版本改为 <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>在 <code>flutterservice</code> 目录下的 <code>build.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">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>从<code>flutter_boost/example/android</code> 中复制所有chu新建 <code>MyApplication</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">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>完成后再manifest文件中指定使用此Application</p>
</li>
<li>
<p>在 MainActivity 中添加弱引用来保存 <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>新建FlutterPageActivity, 记得添加到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>在layout中给textview 添加id</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>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>运行android工程，如果碰到错误请按照提示修改</p>
</li>
<li>
<p>点击 <code>Hello world</code>,就会打开一个Flutter的页面了，到此已经完成了从Native页面打开flutter页面</p>
</li>
<li>
<p>把MyApplication 中 startActivity 函数修改为下面代码：</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>点击flutter页面中的<code>open native page</code>，就会重新打开activity。</p>
<p>这样就完成了两端的相互调用，欢迎入坑 Flutter</p>
]]></content:encoded></item><item><title>Flutter 插件开发 -- Android篇</title><link>http://mings.in/posts/flutter-plugin-development-for-android/</link><pubDate>Sat, 16 Jun 2018 09:00:00 +0800</pubDate><guid>http://mings.in/posts/flutter-plugin-development-for-android/</guid><description>以二维码扫描为例介绍插件开发</description><content:encoded><![CDATA[<p>目前 flutter 的功能还么有很完善，很多常用的三方库在 flutter 中没有类似的实现。如何在 flutter 中使用已经存在的 native 库呢？本文以二维码扫描为例，介绍 flutter 插件开发。</p>
<h2 id="新建-plugin-工程">新建 Plugin 工程</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>打开新创建的工程，可以看到一下代码：</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>通过以上代码，可以清晰看出来，Flutter 通过提供 <code>MethodChannel</code> 来实现跨语言的调用。
Kotlin 的代码中，有个叫做 <code>ScanPlugin</code> 的类，这个类继承自 <code>MethodCallHandler</code>。它会先向 Flutter 注册一个叫做 scan 的 channel， 然后在 <code>onMethodCall</code> 判断当函数名为 <code>getPlatformVersion</code> 时，返回 android 系统的 OS 版本。</p>
<p>在 Dart 中，获取一个注册明为 <code>scan</code> 的 <code>MethodChannel</code>。然后通过 <code>_channel.invokeMethod('getPlatformVersion');</code> 来获取对应的函数的结果。</p>
<p>通过以上分析，我看就可以看得出来，如果要添加一个叫做 <code>codescan</code> 的函数就可以了。</p>
<h2 id="添加-codescan-函数">添加 <code>codescan</code> 函数</h2>
<h3 id="先执行以下命令">先执行以下命令</h3>
<pre><code>```shell
cd example; 
flutter build apk
```
</code></pre>
<h3 id="导入-android-plugin-工程">导入 Android Plugin 工程</h3>
<ol>
<li>打开 Android Studio</li>
<li>选择 Import project,然后选中 <code>example/android/build.gradle</code> 文件</li>
<li>在 Gradle Sync 窗口中，选择 OK</li>
<li>Android Gradle Plugin Update 窗口中选择 Don’t remind me again for this project</li>
</ol>
<p>这样你就可以运行 example 工程了</p>
<h3 id="libscandart-中添加函数"><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="scanpluginkt-中实现该函数"><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="examplelibmaindart-中调用该函数"><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 该工程，应该可以看到如下界面：
<img alt="flutter code scan" loading="lazy" src="/images/flutter-scan-button.png">
点击 Scan 按钮，就可以看到二维码扫描的界面了。</p>
<p><img alt="flutter scan camera" loading="lazy" src="/images/flutter-scan-camera.png"></p>
<p>到这里你就可以实现 dart 来调用三方库来实现具体的功能了。</p>
<p>如何获取第三方库的返回值呢？MethodHandler提供了一个 result 类传递返回值，只需要在 success 函数中传递你需要的返回值就可以了。同时如果需要获取  onActivity 的返回值，可以通过 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>Flutter widgets framework 介绍</title><link>http://mings.in/posts/flutter-widgets-framework/</link><pubDate>Mon, 11 Jun 2018 09:00:00 +0800</pubDate><guid>http://mings.in/posts/flutter-widgets-framework/</guid><description>简单介绍Flutter widgets framework，了解 Flutter 如何通过组装widgets 来实现复杂 UI 的</description><content:encoded><![CDATA[<h2 id="介绍">介绍</h2>
<p>Flutter widgets 是从 <a href="http://facebook.github.io/react/">React</a> 得到启发，从而产生的一套现在流行的响应式框架。其主要思想就是所有的 UI 使用 widgets 来创建。所有的 widgets 会给出当前的配置和状态。当一个 widget 有变化时，系统会计算出来所有的这个 widget背后的渲染树从前一个状态到当前状态的最小变化，从而重新构建自己。所以在 Flutter 中所有的 UI 都是通过各种 widgets 的组合来实现的。<strong><a href="https://flutter.io/widgets/">查看所有的 widgets</a></strong></p>
<h2 id="来一个-hello-world">来一个 Hello World</h2>
<p>将如下代码 copy 到你新建项目中的 <code>lib/main.dart</code>，运行一下将会看到一下效果。<strong>(如果你还没有新建过项目，请按照<a href="/2018/06/03/how-to-setup-development-environment.html">这里的步骤</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="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">
我们在 main 函数中，把一个 text 的 widget 传给了 <code>runApp</code> 这个函数，从而得到上面的效果。
如果我们需要 <code>Hello, world!</code> 居中显示怎么办，前面我讲了在 flutter 中我们需要各种 widgets 的组合。这里我们就需要一个叫做 <code>Center</code> 的widget 所以放在里面的组件，都会显示在这个组建的中间。我们改一下代码：</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>效果如下：
<img alt="Hell world 2" loading="lazy" src="/images/flutter-hello-world-2.png">
<em>细心的朋友，可能注意到了，本段中 <code>Center</code> 跟 <code>Text</code> 的 <code>new</code> 关键字不见了， 这里是因为 Dart 2 提供的语法糖，让我们省略关键字 <code>new</code>。</em></p>
<p>我们把 <code>Text</code> 放到了 <code>Center</code> widget 的 <code>child</code> 属性中，然后这个文字就可以居中了，不要太简单。到这我们就碰到了两种类型的 widgets，一个是用来展示内容的 <code>Text</code>，一个是用来布局的 <code>Center</code>。 在 Flutter 的开发中，我们会大量使用这种 widgets 的组合来实现我们需要的效果。接下来我们需要一个白色的背景以及蓝色的字体。<strong><a href="https://flutter.io/widgets/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">
为了实现白色背景，我们添加了一个 <code>Container</code>  widget，然后颜色设置为 白色。我们看到 Text 没有 color 的属性，但是有个 style，所以我们通过构建一个白色的 TextStyle 来实现字体变成红色。TextStyle 中还可以改变字体的其他属性，自己可以在研究一下。</p>
<p>如何在文字下面添加一个按钮呢？</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">// 实现上下布局
</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">// 按钮
</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">
从代码中我们可以看到我们增加了一个 <code>Column</code> 来实现一个多个 widgets 的竖状排列，所以它的子控件 属性变成了需要一个 List 的 <code>children</code>。我们再来看 Button，这里我们要给 button 添加一个说明，同样通过添加一个 <code>Text</code> widget 来实现。如果你耐心看到这里，你基本上已经入门了 Flutter 开发。再复杂的页面也是类似于这样组合 widget 的方式来进行开发，可能使用到更复杂的 widget 罢了。</p>
<p>你有没有发现，我们没有用 <code>xml</code> 或者 <code>xib</code> 文件，轻轻松松就实现了这样一个界面。 如果我们同样使用 Java 或者 Swift 来实现同样的界面，需要多少代码呢？</p>
]]></content:encoded></item><item><title>Flutter 项目结构介绍</title><link>http://mings.in/posts/flutter-project-structure/</link><pubDate>Sat, 09 Jun 2018 09:00:00 +0800</pubDate><guid>http://mings.in/posts/flutter-project-structure/</guid><description>说明项目的目录结构以及主要文件内容</description><content:encoded><![CDATA[<h1 id="flutter-项目结构介绍">Flutter 项目结构介绍</h1>
<h2 id="主要目录以及文件">主要目录以及文件</h2>
<p><img loading="lazy" src="/images/pic-flutter-project-structure.png"></p>
<ol>
<li><code>android</code> Android 平台相关代码</li>
<li><code>ios</code> iOS 平台相关代码</li>
<li><code>build</code> 项目编译产生的目录，不需要关心</li>
<li><code>lib</code> 跨平台代码，也是 Flutter 项目主要关心的目录</li>
<li><code>test</code> 测试相关代码</li>
<li><code>pubspec.yaml</code> 项目描述文件，相当于 NodeJs 项目的 <code>package.json</code>，里面包含了项目的描述信息以及所需要的依赖的库</li>
</ol>
<h2 id="主要文件说明">主要文件说明</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 使用 <code>dart</code> 语言（以后的章节中会逐步增加一些介绍 dart 的内容）来进行开发，下图是将代码简化之后的效果。只需要3个类就可以实现一个 app 页面，并且可以同时运行在 iOS 和 Android 两个平台，非常简单。而且 <code>main.dart</code> 是所有 Flutter 项目的入口文件，不能被删除或者改名。
<img alt="pic-flutter-main" loading="lazy" src="/images/pic-flutter-main.png"></p>
]]></content:encoded></item><item><title>Flutter 开发环境配置</title><link>http://mings.in/posts/how-to-setup-development-environment/</link><pubDate>Sun, 03 Jun 2018 09:00:00 +0800</pubDate><guid>http://mings.in/posts/how-to-setup-development-environment/</guid><description>Flutter 开发环境配置</description><content:encoded><![CDATA[<h2 id="系统要求">系统要求</h2>
<p>操作系统：macOS (64-bit) 本文以 macOS 系统为例介绍安装过程<br>
工具： <code>bash</code>,<code>git</code>,<code>curl</code>,<code>unzip</code></p>
<h2 id="获取-flutter-sdk">获取 Flutter SDK</h2>
<ol>
<li>
<p>从<a href="https://flutter.io/sdk-archive/#macos">Flutter SDK Archive</a>页面下载最新版本的 SDK。
点击<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>下载或者</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. 如果上面链接有问题,请使用中国专用链接**
    
    ```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>解压文件到你想要的路径</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. 添加`flutter`到PATH

    ```shell
export PATH=`pwd`/flutter/bin:$PATH
</code></pre><ol start="4">
<li>
<p>运行 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>
***如果按照上面的步骤，没有成功安装。请采用下面命令安装：***

```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

####备用的镜像网站####
# 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="配置开发平台">配置开发平台</h2>
<h3 id="ios开发">iOS开发</h3>
<h4 id="安装-xcode">安装 Xcode</h4>
<ol>
<li>
<p>从 <a href="https://itunes.apple.com/us/app/xcode/id497799835">App Store</a> 安装 xcode.</p>
</li>
<li>
<p>配置命令行使用最新的 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>确保您已经接受 xcode 许可协议</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="配置模拟器">配置模拟器</h4>
<ol>
<li>
<p>通过LaunchPad 或者下面的命令来启动模拟器</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` 来运行你的程序


### Android 开发
#### 安装 Android Studio
下载安装 [Android Studio](https://developer.android.com/studio/index.html)
#### Android 设备（Android Version &gt;= 4.1）
1. 参照[此链接](https://developer.android.com/studio/debug/dev-options.html)开启开发者模式并打开 debug
2. 链接你的手机到电脑
3. `flutter run` 运行你的程序
</code></pre>]]></content:encoded></item><item><title>Continuous Delivery System Based on Gitlab</title><link>http://mings.in/posts/continuous-delivery-system-based-on-gitlab/</link><pubDate>Mon, 10 Apr 2017 09:00:00 +0800</pubDate><guid>http://mings.in/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+behind+corporate+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 Null Safety</title><link>http://mings.in/posts/kotlin-null-safety/</link><pubDate>Sun, 12 Mar 2017 09:00:00 +0800</pubDate><guid>http://mings.in/posts/kotlin-null-safety/</guid><description>How to eliminate null pointer exception in Kotlin?</description><content:encoded><![CDATA[<h1 id="kotlin-null-safety">Kotlin Null Safety</h1>
<blockquote>
<p>Kotlin&rsquo;s type system is aimed to eliminate <code>NullPointerException</code>&rsquo;s from our code. The only possible causes of NPE&rsquo;s may be</p>
<ol>
<li>An explicit call to throw <code>NullPointerException()</code></li>
<li>Usage of the <code>!!</code> operator that is described below</li>
<li>External Java code has caused it</li>
<li>There&rsquo;s some data inconsistency with regard to initialization (an uninitialized <code>this</code> available in a constructor is used somewhere)</li>
</ol>
</blockquote>
<h3 id="variables">Variables</h3>
<p>As mentioned above, there&rsquo;re the only 4 ways to cause a NPE. And there&rsquo;re nullable and non-nullable types in Kotlin&rsquo;s System. So when you define a variable, you must tell Kotlin whether the variable is nullable or not.</p>
<ol>
<li>
<p>Non-nullable variable
You can define non-nullable variables 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="k">var</span> <span class="py">b</span><span class="p">:</span><span class="n">String</span> <span class="p">=</span> <span class="s2">&#34;abc&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">var</span> <span class="py">a</span><span class="p">:</span><span class="n">Int</span> <span class="p">=</span> <span class="mi">10</span>
</span></span></code></pre></div><p>Once you want to assign a <code>null</code> to a non-nullable variable,</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">b</span> <span class="p">=</span> <span class="k">null</span>
</span></span><span class="line"><span class="cl">    <span class="n">a</span> <span class="p">=</span> <span class="k">null</span>
</span></span></code></pre></div><p>the compiler will throw you an error. The Kotlin system prevent nullable value in the compile stage.</p>
</li>
<li>
<p>Nullable variable
If you want to define a variable which can be set as <code>null</code>, please 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="k">var</span> <span class="py">b</span><span class="p">:</span><span class="n">String</span><span class="p">?</span> <span class="p">=</span> <span class="s2">&#34;abc&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">var</span> <span class="py">a</span><span class="p">:</span><span class="n">Int</span><span class="p">?</span> <span class="p">=</span> <span class="mi">10</span>
</span></span></code></pre></div><p>Now both of them can be set as <code>null</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="n">b</span> <span class="p">=</span> <span class="k">null</span>    <span class="c1">// ok
</span></span></span><span class="line"><span class="cl">    <span class="n">a</span> <span class="p">=</span> <span class="k">null</span>    <span class="c1">// ok
</span></span></span></code></pre></div></li>
</ol>
<h3 id="nullable-check">Nullable check</h3>
<p>The Kotlin system will tell you an error if you want to call a method from a nullable variable.</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">b</span><span class="p">.</span><span class="n">length</span><span class="p">.</span>  <span class="c1">// compile error
</span></span></span></code></pre></div><p>You must check <code>b</code> whether it is null or not.</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">if</span> <span class="p">(</span><span class="n">b</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">b</span><span class="p">.</span><span class="n">length</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span></code></pre></div><p>It&rsquo;s a Java style way, is there a new method to handle this in Kotlin. Absolutely, yes. There&rsquo;s a new and safe operator, <code>?.</code>, to be used in this state.</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">val</span> <span class="py">a</span> <span class="p">=</span> <span class="n">b</span><span class="o">?.</span><span class="n">length</span>
</span></span></code></pre></div><p>It&rsquo;s safe and never throws the <code>NullPointerException</code>. It will return a <code>null</code> for  this invocation and never really call the <code>length</code> method. Isn&rsquo;t a easy way to handle nullable variable?</p>
<blockquote>
<p>If you want the Java&rsquo;s style to handle exception, just use <code>!!</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">val</span> <span class="py">a</span> <span class="p">=</span> <span class="n">b</span><span class="o">!!</span><span class="p">.</span><span class="n">length</span>
</span></span></code></pre></div><p>The above code may throws a <code>NullPointerException</code> during the runtime.</p>
</blockquote>
<p>There&rsquo;s also another example from kotlin&rsquo;s official site:</p>
<blockquote>
<p>Safe calls are useful in chains. For example, if Bob, an Employee, may be assigned to a Department (or not), that in turn may have another Employee as a department head, then to obtain the name of Bob&rsquo;s department head (if any), we write the 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="n">bob</span><span class="o">?.</span><span class="n">department</span><span class="o">?.</span><span class="n">head</span><span class="o">?.</span><span class="n">name</span>
</span></span></code></pre></div><p>Such a chain returns a <code>null</code> if any of the properties in it is null.</p>
</blockquote>
<p>To perform a certain operation only for non-null values, you can use the safe call operator together with <code>let</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">val</span> <span class="py">listWithNulls</span><span class="p">:</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">String</span><span class="p">?&gt;</span> <span class="p">=</span> <span class="n">listOf</span><span class="p">(</span><span class="s2">&#34;A&#34;</span><span class="p">,</span> <span class="k">null</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="p">(</span><span class="n">item</span> <span class="k">in</span> <span class="n">listWithNulls</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">     <span class="n">item</span><span class="o">?.</span><span class="n">let</span> <span class="p">{</span> <span class="n">println</span><span class="p">(</span><span class="k">it</span><span class="p">)</span> <span class="p">}</span> <span class="c1">// prints A and ignores null
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="elvis-operator-">Elvis Operator (<code>?:</code>)</h3>
<p>You definitely meet the following issue: return the string&rsquo;s length if non-null and just return <code>-1</code> when it&rsquo;s <code>null</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">val</span> <span class="py">l</span><span class="p">:</span> <span class="n">Int</span> <span class="p">=</span> <span class="k">if</span> <span class="p">(</span><span class="n">b</span> <span class="o">!=</span> <span class="k">null</span><span class="p">)</span> <span class="n">b</span><span class="p">.</span><span class="n">length</span> <span class="k">else</span> <span class="p">-</span><span class="mi">1</span>
</span></span></code></pre></div><p>Now there&rsquo;s new operator.</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">val</span> <span class="py">l</span> <span class="p">=</span> <span class="n">b</span><span class="o">?.</span><span class="n">length</span> <span class="o">?:</span> <span class="p">-</span><span class="mi">1</span>
</span></span></code></pre></div><p>or</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">bob</span><span class="o">?.</span><span class="n">department</span><span class="o">?.</span><span class="n">head</span><span class="o">?.</span><span class="n">name</span> <span class="o">?:</span> <span class="s2">&#34;No Name&#34;</span>
</span></span></code></pre></div><p>If the expression to the left of <code>?:</code> is not null, the elvis operator returns it, otherwise it returns the expression to the right. Note that the right-hand side expression is evaluated only if the left-hand side is null.</p>
<p><em><strong>Note that, since throw and return are expressions in Kotlin, they can also be used on the right hand side of the elvis operator. This can be very handy, for example, for checking function arguments:</strong></em></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">fun</span> <span class="nf">foo</span><span class="p">(</span><span class="n">node</span><span class="p">:</span> <span class="n">Node</span><span class="p">):</span> <span class="n">String</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">parent</span> <span class="p">=</span> <span class="n">node</span><span class="p">.</span><span class="n">getParent</span><span class="p">()</span> <span class="o">?:</span> <span class="k">return</span> <span class="k">null</span>
</span></span><span class="line"><span class="cl">    <span class="k">val</span> <span class="py">name</span> <span class="p">=</span> <span class="n">node</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o">?:</span> <span class="k">throw</span> <span class="n">IllegalArgumentException</span><span class="p">(</span><span class="s2">&#34;name expected&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ...
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="safe-cast">safe cast</h3>
<p>Regular casts may result into a ClassCastException if the object is not of the target type. Another option is to use safe casts that return null if the attempt was not successful:</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">val</span> <span class="py">a</span> <span class="p">=</span> <span class="n">Animal</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="k">val</span> <span class="py">dog</span><span class="p">:</span> <span class="n">Dog</span><span class="p">?</span> <span class="p">=</span> <span class="n">a</span> <span class="k">as</span><span class="p">?</span> <span class="n">Dog</span>
</span></span></code></pre></div><h3 id="collections-of-nullable-type">Collections of Nullable Type</h3>
<p>If you have a collection of elements of a nullable type and want to filter non-null elements, you can do so by using filterNotNull.</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">val</span> <span class="py">nullableList</span><span class="p">:</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">Int</span><span class="p">?&gt;</span> <span class="p">=</span> <span class="n">listOf</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">val</span> <span class="py">intList</span><span class="p">:</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">Int</span><span class="p">&gt;</span> <span class="p">=</span> <span class="n">nullableList</span><span class="p">.</span><span class="n">filterNotNull</span><span class="p">()</span>
</span></span></code></pre></div>]]></content:encoded></item><item><title>Kotlin &amp; Dagger2</title><link>http://mings.in/posts/kotlin-with-dagger2/</link><pubDate>Fri, 17 Feb 2017 09:00:00 +0800</pubDate><guid>http://mings.in/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/posts/kotlin-with-rxjava-and-retrofit/</link><pubDate>Thu, 16 Feb 2017 09:00:00 +0800</pubDate><guid>http://mings.in/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/posts/kotlin-data-binding/</link><pubDate>Sun, 05 Feb 2017 09:00:00 +0800</pubDate><guid>http://mings.in/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/posts/android-development-with-kotlin/</link><pubDate>Wed, 25 Jan 2017 09:00:00 +0800</pubDate><guid>http://mings.in/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>