2024.10.01
自社の社内情報を未来の“ゴミ”にしないための備え 「情報量が多すぎる」時代がもたらす課題とは?
Deep Dive into Slice(全1記事)
リンクをコピー
記事をブックマーク
もり氏(以下、もり):こんばんは。Slicesの内部実装を見ながら自分でこういうの作るにはどうやって作るだろう的な、ちょっと益体のない話をしようと思っています。
自己紹介させてください。森と言います。ヤフーから来ました。
ヤフーには黒帯というこういう場でお話ししたりする役割があるんですが、私はAndroid分野で黒帯をしております。そのほかヤフオクもやっております。
いきなり宣伝になってしまいますが、最近本を出しました。
ところで今我々はこちらヒカリエにいるんですけれども、なんとここに啓文堂書店があります。啓文堂書店、よろしくお願いします。
(会場笑)
では始めていきたいと思います。Slicesについてです。
まずSlicesの仕組みなんですけれども。Slicesを返すSliceProvider、我々はこれを作ります。
このSliceProviderはContentProviderを継承していて、ContentProviderなのでSlicesを表示する側はURIをもとにデータ、ここではSlicesを要求するという感じで動いています。
Slices自体がこんな感じで構造化されたフォーマットのデータになっています。
ほかのSlicesとか表示フォーマットだとかアイコンなんかが含まれています。
SliceProviderを実装するにはAndroid Studio 3.2を入れて右クリックして、NewからOther、SliceProviderを押せば終わりなんすけれども。
それだとあんまりなので少し説明を入れると、SliceProviderを継承したクラスを作ってonBindSliceメソッドの中でSlicesを作って返すという感じで作ります。
これは結局ContentProviderなのでマニフェストファイルにAuthorityとともに追加するという感じで使います。
こうして我々サードパーティーはSliceProviderを作るわけなんですが、作ったとしてどこで使ってもらえるのか? 最初はGoogle検索アプリで使用されます。
Google検索アプリでユーザーがクエリを入力するときのサジェストの中に、自分のアプリのSlicesを表示してもらえる可能性があります。
そのための方法が2通りあって、まずユーザーがアプリ名を入力したときに表示する方法。この方法は簡単で、マニフェストファイルのメインアクティビティにメタデータを追加します。
このメタデータにSlicesに対応するURIを設定して、アクティビティの中でGoogle Play ServicesとGoogle検索のパーミッションを入れれば終わりです。
でもGoogle検索アプリでアプリ名で検索するユーザーって……そんなユースケースあるかな? って感じなので,一般的な単語での検索に反応したいなっていうところです。
これのやり方なんですけれども、FirebaseAppIndexingにIndex登録するときにメタデータとしてSlicesのURIを追加する。こうするとAppIndexingが使用されるタイミングでSlicesが使われる可能性があるという感じになります。
そのあとマニフェストファイルのSliceProviderのエレメントにIndexしたURLを受け取るintent-filterを追加します。SlicesのURIではなくてIndexしたURLを設定します。
最後にSlicesプロバイダーのonMapIntentToUriというところで、AppIndexingが渡してくるディープリンクのURLをSlicesのURIに変換して返すという感じです。
以上がGoogle検索アプリで表示してもらう場合の方法です。
ところでサードパーティーは表示できないのか? というところです。Google検索アプリで表示してもらえるだけでもけっこう嬉しいんですが、サードパーティーのアプリ間で連携できればもうちょっと便利そうな感じがします。
特にヤフーにはたくさんのサービスがあって、いろんなアプリを世に出しています。これらで連携できるようになると、なんか便利そうだなって思うわけですね。ヤフオクのケースだと、例えば決済アプリでネイティブ化するということもできそうです。
こういう連携をどうすれば実現できるかなんですけども。ステップ1、待つ。
(会場笑)
というのもGoogle I/Oから帰ってきたときにGoogleの人と話してきたんですが、Slicesの表示をサードパーティーに解放するかどうかはまだ決まっていない。
今、Slice Viewerというものが公開されていて、SliceViewというSlicesを表示する用のViewもJetpackの中に入ってるんですけども。このAPIも今後どうなるかわからないということを言っていました。
じゃあ、Slicesの表示が解放されなかったらどうやってサードパーティ間連携をしていったらいいのでしょうか? 作りましょう、それっぽいのを。
というわけでSlicesが具体的にどう動いてるのかを追いかけてみたいと思います。今回はSliceViewerのソースコードをもとにSliceを要求するところからSlicesを作って返すところまで追いかけていきたいと思います。
まずSlicesを要求するところから。
SliceViewerではSliceViewのbindメソッドを呼ぶことでSlicesのリクエストが開始されます。
これは拡張関数でして、中ではSliceLiveDataというクラスを生成して値を監視しています。
SliceLiveDataではSliceManagerのインスタンスを取得して、bindSliceメソッドを呼びます。
このSliceManagerのgetInstanceメソッドはAndroid P以降かどうかで返すインスタンスが変わってきます。
Android P以降の場合SliceManagerのラッパーを返すんですが、これは新たに爆誕したSliceManagerというシステムサービスをラップしたものになります。
P未満の場合はSliceManagerCompatというクラスのインスタンスを返します。自分でシステムマネージャー作っても虚しいだけなので、今回はこっちのSliceManagerCompatを追いかけていきます。
このbindSlicesが呼ばれてたいたわけなんですが、このクラスはSliceProviderCompatのメソッドを呼ぶだけのクラスです。今、Slicesを要求している側なんですけども、実はSlicesを返す側もSliceProviderCompatを使います。
実は間にはSliceProviderCompatが入ってお互いのSliceProviderCompat同士で通信します。SliceProviderCompatではURIをチェックしたりしてbindSlicesを呼びます。
ここが終着点なんですが、ContentResolverからContentProviderClientを取得してcallメソッドを呼んで、その戻り値のバンドルからSlicesを生成して返します。
ContentProviderを使ったことがある人っていますか?
(会場挙手)
いっぱいいますよね。ContentProviderClientを使ったことがある人っていますか?
いないですね。ContentProviderClientはAPIレベル5からある古株のクラスです。ContentResolverを経由しないで直接ContentProviderとやり取りするためのものです。
ContentProviderデータを要求するときに毎回ContentResolverを使っていると、毎回URIから対応するプロバイダはどれかなって探す処理が走ります。この探す処理がなくなるのでかなり高速化します。
そのcallメソッドなんですが、リレーショナルな感じでリクエストしないときに使うようなメソッドです。引数としてメソッド名を渡します。
実際には任意のメソッドを呼ぶわけじゃなくて、対応するプロバイダーのcallメソッドが呼ばれます。呼び出されたプロバイダ側で引数として渡されるメソッド名や引数を判定して、なにかを実行して結果をBundleで返します。
ここまでがSlicesを要求するフェーズです。結局のところSliceProviderCompatのcallメソッドを呼んでいました。これに対してSlicesを返す側のアプリは何をしているのかを追いかけてみたいと思います。
callメソッドはこうなっています。handleBindSliceというメソッド内でSlicesを作って、Bundleに変換して、さらにBundleに積んで返しています。
Slicesを作っているhandleBindSliceを見てみると、こんな感じです。
なんやかんやでonBindSliceStrictを呼びます。そのonBindSliceStrictがSlicesを生成するときの終着点になります。
2秒でANRが発生するように設定して、ディスクI/Oなど重たい処理をしたらクラッシュするようにしたうえで、SliceProviderのonBindSliceを呼びます。
SliceProviderのonBindSliceは最初に説明したとおり、自分でオーバーライドして実装するものです。
なので大切なのはSlicesが要求されたときに自分で返す場合には、同期的なディスクI/Oだとかネットワークをしないで、2秒以内に返さないといけません。
すぐに返せないのであれば一旦「読み込み中」とでも返しておいて非同期的にデータを取得してnotifyChangeを呼ぶようにしましょう。
こんな感じでSlicesを返しました。そのSlicesはどのように表示されているかですが、もともとライブデータ内で要求されていたので、まずはpostValueでライブデータを更新します。
それを受け取って、SliceView内のプロパティを更新します。
プロパティアクセスっぽく見えるんですが、実際にはSliceViewのsetSliceが呼ばれていて。メソッド内のreinflateというメソッドを呼びます。
この中でSlicesの値、プロパティを読み取りながらViewを生成していくんですが、そこは単純なのでこれ以降は省略します。
長々とSlicesの内部実装を見てきたわけですが、こうしたSlicesめいたものを自分で作るんだったらどうするのか、ということでまとめます。
まずBundleと相互変換できるクラスを作ります。次にContentProviderClientを使ってBundleをやり取りします。最後にBundleから元のクラスに戻して、その値を参照しながらViewを生成するロジックを書く。ここだけ見ると簡単そうに見えまが、ひたすらめんどくさい感じになります。
全体のまとめとしては、Slicesは古典的なAPIをうまく使って作られています。まずはGoogle検索アプリで使われます。サードパーティー間の連携に使用できるかはまだ不透明なようです。
でも似たようなことは作れるようになりましたね。ということで、ご静聴ありがとうございました。
(会場拍手)
関連タグ:
2024.10.29
5〜10万円の低単価案件の受注をやめたら労働生産性が劇的に向上 相見積もり案件には提案書を出さないことで見えた“意外な効果”
2024.10.24
パワポ資料の「手戻り」が多すぎる問題の解消法 資料作成のプロが語る、修正の無限ループから抜け出す4つのコツ
2024.10.28
スキル重視の採用を続けた結果、早期離職が増え社員が1人に… 下半期の退職者ゼロを達成した「関係の質」向上の取り組み
2024.10.22
気づかぬうちに評価を下げる「ダメな口癖」3選 デキる人はやっている、上司の指摘に対する上手な返し方
2024.10.24
リスクを取らない人が多い日本は、むしろ稼ぐチャンス? 日本のGDP4位転落の今、個人に必要なマインドとは
2024.10.23
「初任給40万円時代」が、比較的早いうちにやってくる? これから淘汰される会社・生き残る会社の分かれ目
2024.10.23
「どうしてもあなたから買いたい」と言われる営業になるには 『無敗営業』著者が教える、納得感を高める商談の進め方
2024.10.28
“力を抜くこと”がリーダーにとって重要な理由 「人間の達人」タモリさんから学んだ自然体の大切さ
2024.10.29
「テスラの何がすごいのか」がわからない学生たち 起業率2年連続日本一の大学で「Appleのフレームワーク」を教えるわけ
2024.10.30
職場にいる「困った部下」への対処法 上司・部下間で生まれる“常識のズレ”を解消するには