Eine Alpha-Version von Hilt wurde veröffentlicht, also habe ich sie untersucht. Dieser verwirrende Dolch 2 war sehr leicht zu verstehen. Ich denke, die Einführungsschwelle wurde gesenkt. Daher möchte ich die Grundlagen beim Erstellen einer Beispiel-App für diejenigen erläutern, die "DI, Hilt verwenden und die Grundlagen kennenlernen" möchten. Außerdem wird die Migrationsmethode von Dagger2 nach Hilt nicht beschrieben.
Die Erklärung wie die Gliederung wird weggelassen und plötzlich implementiert. Informationen zu DI und Hilt finden Sie auf der offiziellen Seite. Das diesmal erstellte Beispiel ist eine Anwendung, die die Datenbank durchsucht und die Ergebnisse anzeigt, wenn Sie die Taste auf dem Bildschirm drücken.
Die Struktur der zu erstellenden Klasse ist wie folgt. MainActivity --> SampleUseCase --> SampleRepository --> SampleDao --> DB
Implementieren Sie diese App mit Hilt
.
Ich benutze "Raum" in der Datenbank, aber ich erwähne "Raum" nicht.
Die Umgebung ist wie folgt.
Setzen Sie zuerst die Wurzel build.gradle
.
buildscript {
dependencies {
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
//···(Kürzung)・ ・ ・
}
}
Als nächstes folgt die Einstellung von app / build.gradle
.
apply plugin: 'dagger.hilt.android.plugin'
android {
//・ ・ ・(Kürzung)・ ・ ・
}
dependencies {
implementation "com.google.dagger:hilt-android:2.28-alpha"
annotationProcessor "com.google.dagger:hilt-android-compiler:2.28-alpha"
//・ ・ ・(Kürzung)・ ・ ・
}
Erstellen Sie als Nächstes die Anwendungsklasse.
Fügen Sie einfach @ HiltAndroidApp
zur Anwendungsklasse hinzu. Bisher hat es "DaggerApplication" geerbt oder "HasAndroidInjector" implementiert, aber in Hilt ist es in Ordnung, nur eine Anmerkung hinzuzufügen.
Fügen Sie die Anwendungsklasse nach dem Erstellen zu AndroidManifest.xml hinzu.
@HiltAndroidApp
public class SampleApplication extends Application {
}
AndroidManifest.xml
<application
android:name=".SampleApplication"
android:icon="@mipmap/ic_launcher">
···(Kürzung)···
</application>
Früher habe ich AppComponent erstellt, aber Hilt benötigt es nicht mehr. Wenn Sie von Dagger2 migrieren, löschen Sie es.
// @Singleton
// @Component(modules={AndroidInjectionModule.class})
// public interface AppComponent extends AndroidInjector<SampleApplication> {
//···(Kürzung)・ ・ ・
// }
Sie können injizieren, indem Sie die Aktivität mit "@ AndroidEntryPoint" kommentieren. Bisher wurden Impl von "HasAndroidInjector" und "AndroidInjection.inject (this)" ausgeführt, aber in Hilt wird es nur mit Anmerkungen versehen.
In diesem Beispiel werden wir SampleUseCase in MainActiviyt injizieren.
MainActivity.java
@AndroidEntryPoint //・ ・ ・(1)
public class MainActivity extends AppCompatActivity {
@Inject //・ ・ ・(2)
SampleUseCase useCase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.execute);
button.setOnClickListener(v -> useCase.execute()); //・ ・ ・(3)
}
}
(1) Fügen Sie die Anmerkung "AndroidEntryPoint" hinzu.
(2) Fügen Sie die Anmerkung "Injizieren" hinzu. Hilt fügt eine Instanz in diese useCase
-Variable ein.
(3) Führen Sie useCase
aus, wenn die Taste gedrückt wird. Im Code kann SampleUseCase ausgeführt werden, obwohl es nicht neu ist. Dies liegt daran, dass Hilt die Instanz erstellt und injiziert hat.
Als nächstes kommt der SampleUseCase. Erstens besteht die Implementierung nur darin, das Protokoll auszugeben.
SampleUseCase.java
public class SampleUseCase {
private static String TAG = SampleUseCase.class.getName();
@Inject //・ ・ ・(1)
public SampleUseCase() {
}
public void execute() {
Log.d(TAG, "Lauf!!");
}
}
(1) Fügen Sie dem Konstruktor die Annotation "Inject" hinzu. Ohne sie ist es kein von Hilt verwaltetes Objekt und wird nicht in die Aktivität eingefügt.
Es funktioniert tatsächlich bis zu diesem Punkt. DI ist bereit. Es ist sehr leicht. Es ist überwältigend einfacher als mit Dagger2.
Im obigen Beispiel wird in der zu injizierenden Klasse (SampleUseCase) "@ Inject" im Konstruktor angegeben. Es ist jedoch möglicherweise nicht möglich, "@ Inject" zu gewähren. Zum Beispiel für Schnittstellen oder Klassen in externen Bibliotheken. Erstellen Sie in diesem Fall eine Klasse mit der Annotation "@ Module" und teilen Sie Hilt mit, wie die Instanz erstellt wird.
In diesem Beispiel entspricht dies dem Aufruf der Schnittstelle "SampleRepository" von SampleUseCase. Fügen Sie der SampleUseCase-Klasse eine Implementierung hinzu.
SampleUseCase.java
public class SampleUseCase {
private static String TAG = SampleUseCase.class.getName();
@Inject
SampleRepository repository; //Schnittstelle
@Inject
public SampleUseCase() {
}
public void execute() {
Log.d(TAG, "Lauf!!");
//Ich werde das machen
List<SampleEntity> results = repository.find();
//Ergebnisse im Protokoll anzeigen
results.forEach(result -> {
Log.d(TAG, result.getName());
});
}
Binds
Eine Implementierung von SampleRepository
. Die Schnittstelle und die Entitätsklasse lauten wie folgt.
SampleRepository.java
public interface SampleRepository {
List<SampleEntity> find();
}
SampleRepositoryImpl.java
public class SampleRepositoryImpl implements SampleRepository {
public static final String TAG = SampleRepositoryImpl.class.getName();
@Inject //・ ・ ・(1)
public SampleRepositoryImpl() {
}
public List<SampleEntity> find() {
Log.d(TAG, "find!");
return null;
}
}
(1) Fügen Sie dem Konstruktor der Entitätsklasse "@ Inject" hinzu.
Dies allein kann nicht injiziert werden. Ich muss Hilt beibringen, wie man diese Schnittstelle instanziiert.
Das Hilt-Modul ist eine Klasse, die mit "@ Module" versehen ist. Im Gegensatz zu Daggers Modulen verwendet Hilt die Annotation "@ InstallIn", um Abhängigkeiten anzugeben.
DataModule.java
@Module //・ ・ ・ (1)
@InstallIn(ApplicationComponent.class) //・ ・ ・(2)
abstract public class DataModule {
@Binds //・ ・ ・(3)
public abstract SampleRepository bindSampleRepository(SampleRepositoryImpl impl);
}
(1) Fügen Sie die Annotation "@ Module" hinzu und erklären Sie, dass es sich um eine Hilt-Modulklasse handelt. Der Klassenname kann beliebig sein. (2) Geben Sie die Abhängigkeit dieses Moduls an. In diesem Beispiel können die hier deklarierten Klassen in jede Klasse in der App eingefügt werden. Diese Spezifikation kann auf verschiedene Arten angegeben werden, wie in der folgenden Tabelle gezeigt. Wenn Sie beispielsweise FragmentComponent angeben, können Sie in Fragment, jedoch nicht in Activity injizieren. Geben Sie dieses Mal ApplicationComponent an, damit es in eine beliebige Klasse der App eingefügt werden kann.
Komponente | |
---|---|
ApplicationComponent | Application |
ActivityRetainedComponent | ViewModel |
ActivityComponent | Activity |
FragmentComponent | Fragment |
ViewComponent | View |
ViewWithFragmentComponent | |
ServiceComponent | Service |
Ansicht (3) mit der Annotation WithFragmentBindings Fügen Sie die Annotation Binds
hinzu und deklarieren Sie, welche Entität generiert werden soll. Der Rückgabewert der Methode gibt die Schnittstelle an. Geben Sie in den Methodenparametern die Entität an, die Sie generieren möchten. Zusätzlich zu Binds, bei dem Instanzen mithilfe von "Provides" eingefügt werden, können Sie angeben, wie Instanzen erstellt werden sollen. Externe Bibliotheken können Konstruktoren keine Injektionen geben. Verwenden Sie in diesem Fall "Provides". In diesem Beispiel ruft SampleRepositoryImpl hier Dao auf.
Es ist eine Implementierung, wenn DI sich auf Room bezieht. (Ich werde nicht über Raum erklären. Ich werde es in einem anderen Artikel tun)
Fügen Sie es im obigen Beispielcode zu "DataMudule.java" hinzu.
DataModule.java
@Module
@InstallIn(ApplicationComponent.class)
abstract public class DataModule {
@Provides //・ ・ ・(1)
@Singleton //・ ・ ・(2)
public static SampleDatabase provideDb(Application context) {
return Room.databaseBuilder(context.getApplicationContext(), SampleDatabase.class, "sample.db")
.addCallback(SampleDatabase.INITIAL_DATA)
.allowMainThreadQueries()
.build();
}
@Provides //・ ・ ・(3)
@Singleton
public static SampleDao provideSampleDao(SampleDatabase db) {
return db.getSampleDao();
}
@Binds
public abstract SampleRepository bindSampleRepository(SampleRepositoryImpl impl);
}
(1) Fügen Sie die Annotation "Provides" hinzu und deklarieren Sie, welche Entität generiert werden soll. Der Rückgabewert der Methode ist die erstellte Instanz. Der Parameter kann an eine von Hilt verwaltete Instanz übergeben werden. (2) Diese Methode hat eine Singleton-Annotation. Dies ist die Bereichseinstellung. Normalerweise erstellt Hilt jedes Mal eine neue Instanz, wenn eine Anforderung vorliegt. Dies kann durch Kommentieren gesteuert werden. Da dieses Beispiel "Singleton" ist, wird der Status einer Instanz in der Anwendung realisiert. (Ich erstelle nicht jedes Mal eine neue Instanz). Das Injizieren einer Klasse führt zur gleichen Instanz.
Die folgenden Bereiche sind verfügbar.
Android-Klasse | Generierte Komponente | Umfang |
---|---|---|
Application | ApplicationComponent | Singleton |
View Model | ActivityRetainedComponent | ActivityRetainedScope |
Activity | ActivityComponent | ActivityScoped |
Fragment | FragmentComponent | FragmentScoped |
View | ViewComponent | ViewScoped |
WithFragmentBindings | ViewWithFragmentComponent | ViewScoped |
Service | ServiceComponent | ServiceScoped |
Wenn Sie beispielsweise den InstantRun von "DataModule.java" in diesem Beispiel in "ActivityComponent" und SampleDao in "ActivityScoped" ändern, ist dies dieselbe Instanz für die Dauer der Aktivität. Wenn Sie Dao in SampleActivity, SampleUseCase und SampleRespository einfügen, sind alle Dao dieselbe Instanz.
Kehren Sie zur Beispiel-App-Implementierung zurück. Injizieren Sie Dao in SampleRepositoryImpl, um die Implementierung abzuschließen.
SampleRepositoryImpl.java
public class SampleRepositoryImpl implements SampleRepository {
public static final String TAG = SampleRepositoryImpl.class.getName();
@Inject //・ ・ ・(1)
SampleDao dao;
@Inject
public SampleRepositoryImpl() {
}
public List<SampleEntity> find() {
Log.d(TAG, "find!");
return dao.find(); //・ ・ ・(2)
}
}
(1) Inject Sample Dao. Da der Gültigkeitsbereich "Singleton" ist, wird jedes Mal dieselbe Instanz injiziert. (2) Obwohl es nicht neu ist, verursacht es keine NullPointerException, da es von Hilt injiziert wird.
Hier sind Dao und Entity der Beispiel-Apps, die oben nicht erläutert wurden.
SampleEntity.java
@Entity(tableName = "sample")
public class SampleEntity implements Serializable {
@PrimaryKey
@NonNull
private String code;
private String name;
//setter/Getter weggelassen
}
SampleDao.java
@Dao
public interface SampleDao {
@Insert
long save(SampleEntity dto);
@Query("select * from sample")
List<SampleEntity> find();
}
Wenn Sie zu diesem Zeitpunkt die Taste auf dem Bildschirm drücken, werden die Suchergebnisse im Protokoll angezeigt. Dagger2 wird fast nicht benötigt und ist einfacher. Es ist sehr leicht.
Ich werde die Punkte von Hilt durch dieses Beispiel organisieren.
Recommended Posts