2014年4月30日水曜日

Android で Dagger DI を使いやすくするライブラリを書きました

Daggerというsquare社がオープンソースで提供しているAndroid向けDI (Dependency Injection)フレームワークがあります。


これを試しに自分のAndroidアプリで使ってみようと思い立ったのですが、幾つか問題が発生しました。

  • DI自体の概念が難しい
  • そもそもドキュメントを読んでもDaggerの使い方がよくわからない、公式のサンプルを真似してみても正直いまいちわからない
  • AndroidでDIを行うとなるとandroid.content.Contextの注入が必須になるのだが、Contextは動的なインスタンスであるためDIでの取り扱いが難しい

そこで四苦八苦しながら動くようになったものをライブラリとして公開し、少しでも簡単にDIのメリットだけを享受できればと思いまして DaggeredAndroid なるものを作ってみました。

使い方とかはREADMEを見てください。全部英語ですがすみません(´・_・`)

AndroidでDIを使う際のメリットは主に以下のとおりです。

  • オブジェクトをメンバに接続するだけのコードを無くせるので、コード量が減る。
  • シングルトンの取り扱いが楽になる。
  • Contextの取り扱いが楽になる。
  • Moduleを差し替えればインスタンスが安全に差し替わるので、テスト環境を作ったり、本番と開発環境を分離したりなど、環境の差し替えが楽になる。テスト時のみModuleを上書きすることもできる。

2014年4月20日日曜日

Android の TextView.setText() が遅い場合の原因と対処法

AndroidでTextViewを使っている時に、setText()に数百行単位のテキストを渡すとメインスレッドが1秒弱完全に固まってしまうという現象に見舞われてしまいました。昔の2.3端末ではともかく、手元の最新鋭機Nexus 5 (Android 4.4)でこんなに遅いのでは話になりません。しっかりと原因を調査し対処法を考えることにしました。

まずググってみると出るわ出るわ同じ問題。やはりみんな同じ場所で躓いているようです。
しかしながらいまいち具体的な原因がググっても見つかりません。そこでtraceviewを取ってみました。


すると原因が一発でわかりました。android.graphics.Paint.getTextRunAdvances()です。
Nexus 5では高速化のためJNI経由でネイティブ実装が呼び出されているようですが、それでもまだ間に合わないぐらい遅いようです。それもそのはず、このメソッドは与えられた文字の幅を計算するメソッドです。すなわち数百行のテキストのサイズを計算するため時間がかかっているようです。iOSで例えるならCore TextのCTGryphを計算するようなもの、UILabelのsizeThatFitsを呼び出すようなもので、非常に時間がかかってしまいます。

そこで対処法として、setText()でテキスト全体をセットし直すのではなく、TextViewが裏で保持しているテキストの一部だけを書き換えたり追記したりすることで一度に計算されるテキストのサイズの量を減らして高速化する事を考えました。iOSの場合はUITextViewにはsetText相当のプロパティしか用意されていないので、そのようなことをするのはdelegateを経由してみたりUIKeyInputプロトコルを自前で用意したりなどと困難がつきまとうのですが、Androidの場合は最初からTextViewの裏で保持しているテキストを自在に書きなおすための仕組みが用意されています。

そのためにはまずTextViewの裏で保持されているテキストを「編集モード」にしなければなりません。XMLでandroid:bufferTypeをeditableに指定するか、またはsetText()の第二引数にTextView.BufferType.EDITABLEを指定すると、テキストが編集モードで保持されるようになります。

そうするとgetEditableText()でTextViewが裏側で保持しているテキストが編集可能な状態で取得できます。あとはこのEditableオブジェクトに対して好きなように加工を行うだけです。単にテキストを追加するだけならTextView.append()を実行しても同じ結果が得られます。

こうすると数百行程度であればそれほど遅くなくテキストの追加ができるようになりました。しかしながら1000行を超えてくるとこれでも速度が足りなくなるので、自前でTextViewをサブクラス化して作っていくか、またはListViewにして一度に表示するテキスト量を減らすのが良いと思います。


2014年4月1日火曜日

Objective-🍣


全く新しい、真にユニバーサルな言語へ。


皆さんiOS開発の際にお世話になっているObjective-Cですが、一部の開発者の方々から以下の様な否定的な意見をいただくことがあります。

  • とっつきにくい
  • 文法がキモい
  • @や[]がキモい
  • シグネチャが無駄に長い
  • Apple製品でしか使えない

確かにObjective-Cは習熟すればこれらの欠点を補って余りある素晴らしい言語ですが、これからの更なるモバイルアプリの世界の拡充のためにはより一層多くの開発者に愛される言語になる必要があると私は考えました。

そこでこの度ご紹介するのがObjective-Cをさらに使いやすく、さらに親しまれるように、全く新しく一から作りなおした新言語

Objective-🍣

です!

Objective-🍣とは

以下の様な特徴を持つ言語です!

  • 驚異的に短く、真にユニバーサルな、洗練された文法を持ちます。これまでのプログラミング言語は基本的に英語による記述を強いるものでした。Objective-🍣は真に全人類にとってユニバーサルな絵文字をサポートすることで、この問題をすべて解決しました。Objective-🍣の親しみやすい文法にはすべてのプログラマがシンパシーを感じることができます。
  • Objective-Cと100%のランタイム互換性を持ちます。新しいiOSが登場してもその瞬間からあなたはObjective-🍣の圧倒的なパワーを手にすることができます。

さっそくObjective-🍣で書かれたサンプルコードを見てみましょう!拙作確率計算機のコードをObjective-🍣に書き換えてみました!

before

after

なんというこれまでにない全く新しいソースコード!あのキモかった@や[]、長ったらしいメソッド名がその姿を消しています!そのあまりの美しさには全プログラマが歓喜の涙を流すこと間違いありません!

Objective-🍣の導入方法

こちらのobjsushi.hをあなたのプロジェクト上でincludeするだけで使用できます!簡単ですね!


Objective-🍣を使ってみる

それでは早速ビルドしてみましょう!

あれ

えっちょ

\(^o^)/

ちなみに日本語セレクタ自体はXcode 5以降で普通に使えますよ。

お詫び

こちらの記事にはiOSならびに最新のMacでのみご覧になれる文字(具体的には🍣)を多数含んでおりますことをお詫び申し上げます(´・_・`)