サンプルコードや図を全て写していないので、原文を見ながら適宜理解を深めるのに利用してください。理解しやすいよう所々補足を加えています。先にアクティビティの実行時の変更処理について理解しておくと読みやすくなります。ViewModelViewModelクラスはUIに関連するデータの保持と管理をするようデザインされています。そのため画面回転などの設定変更があってもデータは保持されます。アクティビティやフラグメントなどのAppコンポーネントはAndroidフレームワークによって管理されるライフサイクルを持ちます。Androidフレームワークは、開発者がコントロールできないユーザーのアクションや端末のイベントに従って、ActivityやFragmentを破棄または再生成するか決めます。Activity/FragmentのオブジェクトがOSによって破棄または再生成されると、それらが保持していた全てのデータは破棄されます。ユーザーのリスト(List<User>)をActivityが持っていて、設定変更によってActivityが再生成されると、新しく生成されたActivityはリストデータを取得し直さなければなりません。データが単純ならActivity#onSaveInstanceState()メソッドを使って、Activity#onCreate()でBundleからデータを修復することができます。この方法は、UIの状態など少量のデータに向いています。サイズが大きくなりそうなユーザーのリスト(List<User>)には向いていません。他にも問題があります。activityやfragmentなどのUIコントローラーは戻るまでに時間のかかる非同期の処理を頻繁に呼ぶ必要があります。UIコントローラーはそれらの非同期処理を管理する必要があります。非同期処理が中断されたら、メモリリークを避けるためそれらを片付ける必要があります。これは多くの管理を必要とします。オブジェクトが設定変更によって再生成されて、同じ処理が呼ばれることはリソースの無駄使いです。最後にこれも重要なことですが、これらのUIコントローラーはユーザーのアクションに反応したり、OSとのコミュニケーションに対応する必要があります。自身が持つリソースも管理することになると、クラスは膨れ上がります。そのような状態は、1つのクラスがアプリのすべての機能を他のクラスに委譲せずに自分自身でやろうとすることになります。このような状態はテストを難しくします。Viewに必要なデータのオーナーシップをUIコントローラーのロジックから分離するのが簡単で効果的です。ライフサイクルパッケージはViewModelと呼ばれる新しいクラスを提供します。これはUIコントローラー(Activity/Fragment)のためのヘルパークラスで、UIに使うデータを準備する役割を担います。ViewModelは設定変更があっても自動的に保持されます。そのため、ViewModelが持つデータは再生成されたActivity/Fragmentですぐに利用できます。前述しましたが、ユーザーのリスト(List<User>)を取得し保持するのはActivityやFragmentではなく、ViewModelの責任であるべきです。Activityが再生成されても、再生成された新しいActivityは、前のActivityによって作られたものと同じViewModelのインスタンスを受け取ります。Activityが破棄されると、AndroidフレームワークはViewModel#onCleared()を呼び、ViewModelのインスタンスは破棄されます。Activity/Fragmentの初期化時にもViewModelは生き残ることから、ViewModelはViewを参照するべきではありません。どんなクラスでもそれがActivityコンテクストの参照を持つ場合は、そのクラスを参照すべきではありません。ViewModelがApplicationコンテクストを必要とする場合は、提供されているAndroidViewModelを継承して、コンストラクタでApplicationを受け取ってください。Fragments2つ以上のフラグメントが1つのアクティビティの中で、連携を取り合うことはよくあることです。2つのフラグメントがインタフェースを定義し、オーナーであるactivityが2つを結ぶことは、珍しいことではありません。2つのフラグメントはお互いが存在するか、visibleな状態であるか考えなければなりません。このよくある問題は、ViewModelオブジェクトを使って解決できます。fragmentsのケースを想像してください。アイテムリストを表示するfragmentからユーザーがアイテムを1つ選ぶと、選んだアイテムの詳細を表示するfragmentが出てくるパターンです。この2つのfragmentは、Activityのスコープを使って、お互いのコミュニケーションを管理するためにViewModelを共有することができます。gistbd67d578044e830ee00943b0e43145e72つのfragmentがVIewModelProviderを利用する際、getActivity()を使っていることに注意してください。これは2つのFragmentが同じactivityの範囲で、SharedViewModelのインスタンスを受け取ることを意味します。このアプローチの利点:Activityは何もする必要がありません。fragmentsのコミュニケーションについて知る必要もありません。FragmentはViewModel以外、お互いを一切知る必要がありません。片方が消えても、もう片方はいつも通り動き続けます。各Fragmentはそれぞれのライフサイクルを持ちます。片方のライフサイクルの影響を受けることもありません。実際、Fragmentが他のFragmentに入れ替わっている間も、UIは問題なく機能します。ViewModelの機能は、ViewModelを取得する際ViewModelProviderに渡したライフサイクルの範囲で利用できます。(activityを渡したら、activityがfinish()されるまで利用できます。)ViewModelは、ライフサイクルが終了するまでメモリに置かれます。activityならActivity#finish()、fragmentならFragment#detached()が呼ばれるまで、メモリに残ります。SavedInstanceStateViewModelは、設定変更があってもデータを保ち続けるための簡単な方法を提供します。アプリケーションがOSによってkillされるときは破棄されます。OSが保存されたデータからActivityを復元しています。state機能を使って状態を保存します。ほとんどの場合、開発者は何もする必要がありません。開発者はonSavedInstanceStateコールバックを使ってデータをbundleに追加するだけです。onSavedInstanceStateを使って保存されたデータは、システムのプロセスメモリに保持されます。OSは開発者にとても少ない量のデータを保持することを許可しています。そのため、実際のデータ(アプリが使うコンテンツデータ等)を保持させるのに適した場所ではありません。開発者は、UIコンポーネントによって簡単に置き換えられないデータのためにプロセスメモリを使うのは控えましょう。stateに入れないでください。countryIdを入れることはできます。実際に利用するオブジェクトはデータベースに入るべきです。ViewModelが保存されたcountryIdを使って、オブジェクトを取得します。Studio.Tweet広告を非表示にするもっと読むコメントを書く2017-05-20ロゴの使用許可申請メールテンプレートロゴの使用許可申請メールを作成したので、テンプレートメモ。Storeに申請したいとき用。at:[メールアドレス]Sincerely,[名前]おわり。Android.Tweet広告を非表示にするもっと読むコメントを書く2017-03-05BitcoinのBlockとTransactionのデータ構造についてBitcoinはP2P通信技術を利用している。Bitcoinネットワークに参加する各ノードはクライアントとしてもサーバーとしても動作し、データの生成と送受信を行う。各ノードが持つデータはほとんど同じである。(常にノード間でブロックとトランザクションをやり取りしているのでいつも全く同じデータではない)新しいノードがBitcoinネットワークに参加する流れBitcoinのソフトウェアをインストールし、デーモンを起動する。Seedsから他のノードのIPアドレスを聞き出す。他のノードに過去の取引データ(ブロックチェーン)を送ってもらう。送られたデータは主記憶装置に保存される。リポジトリは、CLI(コマンドラインインターフェース)を持っている。ソースをクローンし、デーモンを起動する。ネットワークに参加するノードは、他のノードのIPアドレスを知らない。そのため、Seedsというノードを利用する。Seedsと呼ばれるノードは常に稼働していることが期待されている。ネットワークに新しく参加したノードは、まずSeedsに他のノードのIPアドレスを聞く。Seedsのリストはbitcoin/src/chainparamsseeds.hに記載されている。手に入れたIPアドレスを元に、他のノードに過去の取引データを送信してもらう。送られた取引履歴は主記憶装置に保存する。保存先は${HOME}/.bitcoin/以下である。取引履歴には、ブロックチェーン、トランザクションリスト、UTXOなどがある。Networkは40GB程度である。前述したように、各ノードが生成したトランザクションやブロックは他のノードにブロードキャストされ、常にデータの同期が行われている。トランザクションとブロックは実際どのようなデータ構造をしているのだろうか。ブロックのデータ構造ブロックは複数のトランザクションを含む。先頭にネットワークを識別するマジックナンバーを持ち、ブロックのサイズ(1MByte以下でなければならない)、直前のブロックのhashなどを持つブロックヘッダー、内包するトランザクションの数と、最後にトランザクションデータを持つ。Wikiに書かれている。)ブロックヘッダーのデータ構造ブロックヘッダーは6つの要素を持つ。Hash(256bit)、時間(秒)、ターゲット、Nonce(32bit)である。)トランザクションのデータ構造トランザクションは取引内容を表すデータを持つ。Bitcoinは実体がないため、どれだけの量のBitcoinがどのアドレスからどのアドレスに移動したか、という内容である。支払い者がどのアドレスからいくらのBitcoinを受け取ったかをInputと呼ぶ。どのアドレスにいくら支払うかをOutputと呼ぶ。データ構造は下記のとおりである。timeには、取引がブロックに含まれる条件を指定することができる。詳細は前回の記事で述べた。銀行などの信頼された金融機関が取引に関与しないことをさす。金融上の取引を行う際、銀行の役割は支払い者に支払いの能力があることと、取引が不正ではないことを保証することである。Bitocinは、そのような信頼される第三者を取引に必要としない。一つ以上の取引データをまとめたものをBlockと呼ぶ。1Blockの最大容量は1MB。Bitcoinのメインネットワークでは約10分にひとつ新しいBlockが生成される。Blockのつながりを指すが、Bitcoinを支える分散型台帳技術を指したり、ネットワークやソフトウェアをさすこともある。ソフトウェアはC++で開発されている。