80

AndroidがR.id.XXXから適切なリソースを見つけるのは魔法のようです。

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

多分それはこのように動作します:

たとえば、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で文字列値を見つけるにはどうすればよいですか?

4

5 に答える 5

198

ビルド時に、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

最初に表示されるタイプは「layout」であるため、TT == 1 が指定されます。そのタイプの最初の名前は「main」であるため、NNNN == 1 が指定されます。最終的なリソース ID は 0x7f010001 です。

次に、TT == 2 が与えられる「drawable」が表示されます。そのタイプの最初の名前は「icon」であるため、NNNN == 1 が取得されます。最終的なリソース ID は 0x7f020001 です。

最後に、以前と同様に TT == 1 を持つ別の「レイアウト」を確認します。これは新しい名前「listitem」を持つため、次の値 NNNN == 2 を取得します。最終的なリソース ID は 0x7f010002 です。

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

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

コマンド「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

于 2011-07-11T05:29:33.220 に答える
8

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

レイアウトがリソース ID からビューにどのように変換されるかを知るには、LayoutInfater .javaをチェックしてください。

于 2011-06-29T08:15:18.557 に答える
6

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

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

-ダン

于 2011-07-05T12:02:12.860 に答える
1

最後に 1 つ: 長い間、相対レイアウトを使用していませんでした。これは、多くのアイテムが xml ファイルのさらに下のアイテムを参照する必要があり、定義されていない@id/fooを参照する方法がわからなかったからです。まだ。

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

それからある日、参照でIDを定義できることに気づきました。ID を持つ要素にある必要はありません。

<!-- works -->
<TextView android:layout_above="@+id/foo">above</textview>
<TextView android:id="@id/foo">below</textview>
于 2013-09-14T16:29:00.220 に答える
0

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

于 2011-06-29T07:46:01.333 に答える