「Realm Report」にみるモバイル開発のトレンド

Realm Report Q4 2017

モバイル開発者が利用している言語は?

モダンな言語に移行が進んでいる

今現在, モバイルプラットフォームでは7つの主要言語がありますが割合は急速に変化しています. iOS開発者においては, Swift が登場しましたが, 今では Objective-C を超えています.

Androidでは, Javaがピークに達しており Kotlin のAndroidプラットフォーム獲得が進んでいます.

 

世界で一番モバイル開発の進んでいるのは?

優秀な開発者はどこにでもいる

Realm を利用した開発者は基本的なデフォルトの選択を超えており, 193カ国からコードがプッシュされていますが, 上位10カ国は世界中に均等に分布しています.

現在, 開発者が注目している技術やプラットフォームの興味深い違いをこの分析に見ることができます.

 

iOSは西欧を拠点としている

西欧の開発者は iOS 11 beta にすばやく注目しており, 全開発者の10%以上が, ドイツとアメリカにおいて iOS11beta を利用しています.

 

西欧の開発者は iOS の新技術に素早く対応している

西欧諸国の開発者は新しい Realm の iOS バージョンに非常に早くアップグレードしています.

 

西欧の開発者はiOS8のような古いバージョンは素早く切り捨てています

新しい技術に対応することは, 古いバージョンやデバイスのサポートをやめることになることになることがあります. 西欧諸国では, そのトレードオフのほうを好んでいます,

 

iOSに関しては, ドイツとアメリカが常に上位 (イギリスが3位)

iOS11対応やRealm対応, 古いiOSバージョンを切り捨てるスピードでは3カ国の開発者は他を圧倒しています. イギリスは開発者数では12番目ですが, 対応の速さでは常にドイツとアメリカに続いています.

 

Androidではアジアがリードしている

iOS では, アプリビルド数ではアメリカが上位ですが, Android Oreo 対応では低迷しており, ロシアや日本が上位となっています.

 

Android版Realmの対応割合の上位ははっきりしない

Android版Realmの対応状況はアジア諸国の開発者は新技術を追うことに対してより保守的であることを示しています.

 

Kotlin 対応はアメリカがさらに加速していくかも知れない

Android に Kotlin が新しい風を起こしており, アメリカ開発者のプラットフォームの将来を動かすかもしれない.

 

モバイル開発全体ではドイツが明快にトップ

ドイツのモバイル開発が両プラットフォームでのトップで Android とiOS の新バージョンや技術の対応も最も素早い.

 

Kotlin が今 Android 生態系を変えようとしている

Google I/O 2017 以降, Kotlin の割合は劇的に世界中で増加しています.

 

まとめ?

iPhoneXは4Kテレビと同じにおいを感じるんですよ。「技術としてスゴい」ことと「便利」なことって似ているようで違いますよね。んで、iPhoneXは、技術を追求するために便利さを捨てている気がするんですよ。

ホリエモン×ひろゆきが分析するiPhoneXの新機能「技術を追求するために便利さを捨てている」 - IT・テクノロジー - ニュース|週プレNEWS[週刊プレイボーイのニュースサイト]

アジアでありながら西欧諸国のようにiPhoneの販売台数割合は大きい日本ですが, 今後, 「古いOSやデバイスを考慮しない」という考え方でそれらを切り捨てていくという西欧スタイルの考え方は今後もさらに浸透していくのでしょうか.

そして, 新しい技術への対応や古いOSを切り捨てることに対してのより保守的なアジアスタイルの考え方はやは今後も縮小していくのでしょうか.

Realm Report Q4 2017


Dagger に馴染めない人のためのいくつかの原則

Keeping the Daggers Sharp ⚔️ – Square Corner Blog – Medium

Dagger2 は 素晴らしい Dependency Injection ライブラリですが, なかなか上手に使いこなせません.

分かりやすくするための考え方や実装方法をいくつか見てみましょう.

フィールドよりコンストラクタのインジェクションを使う

フィールドインジェクションは, finalでなく, privateでないフィールドに使います.


// BAD
class CardConverter {

  @Inject PublicKeyManager publicKeyManager;

  @Inject public CardConverter() {}

}

フィールドに @Inject を忘れると NullPointerException の原因となります.


// BAD
class CardConverter {

  @Inject PublicKeyManager publicKeyManager;
  Analytics analytics; // Oops, forgot to @Inject

  @Inject public CardConverter() {}

}

コンストラクタインジェクションはイミュータブルですので, 局所的な状態を持ちませんのでスレッドセーフにつながります.


// GOOD
class CardConverter {

  private final PublicKeyManager publicKeyManager;

  @Inject public CardConverter(PublicKeyManager publicKeyManager) {
    this.publicKeyManager = publicKeyManager;
  }

}

Kotlinでは, さらに簡素化してくれます.


class CardConverter

@Inject constructor(
  private val publicKeyManager: PublicKeyManager)

それでも, フィールドインジェクションを使いたい場合は以下のようになります.


public class MainActivity extends Activity {

  public interface Component {
    void inject(MainActivity activity);
  }

  @Inject ToastFactory toastFactory;

  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Component component = SquareApplication.component(this);
    component.inject(this);
  }

}

Singleton はあまり使う必要はない

ミュータブルな状態に対して多くのアクセスが必要な場合は Singleton は便利です.


// GOOD
@Singleton
public class BadgeCounter {

  public final Observable<Integer> badgeCount;

  @Inject public BadgeCounter(...) {
     badgeCount = ...
  }

}

しかし, 変化しない状態に対しては Singleton にする必要はありません.


// BAD, should not be a singleton!
@Singleton
class RealToastFactory implements ToastFactory {

  private final Application context;

  @Inject public RealToastFactory(Application context) {
    this.context = context;
  }

  @Override public Toast makeText(int resId, int duration) {
    return Toast.makeText(context, resId, duration);
  }

}

まれに, 作成のコストがかかるキャッシュインスタンスの走査に使うことがあります. そうすることで, 繰り返し作成して破棄することを避けることができます.

@Provides でなく @Inject を使う

@Provides はコンストラクタを複製すべきではありません.
関係する部分を一つにするとコードがわかりやすくなります.


@Module
class ToastModule {

  // BAD, remove this binding and add @Inject to RealToastFactory
  @Provides RealToastFactory realToastFactory(Application context) {
    return new RealToastFactory(context);
  }

}

このことは, 特に singleton においては重要です. そのクラスを読むときの重要な実装の内容一覧となります. 一部分をみればすべての内容が把握できます.


// GOOD, I have all the details I need in one place.
@Singleton
public class BadgeCounter {

  @Inject public BadgeCounter(...) {}

}

static @Provides を使う

@Provides は static にすることができます.


@Module
class ToastModule {

  @Provides
  static ToastFactory toastFactory(RealToastFactory factory) {
    return factory;
  }

}

モジュールインスタンスを作成する代わりに, 直接メソッドを実行することができます. このときそのメソッドの呼び出しはコンパイラによってインライン化されています.


@Generated
public final class DaggerAppComponent extends AppComponent {

  // ...
  @Override public ToastFactory toastFactory() {
    return ToastModule.toastFactory(realToastFactoryProvider.get())
  }

}

一つだけのメソッドを static にしてもあまり変化はないですが, すべてを static にすると, かなりのパフォーマンスが向上します.

また, モジュールを abstract にすると, static でない @provides メソッドが ひとつでもあるとコンパイルに失敗します.

@Provides よりも @Binds を使う

あるタイプを他にマッピングするときは @Provides でなく @Binds を使う.


@Module
abstract class ToastModule {

  @Binds
  abstract ToastFactory toastFactory(RealToastFactory factory);

}

このメソッドは abstract でなければなりません. @Generated コードは実装内容をそのまま使おうとします.


@Generated
public final class DaggerAppComponent extends AppComponent {

  // ...
  private DaggerAppComponent() {
    // ...
    this.toastFactoryProvider = (Provider) realToastFactoryProvider;
  }

  @Override public ToastFactory toastFactory() {
    return toastFactoryProvider.get();
  }

}

@Singleton の interface binding は避ける

Statefulness is an implementation detail

集中するアクセスがミュータブルな状態にアクセスする必要があるかは実装のみが知っていますので, 実装をインターフェースにバインドさせるとき, アノテーションをつけるべきではありません.


@Module
abstract class ToastModule {

  // BAD, remove @Singleton
  @Binds @Singleton

  abstract ToastFactory toastFactory(RealToastFactory factory);

}

error-prone を使おう

一般的な Dagger のエラーはこれを使うことで分かりやすく検出できます.

👉 MVVM で Hilt のパターン化 💉  hatena-bookmark


日本国内キャリアに Pixel2 はLTEバンドが対応していないのか?

最近の記事をみながら思ったりしますが,

グーグル、リファレンス機スマートフォン「Pixel 2」と「Pixel 2 XL」が日本で発売されないことに関しての深刻な状況と危機感 | GPad

Pixel2が日本で出ないとなんでAndroid開発者が死亡するのか

海外でPixelを買って日本で使っている人もいますが、技適違反になるのでがまんしました。Pixel 2はLTEのバンドが日本のキャリア向けになっていないので、そもそも違反してまで買ってもいいことはなさそうです。

「Pixel 2」を買えなくてがっかりな気持ちをGoogleさんに伝えてみた - ITmedia NEWS

Pixel など, これまでの Android では, 「北米向け」ではない「グローバル向け」の端末では日本のキャリアでも利用できる周波数設定になっていたような気がします.

Network スペックを探してみる.

GSM/EDGE: Quad-band (850, 900, 1800, 1900 MHz)
UMTS/HSPA+/HSDPA: Bands 1/2/4/5/8
CDMA EVDO Rev A: BC0/BC1/BC10
FDD-LTE : Bands 1*/2*/3*/4*/5/7*/8/12/13/17/20/25/26/28/29/30/32/66*2
TD-LTE: Bands 38*/40/412

Google Pixel 2 and Pixel 2 XL specs: Google’s vision for the modern flagship | AndroidAuthority

FDD-LTE 1, 3, 28
いけそうな気がするが...

日本で使える LTE/3G バンド は?

ああ, そうか「技適」を通過していないので使ったらダメなのか...

技適についてだけはレスしておこう。 技適があるからガラパゴスみたいなク..

以下, 参考.

その「SIMフリー端末」は実質ロックされてないか?

Google Pixel 2の予約をCloveが受付開始。予定価格は約87,300円から | そうすけブログ.com

NTTドコモ系MVNOの周波数帯(バンド) | スマホゴーゴー

格安スマホ向け、ドコモとauとソフトバンクの対応バンドのまとめ(4G / LTE / VoLTE / 3G / WCDMA / CDMA2000)

日本の大手キャリアの対応周波数バンドをチェック!

SIMフリースマホを購入するときに知っておきたい「バンド」とは | 格安スマホ・格安SIMなら【SIM通】

ご利用いただける国 - Google Store ヘルプ


【Mac】言語設定をアプリごとに行う

気持ちが悪いですよね日本語名のディレクトリ.

macのつらい日本語ホームディレクトリを英語にする - Qiita

macのホームディレクトリの日本語表記を英語表記に変更する - Qiita

そんな方法があるのだなあ,と思いつつも,OS自体の言語設定は「English」でいいや,と思い過ごしていましたが,

使用するアプリによっては,そのアプリ内には言語の設定はなく,OSの言語設定を見ながらメニューや操作のラベルをその英語で表示する.

複雑なアプリの場合,細かい操作方法をググるとなると英語では辛くなってきた.

やっぱ日本語だよなと,OSの言語設定を「日本語」に戻す.

すると,最近 Google から登場した Backup and Sync がすでに存在する「Google Drive」ディレクトリとは別に「Google ドライブ」ディレクトリを作成してクラウド上から無駄にPC内に重複するファイル群をダウンロードし始める.

当然,前述の「ダウンロード」や「ドキュメント」などの日本語名ディレクトリも復活している.

 

アプリごとに言語設定をする

OSの言語設定は「English」にしたまま,特定のアプリだけ「日本語」設定にする.

TJ-HD Software - Language Switcher

アプリごとにOSで利用可能な言語の中から言語を設定できます.

便利です.

MBP2017-mid/Sierra にて.


Kotlin で static なメンバーをどう書くべきなのか?

092: Learning Kotlin – dealing with static-ness and (companion) objects costs – Fragmented

「companion object」だな. と思いながらとりあえず書く.


class Foo {
    companion object {
        val myVar = "testing"
    }
}

これを Kotlin から呼ぶ場合は,


Foo.myVar

ですが, Java から呼ぶ場合は,


Foo.Companion.getMyVar();

となり クソですね.

では, Jvm アノテーション を使います.


class Foo {
    companion object {
        @JvmField val myVar = "testing"
    }
}

この場合は Kotlin/Java それぞれ同じように呼べます.


// calling from Kotlin
Foo.myVar

// calling from Java
Foo.myVar;

なるべく入れたくないですよね Jvm なアノテーション.

const キーワード を使う


class Foo {
    companion object {
        const val myVar = "testing"
    }
}

以下, 共に問題ありません.


// calling from Kotlin
Foo.myVar

// calling from Java
Foo.myVar;

同様に, パッケージレベルでは,


class BottomSheetView {
    companion object {
        const val BOTTOM_SHEET_ANIMATION_TIMING = 500L
    }

    // ...
}


animation.setTiming(BottomSheetView.BOTTOM_SHEET_ANIMATION_TIMING)

Companion object is initialized from the static constructor of the containing class and plain object is initialized lazily on the first access to that object.

こんなかんじでしっくりくる記述って見つけにくい気がしません? Kotlin て.

“Static constants” in Kotlin | Kotlin Blog