Android 리소스와 리소스 ID 간의 매핑은 어떻게 작동합니까?
Android가 R.id.XXX를 통해 적절한 리소스를 찾는 것은 마술입니다 .
AFAIK, 리소스는 바이너리 형식으로 컴파일됩니다. 그렇다면이 매핑 논리는 내부에서 어떻게 작동합니까?
아마도 다음과 같이 작동합니다.
예를 들어, layout1.xml 에서 다음을 얻었습니다.
<Button android:id="@+id/button1" >
AAPT는 R.java에서 이것을 생성합니다.
public static final int button1=0x7f05000b;
때 *의 .apk 파일이 genrated있는되면, @ + ID / 단추 1 "0x7f05000b"로 substituded 수와.
따라서 다음과 같이 호출 할 때 :
findViewById(R.id.button1);
ID는 0x7f05000b와 같은 숫자이지만 기본적으로 여전히 ID를 기반으로 검색을 수행합니다.
감사!
더하다
내가 정말로 알고 싶은 것은 리소스 ID 정수가 리소스 콘텐츠로 파싱되는 방법입니까? 즉, Android 런타임은 리소스 ID가 유일한 단서 인 리소스 콘텐츠를 어떻게 찾습니까?
예를 들어, 리소스 ID로 드로어 블 그림을 어떻게 찾을 수 있습니까? 또는 리소스 ID로 문자열 값을 어떻게 찾을 수 있습니까?
빌드시 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입니다.
다음으로 "drawable"이 표시되므로 TT == 2가됩니다. 해당 유형의 이름은 "icon"이므로 NNNN == 1이됩니다. 최종 리소스 ID는 0x7f020001입니다.
마지막으로 이전과 같이 TT == 1 인 또 다른 "레이아웃"을 봅니다. 다음 값 NNNN == 2를 가져 오도록 새 이름 "listitem"이 있습니다. 최종 리소스 ID는 0x7f010002입니다.
기본적으로 aapt는 빌드간에 이러한 식별자를 동일하게 유지하려고하지 않습니다. 리소스가 변경 될 때마다 모두 새 식별자를 얻을 수 있습니다. 빌드 될 때마다 코드가 올바른 값을 가져 오도록 현재 식별자로 새 R.java가 생성됩니다. 따라서 앱의 여러 빌드에서 사용할 수있는 위치에 리소스 식별자를 유지해서는 안됩니다.
리소스가 컴파일되고 식별자가 할당되면 aapt는 소스 코드에 대한 R.java 파일과 모든 리소스 이름, 식별자 및 값을 포함하는 "resources.arsc"라는 이진 파일을 생성합니다 (별도의 파일에서 가져온 리소스의 경우). , 해당 값은 런타임에 장치에서 쉽게 mmapp 및 구문 분석 할 수있는 형식으로 .apk에있는 해당 파일의 경로입니다.
"aapt dump resources <path-to-apk>"명령을 사용하여 apk의 resources.arsc 파일 요약을 얻을 수 있습니다.
바이너리 리소스 테이블의 형식은 다음 리소스 데이터 구조의 헤더 파일에 설명되어 있습니다.
장치에서 리소스 테이블을 읽기위한 전체 구현은 다음과 같습니다.
https://github.com/android/platform_frameworks_base/blob/master/libs/androidfw/ResourceTypes.cpp
내부 구현 (장치 측)에 관심이있는 경우 Resources.java의 loadDrawable ()을 살펴보십시오 . 리소스 테이블 에서 데이터 추출에 대한 정보는 hackbod의 우수한 답변을 참조하십시오.
레이아웃이 리소스 ID에서 View로 변환되는 방법을 알고 싶다면 LayoutInfater .java를 확인하세요 .
내가 이해 한 바에 따르면 aapt는 각 리소스에 대한 고유 ID를 자동 생성하고 조회 테이블에 저장합니다. 이 조회 테이블은 "bin / resources.ap_"에있는 "resources.arsc"파일로 유지됩니다 (이것은 단지 ZIP 파일이므로 선호하는 ZIP 뷰어를 사용하여 자유롭게여십시오). 조회 테이블은 R.java로도 유지되며, 아시다시피 Java에서 리소스를 참조 할 수 있습니다.
ARSC 파일에 대한 자세한 정보를 원하시면 인터넷 검색을하거나 http://code.google.com/p/android-apktool/ 의 코드를 검토하시기 바랍니다 .
-단
마지막 메모 : 가장 오랫동안 상대적인 레이아웃을 사용하지 않았습니다. 많은 항목이 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>
마법은 Eclipse 플러그인과 앱의 "gen"폴더에 자동 생성되는 R.java 파일에 있습니다. 이 파일을 들여다 보면 R.xx.XXX의 모든 XXX에 대한 정적 매핑이 표시됩니다. 여기서 xx는 애님, 배열, 색상 및 기타 모든 리소스 유형일 수 있습니다.
'development' 카테고리의 다른 글
Android에서 활성 장치 관리자가 활성화 된 앱을 제거하는 방법은 무엇입니까? (0) | 2020.10.28 |
---|---|
git 프록시 비밀번호에서 @ 문자 이스케이프 (0) | 2020.10.28 |
iframe에 대한 jQuery Force set src 속성 (0) | 2020.10.28 |
redirectMode =“ResponseRewrite”를 설정하면 CustomErrors가 작동하지 않습니다. (0) | 2020.10.28 |
Javascript에서 NodeList를 배열로 변환하는 가장 좋은 방법은 무엇입니까? (0) | 2020.10.28 |