Best Practices befolgen

Bei der Arbeit mit Aufbewahrungsregeln ist es wichtig, den richtigen Grad an Spezifität zu erreichen, damit Sie Vorteile sehen und gleichzeitig das Verhalten Ihrer App beibehalten. In den folgenden Abschnitten finden Sie Informationen zu guten Mustern und dazu, was Sie in Aufbewahrungsregeln vermeiden sollten.

Gute Muster in Aufbewahrungsregeln

Gut definierte Aufbewahrungsregeln sind so spezifisch wie möglich und folgen den folgenden Mustern:

  • Geben Sie für die Klassenspezifikation nach Möglichkeit immer eine bestimmte Klasse, Basisklasse oder annotierte Klasse an, wie in den folgenden Beispielen gezeigt:

    -keepclassmembers class com.example.MyClass {
      void someSpecificMethod();
    }
    
    -keepclassmembers ** extends com.example.MyBaseClass {
      void someSpecificMethod();
    }
    
    -keepclassmembers @com.example.MyAnnotation class ** {
      void someSpecificMethod();
    }
    
  • Verwenden Sie nach Möglichkeit Anmerkungen in Ihrem Quellcode und richten Sie Ihre Keep-Regeln dann direkt auf diese Anmerkungen aus. So wird eine klare, explizite Verbindung zwischen Ihrem Code und den Regeln hergestellt, die ihn schützen. Das macht Ihre Konfiguration robuster, leichter verständlich und weniger anfällig für Fehler, wenn sich der Code ändert.

    Das folgende Snippet zeigt beispielsweise, wie Sie die Klasse „MyClass“ sowie andere Klassen, die mit @com.example.DisplayComponent annotiert sind, beibehalten können:

    // In the source code
    @com.example.DisplayComponent
    class MyClass { /* ... */ }
    
    // In the keep rules
    -keep @com.example.DisplayComponent class * {*;}
    

    Wir empfehlen, Ihre Anmerkungen so zu benennen, dass sie einen aussagekräftigen Kontext dafür liefern, warum Codeabschnitte beibehalten werden. Verwenden Sie beispielsweise @DisplayComponent für eine App, bei der für die Anzeige von Komponenten einige Teile beibehalten werden müssen.

  • Die Mitgliedsspezifikation sollte nach Möglichkeit deklariert werden und nur auf die Teile der Klasse verweisen, die für die Funktion der App beibehalten werden müssen. Es wird empfohlen, eine Regel nicht auf eine ganze Klasse anzuwenden, indem Sie den optionalen Mitgliedsbereich als { *; } definieren, es sei denn, dies ist unbedingt erforderlich.

    -keepclassmembers com.example.MyClass {
      void someSpecificMethod();
      void @com.example.MyAnnotation *;
    }
    
  • Wenn Sie die globale Option repackageclasses verwenden, sollten Sie den optionalen Paketnamen nicht angeben. Dadurch werden kleinere DEX-Dateien erstellt, da das Paketpräfix in den neu verpackten Klassennamen weggelassen wird.

  • Behalten Sie Regeln für alle Elemente bei, auf die über Reflection zugegriffen wird. Auch wenn solche Elemente von R8 ohne explizite Keep-Regeln beibehalten werden, ist es wichtig, die tatsächlichen Regeln beizubehalten, da zukünftige Codeänderungen dazu führen könnten, dass R8 diese Elemente nicht mehr beibehält.

Wenn Sie diese Richtlinien nicht einhalten können, können Sie den Code, der beibehalten werden muss, vorübergehend in einem dedizierten Paket isolieren und Ihre Keep-Regel auf das Paket anwenden. Dies ist jedoch keine langfristige Lösung. Weitere Informationen finden Sie unter Optimierungen schrittweise einführen. Wenn Sie eine Keep-Regel für ein Paket verwenden möchten, definieren Sie eine Keep-Regel wie im folgenden Beispiel:

-keepclassmembers class com.example.pkg.** { *; }

Was du vermeiden solltest

Die Syntax für Aufbewahrungsregeln bietet viele Optionen. Für messbare nachhaltige Leistungssteigerungen empfehlen wir jedoch, Folgendes nicht zu verwenden:

  • Verwenden Sie keine paketweiten Keep-Regeln wie -keep class com.example.pkg.** { *; } langfristig. Sie können vorübergehend verwendet werden, um Probleme bei der Konfiguration von R8 zu umgehen. Weitere Informationen finden Sie unter Optimierungsbereich einschränken. Seien Sie generell vorsichtig mit Platzhaltern und achten Sie darauf, dass Sie nur den Code beibehalten, den Sie wirklich benötigen.
  • Vermeiden Sie nach Möglichkeit Bibliotheken, bei denen Sie Keep-Regeln kopieren und einfügen müssen, insbesondere paketweite Keep-Regeln. Bibliotheken, die für eine gute Leistung auf Android entwickelt wurden, sollten nach Möglichkeit keine Reflexion verwenden und bei Bedarf Keep-Regeln für Verbraucher einbetten.
  • Vermeiden Sie die Verwendung des Inversionsoperators ! in Keep-Regeln, da Sie eine Regel sonst möglicherweise versehentlich auf fast jede Klasse in Ihrer Anwendung anwenden.

Wenn Sie diese Regeln nicht einhalten können, verwenden Sie möglicherweise viel offene Reflexion. In diesem Fall sollten Sie die Reflexion oder die Bibliothek, die Reflexion verwendet, vermeiden (siehe die Gson-Fallstudie).