ユニファ開発者ブログ

ユニファ株式会社システム開発部メンバーによるブログです。

iOSエンジニアですがDroidKaigi 2017に行ってきました

f:id:unifa_tech:20170322011253j:plain

iOSエンジニアのしだです。
DroidKaigi 2017 が先日 3/9 ~ 3/10 にベルサール新宿グラントで行われました。
今回で3回目の DroidKaigi で参加人数約800人と年々盛り上がりを感じます。
私は3/9 は終日一般参加、3/10は午前中だけ参加して来たので少し振り返りたいと思います。

逆引き マテリアル デザイン

マテリアルデザイン

マテリアルデザインのガイドラインを読んだことがなかったので勉強になりました。

  • 日本語のマテリアルデザインガイドライン https://material.io/jp/guidelines/
  • Typographyのページに Jonathan Lee (material designの偉い人)が織田信長扱いされてますw
  • サポートライブラリではできないのでガイドラインに従ってほしいこと
    • FABは、主要なアクションで使う
    • リストの一番下のアイテムがが隠れないように padding 入れる
    • など

サポートライブラリのFABは、影・アニメーションがガイドライン通りの動作しますが、 上記のことは開発者が実装することで、サポートライブラリではどうしようもないので開発者がガイドラインに従う必要があります。
マテリアルデザインのガイドラインを読むときにはこういう視点で読むほうが良いかもしれません。

テーマとスタイル

表記 利用
@style/foobar 定義しているスタイルを参照する場合
?attr/foobar テーマに定義している属性を参照する場合

サポートライブラリのデザインを変更したい場合、themeに定義されていれば、自分のアプリの themes.xml に属性を記述すればすぐ変更できる。 テーマもしくは、スタイルに定義されているものを調べて、サポートライブラリのデザインを変更するのは容易な感じでした。

iOS の nibファイルや storyboard はレイアウトとスタイルが一緒になっているの対して、Androidはレイアウトとスタイルのファイルが別れているので利便性があってうらやましいです。

アニメーション

マテリアルデザインのガイドラインにこうゆうアニメーションがいいですよ。というのがあります。あとで参考にしようと思います。

解剖Kotlin ~バイトコードを読み解く~

Kotlin はもともと興味ありまして、この機会に試しに軽く触って見ました。

項目 Kotlin・デコンパイルコード
型安全
/// kotlin
fun nullable() {
  val notNull: String = ""
  notNull.length
  val nullable: String? = null
  nullable?.length
  val nullable2: String? = null
  nullable2!!.length
}
/// java
public final void nullable() {
  String notNull = "not_null";
  notNull.length();
  String nullable = (String)null;
  if(nullable != null) {
     nullable.length();
  }

  String nullable2 = (String)null;
  if(nullable2 == null) {
     Intrinsics.throwNpe();
  }

  nullable2.length();
}
関数型
/// kotlin
var onClick: (View) -> Unit = { }
/// java
@NotNull
private Function1 onClick;
拡張関数
/// kotlin

/// Extensions.kt
fun SharedPreferences.clear(
    context: Context, name: String) {
    context.getSharedPreferences(name, Context.MODE_PRIVATE)
      .edit().clear().apply()
}
/// java
public final class ExtensionsKt {
  public static final void clear(
    @NotNull SharedPreferences $receiver,
    @NotNull Context context,
    @NotNull String name) {
     Intrinsics.checkParameterIsNotNull(
       $receiver, "$receiver");
     Intrinsics.checkParameterIsNotNull(
       context, "context");
     Intrinsics.checkParameterIsNotNull(
       name, "name");
     context.getSharedPreferences(name, 0)
       .edit().clear().apply();
  }
}
プロパティ
/// kotlin
class Horse(name: String, weight: Float) {
    val name: String
    var weight: Float

    init {
        this.name = name
        this.weight = weight
    }
}
/// java
public final class Horse {
   @NotNull
   private final String name;
   private float weight;

   @NotNull
   public final String getName() {
      return this.name;
   }

   public final float getWeight() {
      return this.weight;
   }

   public final void setWeight(float var1) {
      this.weight = var1;
   }

   public Horse(@NotNull String name, float weight) {
      Intrinsics.checkParameterIsNotNull(name, "name");
      super();
      this.name = name;
      this.weight = weight;
   }
}

今まで Kotlin を使うのにためらいがありましたが、Javaと相互運用可能なのでこれは使っていきたいと思いました。
iOS開発で Objective-C から Swift に移したときに、型安全・Optional型のお陰でクラッシュ減少やバグが見つけやすくなったという印象もっていて、 Android も Kotlin で幸せになれるのではないかと感じてます。

オフラインファーストなアプリケーション開発

Realm Mobile Platform のデモ行っていて、アプリがオフラインでも動作するし、コンフリクトせずに同期されていて便利な印象を受けました。

Realm の衝突解決(デフォルト)

  • 削除は優先
  • 同じプロパティは編集あとがち
  • リストへの挿入は時間順
  • Operational Transform いい感じにしてくれる

CAP定理

  • 一貫性 (Consistency)
  • 可用性 (Availability)
  • 分断耐性 (Partition tolerance)
  • 2つまでしか同時に満たすことができない
type e.g.
一貫性 + 可用性 一般的なRDBなど
一貫性 + 分断耐性 Apache HBase, MongoDBなど
可用性 + 分断耐性 DNSなど Realm Mobile Platform

実務でRealmを利用したことはありませんでしたが、 Realm の思想的な話が聞けたので、Androidの実装問わず、iOS開発でRealmを利用する際にも参考にしたいと思います。

Android ORMの選び方

Activerecord 3.0

  • Query
List<Todo> list = new Select().from(Todo.class)
  .where("id = ?", 1)
  .execute()
  • Pub-Sub: ContentProvider経由で利用可能
  • Migration: あるけどひどい
  • メンテナンスされていない

greenDAO 3.2.0

  • Query
List<Todo> list = todoDao.queryBuilder()
  .where(todoDao.Properties.Id.eq(1))
  .build().list()
  • Pub-Sub: なし
  • Migration: なし
  • High Performance

Requey

  • Query
Result<Todo> list = data.select(Todo.class)
  .where(Todo.ID.eq(1))
  .get()
  • Pub-Sub: RxJava1,2 で利用可能
  • Migration: SQLバージョンのみ
  • Annotation Processing
  • AbstractクラスかInterfaceを定義する

Realm 3.0.0

  • Query
RealmResults<Todo> list = realm.where(Todo.class)
  .equalTo("id", 1)
  .findAll()
  • Pub-Sub: サポート
  • Migration: バージョンで必要に応じてコードを書く
  • RealmObjectを継承する
  • アクセサの実装が必要

ORMA 4.2.1

  • Query
RealmResults<Todo> list = realm.where(Todo.class)
  .equalTo("id", 1)
  .findAll()
  • Pub-Sub: Experience
  • Migration: サポート schema-diff migration
  • Annotation Processing
  • ベースクラスなし
  • index が設定されてなければ検索helperメソッドが生成されない

これらのORMをAndroid開発で利用したことがありませんが、ORMの役割から比較までされていて興味深かったです。

まとめ

DroidKaigi 2017 で聴講したセッションをいくつか上げました。
Data Binding、Kotlin あたりは機会があったら実務で使っていきたいと思ってます。