title: Dagger 2 Save and Restore State when Activity Stops
body: <p>I'm at an impasse. I'm using Dagger 2 for dependency injection, but I'm losing state when the app goes into the background. Here is the scenario: the app starts up and creates the dependencies. All works perfectly as long as the app stays in the foreground. However, there is a scenario when the app has to go into the background. When it comes back, the values stored in one of my injected classes are lost. </p>
  
  <p>For my injected classes that have no dependencies of their own, everything seems to recover correctly. However, there is one injected class that has an injected dependency, and this is the one that doesn't recover. Here is how I am setting it up:</p>
  
  <p><strong>AppComponent.java</strong></p>
  
  <pre><code>@Singleton
  @Component(
      modules = {
          AppModule.class
      }
  )
  
  public interface AppComponent {
  
      SessionKeyExchangerService provideSessionKeyExchangerService();
      AESCipherService provideCipherService();
  
      void inject(LoginActivity loginActivity);
  }
  </code></pre>
  
  <p><strong>AppModule.java</strong></p>
  
  <pre><code>@Module
  public class AppModule {
  
      @Provides @Singleton
      AESCipherService provideCipherService() {
          return new AESCipherService();
      }
  
      @Provides @Singleton
      SessionKeyExchangerService provideSessionKeyExchangerService(AESCipherService service) {
          return new SessionKeyExchangerService(service);
      }
  }
  </code></pre>
  
  <p>And then when I go to inject these dependencies, I do it like this:</p>
  
  <p><strong>LoginActivity.java</strong></p>
  
  <pre><code>@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());
      }
  }
  </code></pre>
  
  <p>So, my fundamental question is how to maintain the state of a Dagger 2 injected class. I'm happy to share more code, but this is the essential idea.</p>
  
  <p>Thanks for any help.</p>
  
  <p><strong>EDIT</strong>
  Assuming that what I've done above is OK, let me move on to how I save and retrieve the values stored in those injected objects. This will show that there is a problem somewhere. </p>
  
  <p>When I go into the background, and then come back, I can see that I get a new PID. I can also see that I am able to store and retrieve the injected values correctly <em>in the LoginActivity class</em>. However, other classes that also have a reference to the injected value <em>now have different values</em> meaning that their reference is to a different memory location, right? </p>
  
  <p>My best guess as to where I am going wrong is in LoginActivity onCreate where I am restoring the <code>sessionKeyExchangerService</code> value from the saved parcel. I think I am creating new values that are not recognized across the app as injected dependencies, but I don't know why this is wrong or how to fix it.</p>
  
  <p>This code is also in LoginActivity.java:</p>
  
  <pre><code>@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());
  }
  </code></pre>
  
  <p>Here is the console output that illustrates the issue. Notice 1) how the PID changes after <code>onStop()</code> is called, and 2) how the class <code>Authenticator</code> (which has a reference to <code>AESCipherService</code> has a different session key value:</p>
  
  <blockquote>
    <p>1398-1398/com.mysite.myapp D/MYTAG﹕ on save instance state<br>
    1398-1398/com.mysite.myapp D/MYTAG﹕ session key saved:
    93Zuy8B3eos+eCfBQk9ErA==<br> 1398-1398/com.mysite.myapp D/MYTAG﹕ on
    stop<br> 3562-3562/com.mysite.myapp D/MYTAG﹕ session key retrieved in
    on create: 93Zuy8B3eos+eCfBQk9ErA==<br> 3562-3562/com.mysite.myapp
    D/MYTAG﹕ on start<br> 3562-3562/com.mysite.myapp D/MYTAG﹕ session key
    retrieved in on restore state: 93Zuy8B3eos+eCfBQk9ErA==<br>
    3562-3562/com.mysite.myapp D/MYTAG﹕ authenticator class says that the
    session key is: 28HwdRCjBqH3uFweEAGCdg==<br></p>
  </blockquote>
  
  <p><strong>SessionKeyExchangerService.java</strong></p>
  
  <pre><code>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&lt;SessionKeyExchangerService&gt; CREATOR = new Creator&lt;SessionKeyExchangerService&gt;() {
          @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);
      }
  </code></pre>
  
  <p><strong>AESCipherService.java</strong></p>
  
  <pre><code>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&lt;AESCipherService&gt; CREATOR = new Creator&lt;AESCipherService&gt;() {
      @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 ));
  }
  </code></pre>