ในระดับสูง กฎการเก็บจะระบุคลาส (หรือคลาสย่อยหรือการใช้งาน) จากนั้นก็ระบุสมาชิก ซึ่งได้แก่ เมธอด ตัวสร้าง หรือฟิลด์ภายในคลาสนั้นเพื่อเก็บไว้
ไวยากรณ์ทั่วไปสำหรับกฎการเก็บมีดังนี้ แต่ตัวเลือกการเก็บข้อมูลบางอย่างไม่ยอมรับ keep_option_modfier
ที่ไม่บังคับ
-<keep_option>[,<keep_option_modifier_1>,<keep_option_modifier_2>,...] <class_specification>
ตัวอย่างต่อไปนี้คือกฎการเก็บที่ใช้ keepclassmembers
เป็นตัวเลือกการเก็บ allowoptimization
เป็นตัวแก้ไข และเก็บ someSpecificMethod()
จาก com.example.MyClass
-keepclassmembers,allowoptimization class com.example.MyClass {
void someSpecificMethod();
}
ตัวเลือกการเก็บ
ตัวเลือกการเก็บคือส่วนแรกของกฎการเก็บ โดยจะระบุลักษณะของคลาสที่จะเก็บไว้ โดยมีตัวเลือกการเก็บ 6 แบบ ได้แก่ keep
,
keepclassmembers
, keepclasseswithmembers
, keepnames
,
keepclassmembernames
, keepclasseswithmembernames
ตารางต่อไปนี้จะอธิบายตัวเลือกการเก็บรักษาเหล่านี้
ตัวเลือก Keep | คำอธิบาย |
---|---|
keepclassmembers |
เก็บเฉพาะสมาชิกที่ระบุไว้หากชั้นเรียนยังคงมีอยู่หลังจากการเพิ่มประสิทธิภาพ |
keep |
คงคลาสและสมาชิก (ฟิลด์และเมธอด) ที่ระบุไว้ เพื่อป้องกันไม่ให้มีการเพิ่มประสิทธิภาพ หมายเหตุ: โดยทั่วไปแล้ว keep ควรใช้กับตัวแก้ไขตัวเลือกการคงค่าเท่านั้น เนื่องจาก keep เพียงอย่างเดียวจะป้องกันไม่ให้มีการเพิ่มประสิทธิภาพใดๆ ในคลาสที่ตรงกัน |
keepclasseswithmembers |
เก็บรักษาชั้นเรียนและสมาชิกที่ระบุไว้เฉพาะในกรณีที่ชั้นเรียนมีสมาชิกทั้งหมดตามที่ระบุไว้ในชั้นเรียน |
keepclassmembernames |
ป้องกันไม่ให้เปลี่ยนชื่อสมาชิกในชั้นเรียนที่ระบุ แต่ไม่ได้ป้องกันไม่ให้นำชั้นเรียนหรือสมาชิกออก หมายเหตุ: ผู้ใช้มักเข้าใจความหมายของตัวเลือกนี้ผิด ให้ลองใช้ -keepclassmembers,allowshrinking ที่เทียบเท่าแทน |
keepnames |
ป้องกันการเปลี่ยนชื่อชั้นเรียนและสมาชิก แต่ไม่ได้ป้องกันไม่ให้ระบบนำชั้นเรียนและสมาชิกออกทั้งหมดหากเห็นว่าไม่ได้ใช้งาน หมายเหตุ: ผู้ใช้มักเข้าใจความหมายของตัวเลือกนี้ผิด ให้ลองใช้ -keep,allowshrinking ที่เทียบเท่าแทน |
keepclasseswithmembernames |
ป้องกันการเปลี่ยนชื่อชั้นเรียนและสมาชิกที่ระบุ แต่จะทำได้ก็ต่อเมื่อสมาชิกอยู่ในโค้ดสุดท้าย แต่ไม่ได้ป้องกันการนำโค้ดออก หมายเหตุ: มักจะมีการเข้าใจความหมายของตัวเลือกนี้ผิด ให้ลองใช้ -keepclasseswithmembers,allowshrinking ที่เทียบเท่าแทน |
เลือกตัวเลือกการเก็บที่เหมาะสม
การเลือกตัวเลือกการเก็บที่เหมาะสมเป็นสิ่งสำคัญในการกำหนดการเพิ่มประสิทธิภาพที่เหมาะสม สำหรับแอปของคุณ ตัวเลือกการเก็บบางอย่างจะลดขนาดโค้ด ซึ่งเป็นกระบวนการที่ โค้ดที่ไม่ได้อ้างอิงจะถูกนำออก ในขณะที่ตัวเลือกอื่นๆ จะทำให้โค้ดสับสนหรือเปลี่ยนชื่อโค้ด ตารางต่อไปนี้แสดงการดำเนินการของตัวเลือกการเก็บรักษาต่างๆ
ตัวเลือก Keep | ลดขนาดคลาส | ปิดบังคลาส | ลดจำนวนสมาชิก | ซ่อนสมาชิก |
---|---|---|---|---|
keep |
||||
keepclassmembers |
||||
keepclasseswithmembers |
||||
keepnames |
||||
keepclassmembernames |
||||
keepclasseswithmembernames |
ตัวปรับแต่งตัวเลือก Keep
ตัวแก้ไขตัวเลือกการเก็บจะใช้เพื่อควบคุมขอบเขตและลักษณะการทำงานของกฎการเก็บ คุณสามารถเพิ่มตัวแก้ไขตัวเลือก keep 0 รายการขึ้นไปลงในกฎการเก็บรักษา
ค่าที่เป็นไปได้สำหรับตัวแก้ไขตัวเลือกการเก็บจะอธิบายไว้ในตารางต่อไปนี้
ค่านิยม | คำอธิบาย |
---|---|
allowoptimization |
อนุญาตให้เพิ่มประสิทธิภาพองค์ประกอบที่ระบุ อย่างไรก็ตาม ระบบจะไม่เปลี่ยนชื่อหรือนำองค์ประกอบที่ระบุออก |
allowobfucastion |
อนุญาตให้เปลี่ยนชื่อองค์ประกอบที่ระบุ อย่างไรก็ตาม จะไม่มีการนำองค์ประกอบออกหรือเพิ่มประสิทธิภาพองค์ประกอบ |
allowshrinking |
อนุญาตให้นำองค์ประกอบที่ระบุออกได้หาก R8 ไม่พบการอ้างอิงถึงองค์ประกอบเหล่านั้น อย่างไรก็ตาม ระบบจะไม่เปลี่ยนชื่อหรือเพิ่มประสิทธิภาพองค์ประกอบ |
includedescriptorclasses |
สั่งให้ R8 เก็บรักษาคลาสทั้งหมดที่ปรากฏในตัวอธิบายของเมธอด (ประเภทพารามิเตอร์และประเภทการคืนค่า) และฟิลด์ (ประเภทฟิลด์) ที่จะเก็บไว้ |
allowaccessmodification |
อนุญาตให้ R8 เปลี่ยน (โดยปกติคือขยาย) ตัวแก้ไขการเข้าถึง (public , private , protected ) ของคลาส เมธอด และฟิลด์ในระหว่างกระบวนการเพิ่มประสิทธิภาพ |
allowrepackage |
อนุญาตให้ R8 ย้ายคลาสไปยังแพ็กเกจต่างๆ รวมถึงแพ็กเกจเริ่มต้น (รูท) |
ข้อกำหนดของชั้นเรียน
คุณต้องระบุคลาส คลาสแม่ หรืออินเทอร์เฟซที่ติดตั้งใช้งานเป็นส่วนหนึ่งของกฎ keep
ต้องระบุคลาสทั้งหมด รวมถึงคลาสจากเนมสเปซ java.lang
เช่น
java.lang.String
โดยใช้ชื่อ Java ที่สมบูรณ์ หากต้องการ
ทำความเข้าใจชื่อที่ควรใช้ ให้ตรวจสอบไบต์โค้ดโดยใช้เครื่องมือ
ที่อธิบายไว้ในรับชื่อ Java ที่สร้างขึ้น
ตัวอย่างต่อไปนี้แสดงวิธีระบุคลาส MaterialButton
- ถูกต้อง:
com.google.android.material.button.MaterialButton
- ไม่ถูกต้อง:
MaterialButton
นอกจากนี้ ข้อมูลจำเพาะของชั้นเรียนยังระบุสมาชิกในชั้นเรียนที่
ควรเก็บไว้ด้วย กฎต่อไปนี้จะเก็บคลาส MaterialButton
และสมาชิกทั้งหมดไว้
-keep class com.google.android.material.button.MaterialButton { *; }
คลาสย่อยและการใช้งาน
หากต้องการกำหนดเป้าหมายไปยังคลาสย่อยหรือคลาสที่ใช้การติดตั้งใช้งานอินเทอร์เฟซ ให้ใช้ extend
และ
implements
ตามลำดับ
ตัวอย่างเช่น หากคุณมีคลาส Bar
ที่มีคลาสย่อย Foo
ดังนี้
class Foo : Bar()
กฎการเก็บรักษาต่อไปนี้จะเก็บรักษาสับคลาสทั้งหมดของ Bar
โปรดทราบว่า
กฎ keep ไม่รวมคลาสหลัก Bar
เอง
-keep class * extends Bar
หากคุณมีคลาส Foo
ที่ใช้ Bar
ให้ทำดังนี้
class Foo : Bar
กฎการเก็บรักษาต่อไปนี้จะเก็บรักษาคลาสทั้งหมดที่ใช้ Bar
โปรดทราบว่า
กฎการเก็บรักษาไม่ได้รวมอินเทอร์เฟซ Bar
เอง
-keep class * implements Bar
ตัวแก้ไขการเข้าถึง
คุณระบุตัวแก้ไขการเข้าถึง เช่น public
, private
, static
และ final
เพื่อให้กฎการเก็บรักษาแม่นยำยิ่งขึ้นได้
ตัวอย่างเช่น กฎต่อไปนี้จะเก็บคลาส public
ทั้งหมดไว้ในแพ็กเกจ api
และแพ็กเกจย่อย รวมถึงสมาชิกแบบสาธารณะและแบบป้องกันทั้งหมดในคลาสเหล่านี้
-keep public class com.example.api.** { public protected *; }
นอกจากนี้ คุณยังใช้ตัวแก้ไขสำหรับสมาชิกในชั้นเรียนได้ด้วย ตัวอย่างเช่น กฎต่อไปนี้จะเก็บเฉพาะpublic static
เมธอดของคลาส Utils
-keep class com.example.Utils {
public static void *(...);
}
ตัวแก้ไขเฉพาะ Kotlin
R8 ไม่รองรับตัวแก้ไขเฉพาะของ Kotlin เช่น internal
และ suspend
โปรดใช้หลักเกณฑ์ต่อไปนี้เพื่อเก็บช่องดังกล่าว
หากต้องการเก็บ
internal
คลาส เมธอด หรือฟิลด์ ให้ถือว่าเป็นแบบสาธารณะ ตัวอย่างเช่น ลองพิจารณาแหล่งที่มาของ Kotlin ต่อไปนี้package com.example internal class ImportantInternalClass { internal f: Int internal fun m() {} }
คลาส เมธอด และฟิลด์
internal
จะเป็นpublic
ในไฟล์ที่คอมไพเลอร์ Kotlin สร้างขึ้น ดังนั้นคุณต้องใช้คีย์เวิร์ดpublic
ตามที่แสดงในตัวอย่างต่อไปนี้.class
-keepclassmembers public class com.example.ImportantInternalClass { public int f; public void m(); }
เมื่อรวบรวม
suspend
สมาชิก ให้จับคู่ลายเซ็นที่รวบรวมไว้ใน กฎการเก็บรักษาเช่น หากคุณมีฟังก์ชัน
fetchUser
ที่กำหนดตามที่แสดงใน ข้อมูลโค้ดต่อไปนี้suspend fun fetchUser(id: String): User
เมื่อคอมไพล์แล้ว ลายเซ็นในไบต์โค้ดจะมีลักษณะดังนี้
public final Object fetchUser(String id, Continuation<? super User> continuation);
หากต้องการเขียนกฎการเก็บรักษาสำหรับฟังก์ชันนี้ คุณต้องจับคู่ลายเซ็นที่คอมไพล์นี้ หรือใช้
...
ตัวอย่างการใช้ลายเซ็นที่คอมไพล์แล้วมีดังนี้
-keepclassmembers class com.example.repository.UserRepository { public java.lang.Object fetchUser(java.lang.String, kotlin.coroutines.Continuation); }
ตัวอย่างการใช้
...
มีดังนี้-keepclassmembers class com.example.repository.UserRepository { public java.lang.Object fetchUser(...); }
ข้อกำหนดของสมาชิก
การระบุคลาสอาจรวมถึงสมาชิกของคลาสที่จะเก็บไว้ด้วย (ไม่บังคับ) หากคุณระบุสมาชิกอย่างน้อย 1 คนสำหรับชั้นเรียน กฎจะมีผลกับสมาชิกเหล่านั้นเท่านั้น
ตัวอย่างเช่น หากต้องการเก็บรักษาชั้นเรียนที่เฉพาะเจาะจงและสมาชิกทั้งหมด ให้ใช้คำสั่งต่อไปนี้
-keep class com.myapp.MyClass { *; }
หากต้องการเก็บรักษาเฉพาะชั้นเรียนและไม่รวมสมาชิก ให้ใช้คำสั่งต่อไปนี้
-keep class com.myapp.MyClass
โดยส่วนใหญ่แล้ว คุณจะต้องระบุสมาชิกบางราย ตัวอย่างเช่น ตัวอย่างต่อไปนี้จะเก็บฟิลด์สาธารณะ text
และเมธอดสาธารณะ updateText()
ไว้ในคลาส MyClass
-keep class com.myapp.MyClass {
public java.lang.String text;
public void updateText(java.lang.String);
}
หากต้องการเก็บฟิลด์และเมธอดสาธารณะทั้งหมดไว้ ให้ดูตัวอย่างต่อไปนี้
-keep public class com.example.api.ApiClient {
public *;
}
วิธีการ
ไวยากรณ์สำหรับการระบุวิธีการในการระบุสมาชิกสำหรับกฎการเก็บมีดังนี้
[<access_modifier>] [<return_type>] <method_name>(<parameter_types>);
ตัวอย่างเช่น กฎการเก็บรักษาต่อไปนี้จะเก็บรักษาวิธีการสาธารณะที่ชื่อ setLabel()
ซึ่งแสดงผลเป็น void และรับ String
-keep class com.example.MyView {
public void setLabel(java.lang.String);
}
คุณใช้ <methods>
เป็นแป้นพิมพ์ลัดเพื่อจับคู่เมธอดทั้งหมดในคลาสได้ดังนี้
-keep class com.example.MyView {
<methods>;
}
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีระบุประเภทสำหรับประเภทการคืนค่าและประเภทพารามิเตอร์ได้ที่ประเภท
ผู้ผลิต
หากต้องการระบุตัวสร้าง ให้ใช้ <init>
ไวยากรณ์สำหรับการระบุตัวสร้าง
ในข้อกำหนดของสมาชิกสำหรับกฎการเก็บมีดังนี้
[<access_modifier>] <init>(parameter_types);
ตัวอย่างเช่น กฎการเก็บรักษาต่อไปนี้จะเก็บตัวสร้าง View
ที่กำหนดเองซึ่ง
รับ Context
และ AttributeSet
-keep class com.example.ui.MyCustomView {
public <init>(android.content.Context, android.util.AttributeSet);
}
หากต้องการเก็บตัวสร้างสาธารณะทั้งหมด ให้ใช้ตัวอย่างต่อไปนี้เป็นข้อมูลอ้างอิง
-keep class com.example.ui.MyCustomView {
public <init>(...);
}
ช่อง
ไวยากรณ์สำหรับการระบุฟิลด์ในข้อกำหนดของสมาชิกสำหรับกฎการเก็บมีลักษณะดังนี้
[<access_modifier>...] [<type>] <field_name>;
เช่น กฎ keep ต่อไปนี้จะเก็บฟิลด์สตริงส่วนตัวที่ชื่อ
userId
และฟิลด์จำนวนเต็มแบบคงที่สาธารณะที่ชื่อ STATUS_ACTIVE
-keep class com.example.models.User {
private java.lang.String userId;
public static int STATUS_ACTIVE;
}
คุณใช้ <fields>
เป็นทางลัดเพื่อจับคู่ช่องทั้งหมดในชั้นเรียนได้ดังนี้
-keep class com.example.models.User {
<fields>;
}
ฟังก์ชันระดับแพ็กเกจ
หากต้องการอ้างอิงฟังก์ชัน Kotlin ที่กำหนดไว้นอกคลาส (โดยทั่วไปเรียกว่าฟังก์ชันระดับบนสุด) ให้ตรวจสอบว่าได้ใช้ชื่อ Java ที่สร้างขึ้นสำหรับคลาสที่คอมไพเลอร์ Kotlin เพิ่มโดยนัย ชื่อคลาสคือชื่อไฟล์ Kotlin
ที่ต่อท้ายด้วย Kt
ตัวอย่างเช่น หากคุณมีไฟล์ Kotlin ชื่อ
MyClass.kt
ที่กำหนดไว้ดังนี้
package com.example.myapp.utils
// A top-level function not inside a class
fun isEmailValid(email: String): Boolean {
return email.contains("@")
}
หากต้องการเขียนกฎการเก็บสำหรับฟังก์ชัน isEmailValid
ข้อกำหนดของคลาส
ต้องกำหนดเป้าหมายเป็นคลาส MyClassKt
ที่สร้างขึ้น
-keep class com.example.myapp.utils.MyClassKt {
public static boolean isEmailValid(java.lang.String);
}
ประเภท
ส่วนนี้จะอธิบายวิธีระบุประเภทการคืนค่า ประเภทพารามิเตอร์ และประเภทฟิลด์ในข้อกำหนดของสมาชิกกฎการเก็บรักษา อย่าลืมใช้ชื่อ Java ที่สร้างขึ้นเพื่อระบุ ประเภทหากแตกต่างจากซอร์สโค้ด Kotlin
ประเภทดั้งเดิม
หากต้องการระบุประเภทดั้งเดิม ให้ใช้คีย์เวิร์ด Java ของประเภทนั้น R8 จะรู้จักประเภทข้อมูลพื้นฐานต่อไปนี้
boolean
, byte
, short
, char
, int
, long
, float
,
double
ตัวอย่างกฎที่มีประเภทดั้งเดิมมีดังนี้
# Keeps a method that takes an int and a float as parameters.
-keepclassmembers class com.example.Calculator {
public void setValues(int, float);
}
ประเภททั่วไป
ในระหว่างการคอมไพล์ คอมไพลเลอร์ Kotlin/Java จะลบข้อมูลประเภททั่วไป ดังนั้นเมื่อเขียนกฎ keep ที่เกี่ยวข้องกับประเภททั่วไป คุณต้องกำหนดเป้าหมายเป็นการแสดงที่คอมไพล์แล้วของโค้ด ไม่ใช่ซอร์สโค้ดเดิม ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเปลี่ยนประเภททั่วไปได้ที่การลบประเภท
ตัวอย่างเช่น หากคุณมีโค้ดต่อไปนี้ที่มีประเภททั่วไปแบบไม่จำกัด
ซึ่งกำหนดไว้ใน Box.kt
package com.myapp.data
class Box<T>(val item: T) {
fun getItem(): T {
return item
}
}
หลังจากลบประเภทแล้ว T
จะถูกแทนที่ด้วย Object
หากต้องการเก็บตัวสร้างและเมธอดของคลาส
ไว้ กฎของคุณต้องใช้ java.lang.Object
แทนT
ทั่วไป
ตัวอย่างกฎการเก็บรักษาจะเป็นดังนี้
# Keep the constructor and methods of the Box class.
-keep class com.myapp.data.Box {
public init(java.lang.Object);
public java.lang.Object getItem();
}
หากคุณมีโค้ดต่อไปนี้ที่มีประเภททั่วไปที่จำกัดใน NumberBox.kt
package com.myapp.data
// T is constrained to be a subtype of Number
class NumberBox<T : Number>(val number: T)
ในกรณีนี้ การลบแบบพิมพ์จะแทนที่ T
ด้วยขอบเขตของ java.lang.Number
ตัวอย่างกฎการเก็บรักษาจะเป็นดังนี้
-keep class com.myapp.data.NumberBox {
public init(java.lang.Number);
}
เมื่อใช้ประเภททั่วไปเฉพาะแอปเป็นคลาสฐาน คุณจะต้อง รวมกฎการเก็บสำหรับคลาสฐานด้วย
เช่น สำหรับโค้ดต่อไปนี้
package com.myapp.data
data class UnpackOptions(val useHighPriority: Boolean)
// The generic Box class with UnpackOptions as the bounded type
class Box<T: UnpackOptions>(val item: T) {
}
คุณใช้กฎการเก็บรักษาด้วย includedescriptorclasses
เพื่อเก็บรักษาทั้งคลาส UnpackOptions
และเมธอดของคลาส Box
ด้วยกฎเดียวได้ดังนี้
-keep,includedescriptorclasses class com.myapp.data.Box {
public <init>(com.myapp.data.UnpackOptions);
}
หากต้องการเก็บฟังก์ชันที่เฉพาะเจาะจงซึ่งประมวลผลรายการออบเจ็กต์ คุณต้องเขียนกฎที่ตรงกับลายเซ็นของฟังก์ชันอย่างแม่นยำ โปรดทราบว่าเนื่องจากมีการลบประเภททั่วไป
พารามิเตอร์อย่าง List<Product>
จึงถือเป็น
java.util.List
ตัวอย่างเช่น หากคุณมีคลาสยูทิลิตีที่มีฟังก์ชันที่ประมวลผลรายการ
ของออบเจ็กต์ Product
ดังนี้
package com.myapp.utils
import com.myapp.data.Product
import android.util.Log
class DataProcessor {
// This is the function we want to keep
fun processProducts(products: List<Product>) {
Log.d("DataProcessor", "Processing ${products.size} products.")
// Business logic ...
}
}
// The data class used in the list (from the previous example)
package com.myapp.data
data class Product(val id: String, val name: String)
คุณสามารถใช้กฎการเก็บรักษาต่อไปนี้เพื่อปกป้องเฉพาะprocessProducts
ฟังก์ชันได้
-keep class com.myapp.utils.DataProcessor {
public void processProducts(java.util.List);
}
ประเภทอาร์เรย์
ระบุประเภทอาร์เรย์โดยต่อท้าย []
กับประเภทคอมโพเนนต์สำหรับแต่ละมิติข้อมูล
ของอาร์เรย์ ซึ่งมีผลกับทั้งประเภทคลาสและประเภทดั้งเดิม
- อาร์เรย์คลาสแบบมิติเดียว:
java.lang.String[]
- อาร์เรย์ดั้งเดิมแบบ 2 มิติ:
int[][]
ตัวอย่างเช่น หากคุณมีโค้ดต่อไปนี้
package com.example.data
class ImageProcessor {
fun process(): ByteArray {
// process image to return a byte array
}
}
คุณสามารถใช้กฎการเก็บรักษาต่อไปนี้
# Keeps a method that returns a byte array.
-keepclassmembers class com.example.data.ImageProcessor {
public byte[] process();
}
ไวลด์การ์ด
ตารางต่อไปนี้แสดงวิธีใช้อักขระไวด์การ์ดเพื่อใช้กฎการเก็บกับคลาสหรือสมาชิกหลายรายการที่ตรงกับรูปแบบหนึ่งๆ
สัญลักษณ์แทน | ใช้กับชั้นเรียนหรือสมาชิก | คำอธิบาย |
---|---|---|
** | ทั้งคู่ | ใช้บ่อยที่สุด ตรงกับชื่อประเภทใดก็ได้ รวมถึงตัวคั่นแพ็กเกจจำนวนเท่าใดก็ได้ ซึ่งจะมีประโยชน์ในการจับคู่คลาสทั้งหมดภายในแพ็กเกจและแพ็กเกจย่อย |
* | ทั้งคู่ | สำหรับข้อกำหนดของคลาส จะตรงกับส่วนใดก็ได้ของชื่อประเภทที่ไม่มีตัวคั่นแพ็กเกจ (. ) สำหรับข้อกำหนดของสมาชิก จะตรงกับชื่อเมธอดหรือฟิลด์ใดก็ได้ เมื่อใช้เพียงอย่างเดียว ก็จะเป็นชื่อแทนของ ** ด้วย |
? | ทั้งคู่ | จับคู่อักขระเดียวในชื่อคลาสหรือชื่อสมาชิก |
*** | สมาชิก | ตรงกับประเภทใดก็ได้ รวมถึงประเภทดั้งเดิม (เช่น int ) ประเภทคลาส (เช่น java.lang.String ) และประเภทอาร์เรย์ของมิติข้อมูลใดก็ได้ (เช่น byte[][] ) |
... | สมาชิก | จับคู่รายการพารามิเตอร์ใดก็ได้สำหรับเมธอด |
% | สมาชิก | ตรงกับประเภทดั้งเดิมใดก็ได้ (เช่น `int`, `float`, `boolean` หรืออื่นๆ) |
ตัวอย่างวิธีใช้ไวลด์การ์ดพิเศษมีดังนี้
หากคุณมีหลายวิธีที่มีชื่อเดียวกันซึ่งใช้ประเภทดั้งเดิมที่แตกต่างกันเป็นอินพุต คุณสามารถใช้
%
เพื่อเขียนกฎการเก็บที่จะเก็บทั้งหมดไว้ เช่น คลาสDataStore
นี้มีเมธอดsetValue
หลายรายการclass DataStore { fun setValue(key: String, value: Int) { ... } fun setValue(key: String, value: Boolean) { ... } fun setValue(key: String, value: Float) { ... } }
กฎการเก็บรักษาต่อไปนี้จะเก็บรักษาวิธีการทั้งหมด
-keep class com.example.DataStore { public void setValue(java.lang.String, %); }
หากคุณมีหลายชั้นเรียนที่มีชื่อต่างกันเพียง 1 อักขระ ให้ใช้
?
เพื่อเขียนกฎการเก็บที่เก็บชั้นเรียนทั้งหมดไว้ เช่น หากคุณมีคลาสต่อไปนี้com.example.models.UserV1 {...} com.example.models.UserV2 {...} com.example.models.UserV3 {...}
กฎการเก็บรักษาต่อไปนี้จะเก็บรักษาชั้นเรียนทั้งหมด
-keep class com.example.models.UserV?
หากต้องการจับคู่คลาส
Example
และAnotherExample
(หากเป็นคลาสระดับรูท) แต่ไม่จับคู่com.foo.Example
ให้ใช้กฎการเก็บรักษาต่อไปนี้-keep class *Example
หากคุณใช้ * เพียงอย่างเดียว ระบบจะถือว่าเครื่องหมายนี้เป็นชื่อแทนของ ** ตัวอย่างเช่น กฎการเก็บข้อมูลต่อไปนี้จะมีความหมายเหมือนกัน
-keepclasseswithmembers class * { public static void main(java.lang.String[];) } -keepclasseswithmembers class ** { public static void main(java.lang.String[];) }
ตรวจสอบชื่อ Java ที่สร้างขึ้น
เมื่อเขียนกฎการเก็บรักษา คุณต้องระบุคลาสและประเภทอ้างอิงอื่นๆ โดยใช้ชื่อหลังจากที่คอมไพล์เป็น Java bytecode แล้ว (ดูตัวอย่างได้ในข้อกำหนดของคลาสและประเภท) หากต้องการตรวจสอบชื่อ Java ที่สร้างขึ้นสำหรับโค้ด ให้ใช้เครื่องมือใดเครื่องมือหนึ่งต่อไปนี้ใน Android Studio
- ตัววิเคราะห์ APK
- เมื่อเปิดไฟล์ต้นฉบับ Kotlin แล้ว ให้ตรวจสอบไบต์โค้ดโดยไปที่เครื่องมือ > Kotlin > แสดงไบต์โค้ด Kotlin > แยก