web-dev-qa-db-ja.com

AndroidリソースとリソースIDの間のマッピングはどのように機能しますか?

AndroidがR.id.XXX

知る限り、リソースはバイナリ形式にコンパイルされていますが、このマッピングロジックは内部でどのように機能しますか?

たぶんこのように動作します:

たとえば、layout1.xmlでは、次のようになりました:

<Button Android:id="@+id/button1" >

aAPTはR.Javaでこれを生成します。

public static final int button1=0x7f05000b;

*。apkが生成されると、@ + id/button1が「0x7f05000b」に置き換えられます。

したがって、私たちが呼び出すとき:

findViewById(R.id.button1);

iDは0x7f05000bのような数字ですが、基本的にはIDに基づいて検索を行います。

ありがとう!

追加

私が本当に知りたいのは、リソースIDの整数がどのようにリソースコンテンツに解析されるのですか?言い換えると、Androidランタイムは、リソースIDを唯一の手がかりとしてリソースコンテンツをどのように見つけますか?

たとえば、リソースIDで描画可能な画像はどのように検出されますか?または、リソースIDで文字列値を見つける方法は?

69
smwikipedia

ビルド時に、aaptツールは定義したすべてのリソースを収集し(個別のファイルまたはファイル内の明示的な定義)、リソースIDをそれらに割り当てます。

リソースIDは、PPTTNNNNという形式の32ビットの数値です。 PPはリソースのパッケージです; TTはリソースのタイプです。NNNNはそのタイプのリソースの名前です。アプリケーションリソースの場合、 PPは常に0x7fです。

TTとNNNNの値はaaptによって任意に割り当てられます-基本的に、新しいタイプごとに、次に利用可能な番号が割り当てられ、使用されます(1から始まります)。同様に、タイプの新しい名前ごとに、次に使用可能な番号が割り当てられ、使用されます(1から始まります)。

したがって、これらのリソースファイルがこの順序でaaptによって処理される場合:

layout/main.xml
drawable/icon.xml
layout/listitem.xml

表示される最初のタイプは「レイアウト」であるためTT == 1.が与えられます。そのタイプの最初の名前は「メイン」であるためNNNN == 1が与えられます。 0x7f010001です。

次に、TT == 2.が与えられるように「描画可能」が表示されます。そのタイプの名はNNNN == 1を取得するために「アイコン」です。最終的なリソースIDは0x7f020001です。

最後に、以前と同じようにTT == 1を持つ別の「レイアウト」が表示されます。これは新しい名前「listitem」を持つため、次の値NNNN == 2を取得します。 。

デフォルトでは、aaptはビルド間でこれらの識別子を同じにしようとしないことに注意してください。リソースが変更されるたびに、すべてのリソースが新しい識別子を取得できます。それらが構築されるたびに、現在の識別子で新しいR.Javaが作成されるため、コードは正しい値を取得します。このため、アプリのさまざまなビルドでリソース識別子を使用できる場所でリソース識別子を永続化しないでください。

リソースがコンパイルされ、識別子が割り当てられると、aaptはソースコード用のR.Javaファイルと、すべてのリソース名、識別子、および値を含む「resources.arsc」というバイナリファイルを生成します(個別のファイルからのリソースの場合) 、それらの値は.apk内のそのファイルへのパスです。実行時にデバイス上で簡単にマップおよび解析できる形式です。

「aapt dump resources <path-to-apk>」コマンドを使用すると、apkでresources.arscファイルの概要を取得できます。

バイナリリソーステーブルの形式は、リソースデータ構造のヘッダーファイルに記載されています。

https://github.com/Android/platform_frameworks_base/blob/master/libs/androidfw/include/androidfw/ResourceTypes.h

デバイスのリソーステーブルを読み取るための完全な実装は次のとおりです。

https://github.com/Android/platform_frameworks_base/blob/master/libs/androidfw/ResourceTypes.cpp

177
hackbod

内部実装(デバイス側)に興味がある場合は、 Resources.Java のloadDrawable()をご覧ください。 データの抽出リソーステーブル に関する情報については、hackbodの優れた回答を参照してください。

リソースIDからレイアウトがどのようにビューに変換されるかを確認するには、チェックアウト LayoutInfater 。Java

7
Reno

私が理解していることから、aaptはリソースごとに一意のIDを自動生成し、ルックアップテーブルに保存します。このルックアップテーブルは、「bin/resources.ap_」にある「resources.arsc」ファイルとして保持されます(これは単なるZipファイルです。お好みのZipビューアーを使用して自由に開いてください)。ルックアップテーブルはR.Javaとしても保持され、ご存じのとおり、Javaでリソースを参照できます。

ARSCファイルの詳細情報が必要な場合は、グーグルで検索するか、 http://code.google.com/p/Android-apktool/ のコードを確認することをお勧めします。

-ダン

5
Dan

最後の注意点:長い間、多くのアイテムはxmlファイルのさらに下のアイテムを参照する必要があるため、相対的なレイアウトを使用しませんでした。また、@ id/foo =まだ定義されていません。

<!-- doesn't work -->
<TextView Android:layout_above="@id/foo">above</textview>
<TextView Android:id="@+id/foo">below</textview>

それからある日、私はあなたがdefine参照のidであることに気づきました。 idを持つ要素内にある必要はありません:

<!-- works -->
<TextView Android:layout_above="@+id/foo">above</textview>
<TextView Android:id="@id/foo">below</textview>
1
Edward Falk

魔法はEclipseプラグインにあり、R.Javaファイルはアプリの「gen」フォルダーに自動生成します。このファイルを覗くと、R.xx.XXXのすべてのXXXの静的マッピングが表示されます。xxは、アニメーション、配列、色、およびその他すべてのリソースタイプです。

0
ErikR