Versuchen Sie, Android Hilt in Java zu implementieren

Einführung

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.

Plötzlich implementiert

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.

Bibliothek hinzufügen

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 einer Anwendungsklasse

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)・ ・ ・
// }

In Aktivität injizieren

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.

Erstellen eines Hilt-Moduls

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());
        });
    }

Injizieren Sie Instanzen mit 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.

Anderer Code

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();
}

Komplett! !!

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.

Zusammenfassung

Ich werde die Punkte von Hilt durch dieses Beispiel organisieren.

  1. Geben Sie die Aktivität "@ AndroidEntryPoint" ein
  2. Vergessen Sie nicht, dem Konstruktor der zu injizierenden Klasse "@ Inject" hinzuzufügen.
  3. Verwenden Sie "@ Binds" oder "@ Provides", wenn Sie Schnittstellen und andere Bibliotheken einfügen das ist alles. Es ist einfach. Beim nächsten Mal möchte ich Hilt und ViewModel verwenden, um die Suchergebnisse auf dem Bildschirm anzuzeigen. wir sehen uns!

Referenz

Recommended Posts

Versuchen Sie, Android Hilt in Java zu implementieren
Es ist spät! Versuchen Sie, Android Notification in Java (Anfänger) zu implementieren.
Es ist spät! Versuchen Sie, Android Work Manager in Java zu implementieren (Anfänger)
Versuchen Sie es mit RocksDB mit Java
Versuchen Sie, JavaScript in Java aufzurufen
Lassen Sie uns Spresense mit Java entwickeln (1)
Probieren Sie den Funktionstyp in Java aus! ①
Versuchen Sie, die asynchrone Verarbeitung in Azure zu implementieren
Lassen Sie uns die Signaturüberprüfung des Codes für elliptische Kurven in Java implementieren
Versuchen Sie, Selenuim 3.141.59 mit Eclipse (Java) auszuführen.
Versuchen Sie einen If-Ausdruck in Java
Versuchen Sie, AWS X-Ray in Java auszuführen
Versuchen Sie, Yuma in Java zu implementieren
Java: Versuchen Sie, einen durch Kommas getrennten Formatierer selbst zu implementieren
Versuchen Sie, Project Euler in Java zu lösen
Versuchen Sie, n-ary Addition in Java zu implementieren
Versuchen Sie es mit der Stream-API in Java
Versuchen Sie es mit der JSON-Format-API in Java
Versuchen Sie, den CORBA-Dienst unter Java 11+ aufzurufen
Lassen Sie uns eine Taschenrechner-App mit Java erstellen
Von Java nach C und von C nach Java in Android Studio
Partisierung in Java
Probieren Sie Java 8 Stream aus
Änderungen in Java 11
Janken in Java
Umfangsrate in Java
Versuchen Sie es mit Java 9
FizzBuzz in Java
Versuchen Sie, Firebase Cloud-Funktionen unter Android (Java) zu verwenden.
[AWS IoT] Implementieren der Autorisierung von Direktaufrufen in Java [Java]
Versuchen Sie, etwa 30 Zeilen in Java zu kratzen (CSV-Ausgabe)
[Android / Java] Betreiben Sie eine lokale Datenbank in Room
Versuchen Sie, ein Bulletin Board in Java zu erstellen
Zweite Abkochung: Versuchen Sie einen If-Ausdruck in Java
Versuchen Sie es mit Sourcetrail (Win-Version) mit Java-Code
Versuchen Sie, die Cloud Vision-API von GCP in Java zu verwenden
Versuchen Sie es mit Sourcetrail (MacOS-Version) mit Java-Code
Versuchen Sie die Kommunikation mit gRPC auf einem Android + Java-Server
Schwierigkeiten bei der Implementierung von Alarm Manager in Android Studio
Versuchen Sie es mit der Syntaxanalyse der COTOHA-API in Java
Repräsentiert "nächster Tag" und "vorheriger Tag" in Java / Android
Lesen Sie JSON in Java
Interpreter-Implementierung durch Java
Machen Sie einen Blackjack mit Java
[Android / Java] Bildschirmübergang und Rückgabeverarbeitung in Fragmenten
Versuchen Sie, synchronisierte Methoden aus mehreren Threads in Java aufzurufen
Janken App in Java
Einschränkungsprogrammierung in Java
Setzen Sie Java8 in Centos7
NVL-artiger Typ in Java
Verbinden Sie Arrays in Java
"Hallo Welt" in Java
Aufrufbare Schnittstelle in Java
Versuchen Sie, das Eratostenes-Sieb mithilfe der Java-Standardbibliothek zu implementieren
Kommentare in der Java-Quelle
Azure funktioniert in Java
Versuchen Sie LetCode in Ruby-TwoSum
Formatieren Sie XML in Java
Einfache HTML-Spezialchars in Java