Why is a wrapper necessary for a LiveData value?

Suppose your LiveData observer in a Fragment navigates to a second Fragment. The user rotates the screen so the first Fragment instance is destroyed. When they back out of the second Fragment, a new instance of the first Fragment is recreated, so its observer is triggered again. Without the event wrapper, it would suddenly and surprisingly navigate back to the second Fragment immediately.

Also, a LiveData might have multiple observers. Maybe two different Fragments are observing the same events LiveData, but you don't want to risk showing the user a message twice for the same event. For example, they could navigate to a second Fragment that is observing the same events LiveData as the first Fragment. An event fires and the second Fragment observer shows the user a dialog box or something. Then the user backs up to the first Fragment and that same event will fire the first Fragment's observer so the event gets handled twice.

If your project uses coroutines, a cleaner solution for this event observing problem is to use a SharedFlow with replay of 0 instead of using a LiveData with an event wrapper class. I suspect the reason they didn't use SharedFlow in the JetSurvey project is that they don't want to assume you're already familiar with Flows when that's not what the example is about.

An alternate solution called SingleLiveEvent appeared in an official Android example once, but was considered too hacky to add to the Jetpack libraries.