-
Notifications
You must be signed in to change notification settings - Fork 989
Fix: TransactionTooLargeException crash #6063
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
@@ -319,7 +323,13 @@ open class BrowserActivity : DuckDuckGoActivity() { | |||
super.onSaveInstanceState(outState) | |||
|
|||
if (swipingTabsFeature.isEnabled) { | |||
outState.putParcelable(KEY_TAB_PAGER_STATE, tabPagerAdapter.saveState()) | |||
if (swipingTabsFeature.isSaveStateToDataStoreEnabled) { | |||
runBlocking { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we have a runblocking here? this will block main thread and cause ANRs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TabsDataStore.saveState()
function is suspended so I was worried that when the activity is finishing and onSaveInstanceState()
would launch a coroutine and then continue, the app might get killed before it can finish saving data. Previously, the state was also getting saved synchronously. But maybe I'm wrong..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AI agrees :)
Launching a coroutine in onSaveInstanceState() is not safe
onSaveInstanceState() is called when an Activity might be destroyed, and the Android system expects you to quickly save minimal state data synchronously in this method. The Bundle you provide must be completely populated by the time the method returns.
Problems with launching a coroutine in onSaveInstanceState():
- Coroutines run asynchronously, so any state saved after the method returns won't make it into the Bundle
- The Activity might be destroyed before the coroutine completes
- The lifecycle of the coroutine wouldn't be properly managed
Instead, you should:
- Save state synchronously in onSaveInstanceState()
- Do any heavy operations earlier in the Activity lifecycle
- Use ViewModel with SavedStateHandle for more complex state saving
- If you need to save state that requires async operations, it's better to do that proactively during normal Activity operation, not during the saving process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just flagging this is danger territory and maybe the approach is not correct. The activity is being destroyed but you are blocking the UI thread until operation finishes and that will produce an ANR.
I see you want to persist the ViewState, and it's suspend because you rely on DataStore. But is dataStore the place where to store that state? do you need to persist into disk? do you want to recover from app being killed?
Task/Issue URL: https://app.asana.com/1/137249556945/project/1202552961248957/task/1210238988495963?focus=true
Description
This PR saves the
TabPagerAdapter
to disk instead of the state instance Bundle, which should potentially prevent any/mostTransactionTooLargeException
crashes when thesaveStateToDataStore
feature flag is enabled.Although the tab swiping feature reduces the limit of active tabs from 40 to 20, which should prevent the original crash, the
ViewPager2
adapter needs to save its state, which again increases the amount of data saved and causes the crash.Steps to test this PR
Don't keep activities
in the device Developer options