「リソースをコンパイルする」とはどういう意味かを理解しようとしています。
私はこの主題について多くの記事を読みましたが、簡単な答えは見つかりませんでした。私が読んだ最高のものはこれでした: AndroidリソースとリソースID間のマッピングはどのように機能しますか? 。
私の理解では、ANT(Eclipse)またはGradle(AS)でプロジェクトをコンパイルするとき。 aapt-Android Asset Packaging Toolというツールを使用します。レイアウト、スタイルなどのリソースをルックアップテーブルに格納し、2つのファイルを生成してこのルックアップテーブルを永続化します。
簡単にするために、activity_main.xmlにこれがあるとしましょう。
_ <TextView Android:id="@+id/my_textView"
Android:text="@string/hello_world"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content" />
_
そして、次を使用してonCreateから呼び出します:
_findViewById(R.id.my_textView)
_
R.Javaファイルに次のように表示されます。
_public static final int my_textView=0x7f08003f;
_
使用:生成されたapkのaaptダンプリソースには、my_textViewの2行が含まれています:ec resource 0x7f08003f com.example.lizi.liortest2:id/my_textView:flags = 0x00000000 resource 0x7f08003f com.example.lizi.liortest2:id/my_textView :t = 0x12 d = 0x00000000(s = 0x0008 r = 0x00)
このresources.arscファイルには、リソースIDだけでなく、Android:layout_width = "wrap_content"など、ビューに定義したすべてのプロパティも含まれると考えていました。
では、実行中にVMがfindViewById(R.id.my_textView)
を実行しようとすると、どのビューを取得するか、そのプロパティを作成するかをどのように知るのでしょうか?
私は単にそれがどのように機能するか理解できません...このルックアップテーブルにはプロパティデータも含まれるべきではありませんか?そして、この0x7f08003f番号は何ですか? (オブジェクトが格納される物理メモリに後でマップされる値を表す必要がありますか?)
TL; DR:Android compiler(aapt)xmlノードは、Javaクラスと、数値IDに対応する属性に変換されます。Androidランタイムはこれらで動作しますビューを作成するためにクラスをインスタンス化するID
このコマンドを実行して、バイナリxmlをダンプします
_aapt d xmltree apk_file_name res/layout/activity_main.xml
_(aaptはAndroid-sdk-dir/build-tools/23.0.2/aapt.exe)
これにより、xmlノード(例:LinearLayout
、RelativeLayout
など)とその属性(_Android:layout_width, Android:layout_height
_)および値が表示されます。定数_match_parent
_(数値_0xffffffff
_または_-1
_)または_wrap_content
_(数値_0xfffffffe
_または_-2
_)が表示されることに注意してください。
実際のところ、apkの他のxmlファイルでこのコマンドを使用できます。 _AndroidManifest.xml or layout files
_
Apkファイルは、すべてのJavaクラスファイル(_classes.dex
_)、すべてのコンパイル済みリソースファイル、および_resources.arsc
_という名前のファイルを含むZipアーカイブです。この_resource.arsc
_ファイルには、リソースに関するすべてのメタ情報が含まれています。
LinearLayout
、RelativeLayout
など)、Android:layout_width
_)、id
's。リソースid
は、apkファイル内の実際のリソースを参照します。属性は実行時に値に解決されます。解決プロセスは、リダイレクト(_@dimen/...
_ではなく_4dp
_または_@color/...
_ではなく_"#FFaabbcc"
_)に対して賢く、使用可能な値(a dimen
値は、color
値とは異なる方法で解決されます)。
コンパイル済みXMLファイルとは:コンパイル済みXMLファイルは、リソース参照が対応するids
に変更された同じXMLファイルです。たとえば、参照_@string/ok
_は_0x7f000001
_に置き換えられます。さらに、Android
名前空間の属性はそれぞれの整数値に変更されます(例:_wrap_content
_は_0xfffffffe
_または_-2
_に変更されます)
How Android実行時にリソースを解決する:メソッド inflater.inflate()
解析するコンパイルされたxmlファイル。xmlノードをインスタンス化してビュー階層を作成します。各xmlノードはJava class(LinearLayout.Java、RelativeLayout.Java)などによってインスタンス化されます。インスタンス化するには、 inflaterは、コンパイルされたxmlファイルを解析し、ノードのすべての属性を収集し、 creates タイプのパック構造 AttributeSet
。このAttributeSet
はクラスコンストラクターに渡されるクラスコンストラクターは、AttributeSet
を調べて、各属性値を解決する責任があります。
たとえば、RelativeLayout
を含むレイアウトの場合、inflater
は_layout_width
_および_layout_height
_をAttributeSet
にパックし、コンストラクターに渡します- RelativeLayout(コンテキストコンテキスト、AttributeSet attrs、int defStyleAttr、int defStyleRes) 。この場合、一部の属性とその値は RelativeLayout.initFromAttributes() で解決され、残りは親 ViewGroup.initFromAttributes() で解決されます。
ビューの_Android:id
_は、単なる別の属性です。インフレータは、インスタンス化後にそのビューで setId(id)
を呼び出す によって各ビューのIDを保存します
質問に答える_R.id
_はJava配列で_my_textview
_は整数ですビューのid
_my_textview
_はこの整数です(0x7fで始まります) findViewById()
メソッドは、深さ優先検索を行いますそのビュー階層を使用して、それぞれのビューを見つけます。
お役に立てれば。質問で指定した link は、aaptによるIDの生成方法に既に回答しています。
さまざまな次元のバリエーションを持つデバイスのリソースを管理するすばらしいシステムです。さらに、実装は非常に高速です!!これを基盤として、より高いレベルの機能を実装することができます(例 Runtime Resource Overlay )
LayoutInflater XML文字列を使用してビューを展開します。質問で述べたように、リソースファイルにコンパイルされたXML文字列。
AOSPのこれらのコードスニペットを確認してください。
public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
final Resources res = getContext().getResources();
if (DEBUG) {
Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
+ Integer.toHexString(resource) + ")");
}
final XmlResourceParser parser = res.getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
}
Resources.getLayout
XMLリソースパーサーをロードします
public XmlResourceParser getLayout(int id) throws NotFoundException {
return loadXmlResourceParser(id, "layout");
}
XmlResourceParser loadXmlResourceParser(int id, String type)
throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
mTmpValue = value = new TypedValue();
}
getValue(id, value, true);
if (value.type == TypedValue.TYPE_STRING) {
return loadXmlResourceParser(value.string.toString(), id,
value.assetCookie, type);
}
throw new NotFoundException(
"Resource ID #0x" + Integer.toHexString(id) + " type #0x"
+ Integer.toHexString(value.type) + " is not valid");
}
}
getValue
は AssetManager の getResourceValue を使用し、loadResourceValue
ネイティブメソッドを呼び出します。このネイティブメソッドは、ResTable
の- getResource メソッドを呼び出して、リソースファイルに格納されているXML文字列を取得します。
Use appt for Android-sdk (ex:- /build-tools/27.0.3/aapt )
run given script and get resources.arsc file content
./aapt dump resources ./debug.apk
Package Groups (1)
Package Group 0 id=0x7f packageCount=1 name=com.dianping.example.activity
Package 0 id=0x7f name=com.dianping.example.activity
type 1 configCount=3 entryCount=1
spec resource 0x7f020000 com.example.activity:drawable/ic_launcher: flags=0x00000100
config mdpi-v4:
resource 0x7f020000 com.example.activity:drawable/ic_launcher: t=0x03 d=0x00000000 (s=0x0008 r=0x00)
config hdpi-v4:
resource 0x7f020000 com.example.activity:drawable/ic_launcher: t=0x03 d=0x00000001 (s=0x0008 r=0x00)
config xhdpi-v4:
resource 0x7f020000 com.example.activity:drawable/ic_launcher: t=0x03 d=0x00000002 (s=0x0008 r=0x00)
type 2 configCount=1 entryCount=1
spec resource 0x7f030000 com.dianping.example.activity:string/app_name: flags=0x00000000
config (default):
resource 0x7f030000 com.dianping.example.activity:string/app_name: t=0x03 d=0x00000003 (s=0x0008 r=0x00)
このリンクは役立つかもしれません http://elinux.org/Android_aapt