fix: move ContentResolver.getType off main thread in share intent consumer
The DisposableEffect's OnNewIntentListener is invoked on the main thread when a new ACTION_SEND intent arrives (e.g. SwiftKey sharing a GIF). It called contentResolver.getType() synchronously, which can Binder-IPC to a remote content provider and block for tens to hundreds of milliseconds. Use rememberCoroutineScope() + scope.launch(Dispatchers.IO) since DisposableEffect has no coroutine scope of its own. The scope is tied to composition and cancels cleanly on disposal. Also fix a latent bug: the consumer read activity.intent instead of the intent parameter passed into the callback. activity.intent is the Activity's launch intent, not the new one that triggered the listener, so subsequent intents would reuse the first intent's URI.
This commit is contained in:
+9
-3
@@ -55,6 +55,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -124,6 +125,7 @@ import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, FlowPreview::class)
|
||||
@@ -144,6 +146,7 @@ fun ShortNotePostScreen(
|
||||
|
||||
val context = LocalContext.current
|
||||
val activity = context.getActivity()
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
postViewModel.initWritingAssistant(context)
|
||||
@@ -177,9 +180,12 @@ fun ShortNotePostScreen(
|
||||
postViewModel.addToMessage(it)
|
||||
}
|
||||
|
||||
IntentCompat.getParcelableExtra(activity.intent, Intent.EXTRA_STREAM, Uri::class.java)?.let {
|
||||
val mediaType = context.contentResolver.getType(it)
|
||||
postViewModel.selectImage(persistentListOf(SelectedMedia(it, mediaType)))
|
||||
// Use the `intent` parameter (the new intent), not activity.intent (the launch intent).
|
||||
IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java)?.let { uri ->
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val mediaType = context.contentResolver.getType(uri)
|
||||
postViewModel.selectImage(persistentListOf(SelectedMedia(uri, mediaType)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user