0

If one prints a Fragment:

println("fragment: ${Fragment()}")

it prints out:

Fragment{8d157db} (d63150f2-7497-4c04-9214-d20c3ccaba34)

Looking at the implementation of the toString(), I can see:

public String toString() {
    StringBuilder sb = new StringBuilder(128);
    Class<?> cls = getClass();
    sb.append(cls.getSimpleName());
    sb.append("{");
    sb.append(Integer.toHexString(System.identityHashCode(this)));
    sb.append("}");
    sb.append(" (");
    sb.append(mWho);
    if (mFragmentId != 0) {
        sb.append(" id=0x");
        sb.append(Integer.toHexString(mFragmentId));
    }
    if (mTag != null) {
        sb.append(" tag=");
        sb.append(mTag);
    }
    sb.append(")");
    return sb.toString();
}

So the UUID it's printing is from mWho variable which gets generated using:

// Internal unique name for this fragment;
@NonNull
String mWho = UUID.randomUUID().toString();

Is there a way to get this value for use as the tag when using supportFragmentManager.findFragmentByTag? Getting it without parsing the toString string.

I am asking this because right now I have my own custom uniqueUUID which I use for restoring a fragment using retainInstance. If I can get the mWho, I won't need my own custom code for the uniqueUUID.

  • Be careful as `mWho` can be mutated with configuration changes – Zain Jul 10 '21 at 03:16
  • @Zain When I use `retainInstance` for the fragment, then it doesn't change as far as I can tell. – sudoExclaimationExclaimation Jul 10 '21 at 03:22
  • 1
    It doesn't make sense to use an instance-specific identifier for a tag. Don't get too cozy with `setRetainInstance()`: https://android-review.googlesource.com/c/platform/frameworks/support/+/1159084 – Tenfour04 Jul 10 '21 at 03:29
  • What does "which I use for restoring a fragment using retainInstance" mean? Can you explain what you're actually doing? – ianhanniballake Jul 10 '21 at 04:09
  • @ianhanniballake `retainInstance` in the fragment prevents it from being destroyed when the configuration changes (orientation change for example). https://stackoverflow.com/questions/11182180/understanding-fragments-setretaininstanceboolean – sudoExclaimationExclaimation Jul 10 '21 at 04:36
  • I wrote fragments, so yes, I know how that part works. I'm trying to figure out why you think you need a unique tag and how you are using `findFragmentByTag` at all. – ianhanniballake Jul 10 '21 at 04:41
  • @ianhanniballake I am using it similar to how it's explained in this link. I use the `supportFragmentManager.findFragmentByTag` to get the fragment which was created before device orientation changes. This way I don't have to recreate the data or use anything in `onSaveInstanceState` except the TAG which I use the `mWho` for: https://pspdfkit.com/blog/2019/retaining-objects-using-a-fragment/ – sudoExclaimationExclaimation Jul 10 '21 at 05:03
  • So...why do you need a UUID based tag at all? You could use `"blah"` and it would work exactly the same? – ianhanniballake Jul 10 '21 at 05:07
  • @ianhanniballake when I add another activity with a different fragment instance, wouldn't it end up conflicting? – sudoExclaimationExclaimation Jul 10 '21 at 05:16
  • Each activity is completely separate; there's no conflict. Please include your code where you create your retained fragment, retrieve your retained fragment, and how you use your retained fragment. It really seems like this is an [XY Problem](https://xyproblem.info) that has a much better way of solving your actual underlying problem. – ianhanniballake Jul 10 '21 at 13:38
  • @ianhanniballake is the `supportFragmentManager` unique for every Activity instance? For example when an Activity starts a new activity, is the `supportFragmentManager` for the new activity unique for itself than the previous activity? You are probably right about the XY Problem thing. I am relatively new to Android so I might be using wrong practice. – sudoExclaimationExclaimation Jul 11 '21 at 00:51
  • As I already mentioned, every activity is completely separate from every other activity - the `supportFragmentManager` in one activity is unique to just that activity and a different activity will get a completely different `supportFragmentManager`. – ianhanniballake Jul 11 '21 at 01:25
  • @ianhanniballake ah, then I don't need this unique tag. Thanks. – sudoExclaimationExclaimation Jul 11 '21 at 03:35

1 Answers1

-1

I was able to achieve this using reflection and lazy variable:

val who: String by lazy {
    println("Trying to get who!")
    var toReturn = ""
    try {
        println("Fields: ${javaClass.superclass.superclass}")
        toReturn = javaClass.superclass.superclass.getDeclaredField("mWho").let {
            it.isAccessible = true
            it.get(this)
        } as String
    } catch (e : Exception) {
        println("Exception getting who: $e")
    }
    toReturn
}

Note the use of superclass.superclass because I placed this in a subclass of Fragment. The use of lazy prevents the use of reflection each time it's required as this value doesn't change once initialized.

  • Do not use reflection to access private values of the class - these are private specifically because they are not for your usage. – ianhanniballake Jul 10 '21 at 04:06