Sono in un vicolo cieco. Sto usando Dagger 2 per l'iniezione delle dipendenze, ma sto perdendo lo stato quando l'app entra in background. Ecco lo scenario: l'app si avvia e crea le dipendenze. Tutto funziona perfettamente finché l'app rimane in primo piano. Tuttavia, esiste uno scenario in cui l'app deve andare in secondo piano. Quando ritorna, i valori memorizzati in una delle mie classi iniettate vanno persi.Dagger 2 Salva e ripristina stato quando l'attività si arresta
Per le mie classi iniettate che non hanno dipendenze proprie, tutto sembra ripristinarsi correttamente. Tuttavia, esiste una classe iniettata con una dipendenza iniettata, e questa è quella che non si ripristina. Ecco come sto sua creazione:
AppComponent.java
@Singleton
@Component(
modules = {
AppModule.class
}
)
public interface AppComponent {
SessionKeyExchangerService provideSessionKeyExchangerService();
AESCipherService provideCipherService();
void inject(LoginActivity loginActivity);
}
AppModule.java
@Module
public class AppModule {
@Provides @Singleton
AESCipherService provideCipherService() {
return new AESCipherService();
}
@Provides @Singleton
SessionKeyExchangerService provideSessionKeyExchangerService(AESCipherService service) {
return new SessionKeyExchangerService(service);
}
}
E poi, quando vado per iniettare queste dipendenze, lo faccio In questo modo:
LoginActivity.java
@Inject
SessionKeyExchangerService sessionKeyExchangerService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Injector.INSTANCE.getAppComponent().inject(this);
if (savedInstanceState != null) {
sessionKeyExchangerService = savedInstanceState.getParcelable(SESSION_KEY_PARCEL);
Log.d(Constants.TAG, "session key retrieved in on create: " + sessionKeyExchangerService.getCipherService().getBase64EncodedSessionKey());
}
}
Quindi, la mia domanda fondamentale è come mantenere lo stato di una classe iniettato Dagger 2. Sono felice di condividere più codice, ma questa è l'idea essenziale.
Grazie per qualsiasi aiuto.
EDIT Partendo dal presupposto che quello che ho fatto in precedenza è ok, mi permetta di andare avanti a come mi salvare e recuperare i valori memorizzati in quegli oggetti iniettati. Questo mostrerà che c'è un problema da qualche parte.
Quando vado in background, e poi torno, posso vedere che ottengo un nuovo PID. Posso anche vedere che sono in grado di memorizzare e recuperare correttamente i valori iniettati nella classe LoginActivity. Tuttavia, altre classi che hanno anche un riferimento al valore iniettato hanno ora valori diversi, il che significa che il loro riferimento è a una diversa posizione di memoria, giusto?
La mia ipotesi migliore su dove sto andando storto è in LoginActivity onCreate dove sto ripristinando il valore sessionKeyExchangerService
dal pacchetto salvato. Penso di creare nuovi valori che non sono riconosciuti dall'app come dipendenze iniettate, ma non so perché questo sia sbagliato o come risolverlo.
Questo codice è anche in LoginActivity.java:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(SESSION_KEY_PARCEL, sessionKeyExchangerService);
Log.d(Constants.TAG, "session key saved: " + sessionKeyExchangerService.getCipherService().getBase64EncodedSessionKey());
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
sessionKeyExchangerService = savedInstanceState.getParcelable(SESSION_KEY_PARCEL);
Log.d(Constants.TAG, "session key retrieved in on restore state: " + sessionKeyExchangerService.getCipherService().getBase64EncodedSessionKey());
}
Ecco l'output della console che illustra il problema. Avviso 1) come cambia il PID dopo onStop()
si chiama, e 2) come la classe Authenticator
(che ha un riferimento a AESCipherService
ha una sessione diverso valore chiave:
1398-1398/com.mysite.myapp D/MYTAG: on salva istanza
1398-1398/com.mysite.myapp D/MYTAG: chiave di sessione salvata: 93Zuy8B3eos + eCfBQk9ErA ==
1398-1398/com.mysite.myapp D/MyTag: il arresto
3562-3562/com.mysite.myapp D/MyTag: chiave di sessione recuperata in su Crea: 93Zuy8B3eos + eCfBQk9ErA ==
3562-3562/com.mysite.myapp D/MyTag: all'avvio
3562-3562/com.mysite.myapp D/MYTAG: chiave di sessione recuperata in stato di ripristino: 93Zuy8B3eos + eCfBQk9ErA ==
3562-3562/com.mysite.myapp D/MYTAG: la classe di autenticatore dice che il chiave di sessione è: 28HwdRCjBqH3uFweEAGCdg ==
SessionKeyExchangerService.java
protected SessionKeyExchangerService(Parcel in) {
notifyOn = in.readString();
sessionKeyExchangeAttempts = in.readInt();
MAX_SESSION_KEY_EXCHANGE_ATTEMPTS = in.readInt();
sessionKeyExchangeHasFailed = (in.readByte() == 1);
cipherService = in.readParcelable(AESCipherService.class.getClassLoader());
}
public static final Creator<SessionKeyExchangerService> CREATOR = new Creator<SessionKeyExchangerService>() {
@Override
public SessionKeyExchangerService createFromParcel(Parcel in) {
return new SessionKeyExchangerService(in);
}
@Override
public SessionKeyExchangerService[] newArray(int size) {
return new SessionKeyExchangerService[size];
}
};
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(notifyOn);
dest.writeInt(sessionKeyExchangeAttempts);
dest.writeInt(MAX_SESSION_KEY_EXCHANGE_ATTEMPTS);
dest.writeByte((byte) (hasSessionKeyExchangeFailed() ? 1 : 0));
dest.writeParcelable(cipherService, flags);
}
AESCipherService.java
protected AESCipherService(Parcel in) {
sessionKeyBytes = in.createByteArray();
ivBytes = in.createByteArray();
sessionId = in.readLong();
mIsSessionKeyEstablished = (in.readByte() == 1);
verbose = (in.readByte() == 1);
}
public static final Creator<AESCipherService> CREATOR = new Creator<AESCipherService>() {
@Override
public AESCipherService createFromParcel(Parcel in) {
return new AESCipherService(in);
}
@Override
public AESCipherService[] newArray(int size) {
return new AESCipherService[size];
}
};
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByteArray(sessionKeyBytes);
dest.writeByteArray(ivBytes);
dest.writeLong(sessionId);
dest.writeByte((byte) (isSessionKeyEstablished() ? 1 : 0));
dest.writeByte((byte) (verbose ? 1 : 0));
}
È possibile fornire il codice in cui si inietta l'attività e anche dove si sta costruendo il grafico? – Ognyan
Sto finalmente tornando a questa domanda. Ho riscritto la domanda per concentrarmi sul modo in cui ho impostato l'iniezione della dipendenza piuttosto che sui parcelables. Sono abbastanza fiducioso che sto facendo questa parte correttamente, quindi l'errore deve essere nella parte di Dagger 2. – Alex
Credo che avresti bisogno di serializzare lo stato di ciò che fornisci nel tuo modulo attraverso 'onSaveInstanceState()' e reinserirlo in 'onRestoreInstanceState()', considerando che la morte del processo uccide l'intero processo di applicazione e solo i bundle sopravvivono. Probabilmente dovresti costruire il tuo componente in 'onRestoreInstanceState()' se non esiste, e reinserirlo una volta istanziando le tue dipendenze attraverso i metodi di provisioning del componente. – EpicPandaForce