1

I'm trying to use parcelable to maintain state when rotating my device.

val VehiclesParcelable = VehiclesModel()

override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
    super.onSaveInstanceState(outState, outPersistentState)
    outState.putParcelable(KEY, VehiclesParcelable)
}

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
    if(savedInstanceState != null) {
        savedInstanceState.getParcelable<VehiclesModel>(KEY)
    }
}

I can't figure out how to use the getParcelable, it says it's deprecated, if I try to use the newer version (that says I need to include the class?) getParcelable(KEY, VehiclesModel) I get "type mismatch".

I'm pretty sure I'm putting in the second argument incorrectly.

How do I use the new version? All I find about it just use it like I did in the code above.

Zain
  • 37,492
  • 7
  • 60
  • 84
Coder
  • 340
  • 1
  • 9

1 Answers1

1

I can't figure out how to use the getParcelable, it says it's deprecated

As of API level 33, the one-argument getParcelable (String key) is deprecated. Starting from API level 33, you need to include the class as a second argument using the two-argument version getParcelable (String key, Class<T> clazz)

In Kotlin, the KClass formula is used to represent a class, but to get a Java Class instance corresponding to a given KClass instance, extend that with ".java" suffix (documentation reference). This would be in your model "VehiclesModel::class.java".

So, to fix the deprecation after API level 33:

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) // API 33
        @Suppress("DEPRECATION")
        savedInstanceState.getParcelable<VehiclesModel>(KEY)
    else
        savedInstanceState.getParcelable(KEY, VehiclesModel::class.java)
}

Side notes:

  • The condition if(savedInstanceState != null) has been removed because the savedInstanceState argument is not nullable.
  • The VehiclesModel model class is typically a data class, and that expects a constructor with one argument at least, check here. So, you need to fix that in val VehiclesParcelable = VehiclesModel() statement.
  • ViewModel would be a typical tool instead of onSaveInstaceState() if you just want to survive configuration changes.

Update for the bountied part

how would you solve the bountied part? I'm using Java so I'm using if (savedInstanceState != null) instead of a method onRestoreInstanceState.

Even if you're using Java, the the savedInstanceState is annotated with @NonNull; so it shouldn't be null; instead you'd worry if the getParcelable() returned null in case the key was wrong.

The code in java, you'd use Bitmap.class instead of the OP VehiclesModel:

String KEY = "stateOfImageView";

@Override
protected void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
    super.onSaveInstanceState(savedInstanceState);
    BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
    Bitmap bitmap = drawable.getBitmap();
    savedInstanceState.putParcelable(KEY, bitmap);
}

@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);

    Bitmap bitmap;
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) // API 33
        bitmap = savedInstanceState.getParcelable(KEY);
    else
        bitmap = savedInstanceState.getParcelable(KEY, Bitmap.class);
    ...
}
Zain
  • 37,492
  • 7
  • 60
  • 84
  • @Thank you for the answer, And how would you solve the bountied part? I'm using Java so I'm using `if (savedInstanceState != null)` instead of a method `onRestoreInstanceState`. – xralf Jul 13 '23 at 05:21
  • @xralf Please check the updated answer, hopefully it helps – Zain Jul 13 '23 at 14:44
  • I have the same warning now. Should I add somewhere @Suppress("DEPRECATION")? – xralf Jul 13 '23 at 19:36
  • You could do that if you wish, in java it's `@SuppressWarnings("deprecation")` but unlike Kotlin, it's not supported to put it anywhere ; you'd do that just before the method declaration; but be sure that it will suppress any single deprecation, so don't do that on a wide range of code... The warning is just because sometimes Android studio couldn't be enough intelligent that you add it within the non deprecated APIs (i.e., before API level 33) – Zain Jul 13 '23 at 20:18