Hey guys I am using jetpack compose navigation. I ...
# compose
v
Hey guys I am using jetpack compose navigation. I am trying to pass arraylist and some changes according to this stackoverflow. I am getting error + my value inside data class will drop as well. Can someone guide me, what I am doing wrong here? I am not adding imports, instead I'll add my class link in the name. NavigationGraph.kt
Copy code
private const val NEAREST_RESULT_JSON = "nearestResultJson"

@Composable
internal fun NavigationGraph() {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = ScreenRoute.Home.route) {
        composable(ScreenRoute.Home.route) {
            SetupMainActivityView { nearestResult ->
                val nearestResultJson = Uri.encode(Gson().toJson(nearestResult))
                navController.navigate(ScreenRoute.Result.route + "/{$nearestResultJson}")
            }
        }

        composable(
            ScreenRoute.Result.route + "/{$NEAREST_RESULT_JSON}",
            arguments = listOf(
                navArgument(NEAREST_RESULT_JSON) { type = NearestResultParamType() }
            )
        ) { backStackEntry ->
            ResultScreen(backStackEntry.arguments?.getParcelableArrayList(NEAREST_RESULT_JSON))
        }
    }
}
NearestResultParamType.kt
Copy code
class NearestResultParamType : NavType<ArrayList<NearestResult>>(isNullableAllowed = false) {
    override fun get(bundle: Bundle, key: String): ArrayList<NearestResult>? {
        return bundle.getParcelable(key)
    }

    override fun parseValue(value: String): ArrayList<NearestResult> {
        Log.e("value", ">>$value")
        return Gson().fromJson<ArrayList<NearestResult>>(value, ArrayList::class.java)
    }

    override fun put(bundle: Bundle, key: String, value: ArrayList<NearestResult>) {
        bundle.putParcelableArrayList(key, value)
    }
}
MainActivity.kt
Copy code
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SetupMainActivityView(
    viewModel: MainActivityViewModel = koinViewModel(),
    navigateToNext: (nearestResult: ArrayList<NearestResult>) -> Unit,
) {
    Scaffold(topBar = {
        TopAppBar(
            title = { Text(text = stringResource(id = R.string.app_name)) },
            backgroundColor = getBackgroundColor(),
            elevation = 0.dp
        )
    }, content = { padding ->
        Box(
            modifier = Modifier
                .fillMaxSize()
                .padding(padding)
                .background(getBackgroundColor()),
            contentAlignment = Center
        ) {
            when (val state = viewModel.stateResultFetchState.collectAsState().value) {
                is ResultFetchState.OnSuccess -> {
                    LaunchedEffect(Unit) {
                        navigateToNext(state.nearestResult)
                    }
                }
                is ResultFetchState.IsLoading -> {
                    LoadingFunction()
                }
                is ResultFetchState.OnError,
                is ResultFetchState.OnEmpty -> {
                    ActivityContent(viewModel)
                }
            }
        }
    })
}
When I am printing value inside
parseValue
which drops the value if
day
attribute
Copy code
E/value: >>{[{"day":{},"event":"Roland Garros: Rafael Nadal wins against Schwartzman  in 3 sets"},{"day":{},"event":"Lewis Hamilton wins Silverstone Grand Prix by 5.856 seconds"},{"day":{},"event":"Roland Garros: Novak Djokovic wins against Stefanos Tsitsipas  in 3 sets"},{"day":{},"event":"Lebron James leads Lakers to game 6 win in the NBA playoffs"}]}
I am getting this error and crash the application
Copy code
2022-07-21 17:25:13.821 537-537/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.vivek.sportsresult, PID: 537
    com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
        at com.google.gson.Gson.fromJson(Gson.java:1003)
        at com.google.gson.Gson.fromJson(Gson.java:956)
        at com.google.gson.Gson.fromJson(Gson.java:905)
        at com.vivek.sportsresult.ui.screen.navigation.NearestResultParamType.parseValue(NearestResultParamType.kt:16)
        at com.vivek.sportsresult.ui.screen.navigation.NearestResultParamType.parseValue(NearestResultParamType.kt:9)
        at androidx.navigation.NavType.parseAndPut(NavType.kt:80)
        at androidx.navigation.NavDeepLink.parseArgument(NavDeepLink.kt:254)
        at androidx.navigation.NavDeepLink.getMatchingArguments(NavDeepLink.kt:175)
        at androidx.navigation.NavDestination.matchDeepLink(NavDestination.kt:347)
        at androidx.navigation.NavGraph.matchDeepLink(NavGraph.kt:72)
        at androidx.navigation.NavController.navigate(NavController.kt:1652)
        at androidx.navigation.NavController.navigate(NavController.kt:1984)
        at androidx.navigation.NavController.navigate$default(NavController.kt:1979)
        at com.vivek.sportsresult.ui.screen.navigation.NavigationGraphKt$NavigationGraph$1$1$1.invoke(NavigationGraph.kt:22)
        at com.vivek.sportsresult.ui.screen.navigation.NavigationGraphKt$NavigationGraph$1$1$1.invoke(NavigationGraph.kt:20)
        at com.vivek.sportsresult.ui.screen.MainActivityKt$SetupMainActivityView$1$1$1.invokeSuspend(MainActivity.kt:101)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
        at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
        at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.run(AndroidUiDispatcher.android.kt:57)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7697)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
        Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@f221268, androidx.compose.runtime.BroadcastFrameClock@78db681, StandaloneCoroutine{Cancelling}@db83326, AndroidUiDispatcher@c678b67]
    Caused by: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
        at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350)
        at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:80)
        at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
        at com.google.gson.Gson.fromJson(Gson.java:991)
            ... 27 more
My Github Project link. Can someone guide me what I am doing wrong here. Many Thanks
@Ian Lake Do you have any idea on this?
c
Your JSON is not valid. the array needs a property key inside the object.
v
But when I am passing it already have
It droping some how.
c
No it hasn't as you can see in the logs
>>{[
This is not valid json. You need something like
{„list“:[]}
Check when you are creating the route
v
Ok I'll try to find.
Did not find it
😭
When passing list I need to pass "`list`" before object ?
c
do you understand JSON? you need to create something like
Copy code
{
  "cars": [
    "Ford",
    "BMW",
    "Fiat"
  ]
}
what you are creating is not a valid JSON.
so your object needs a property that has a list as value.
v
I Know how JSON works.
👍 1
Before sending to navigation, I print the value in logs
[NearestResult(day=2020-05-09T23:15:15+01:00[Europe/Dublin], event=Roland Garros: Rafael Nadal wins against Schwartzman  in 3 sets), NearestResult(day=2020-05-09T20:09:03+01:00[Europe/Dublin], event=Lewis Hamilton wins Silverstone Grand Prix by 5.856 seconds), NearestResult(day=2020-05-09T14:00:40+01:00[Europe/Dublin], event=Roland Garros: Novak Djokovic wins against Stefanos Tsitsipas  in 3 sets), NearestResult(day=2020-05-09T09:15:15+01:00[Europe/Dublin], event=Lebron James leads Lakers to game 6 win in the NBA playoffs)]
So this one is correct, so how it internal going to defect after passing in navigation?
i
It looks like you are missing a
Uri.encode
v
I am already doing that link
Copy code
val nearestResultJson = Uri.encode(Gson().toJson(nearestResult))
c
here you are adding the addidtional
{}
Copy code
navController.navigate(ScreenRoute.Result.route + "/{$nearestResultJson}")
just remove the
{}
☝️ 1
not sure why you add these even here
Copy code
ScreenRoute.Result.route + "/{$NEAREST_RESULT_JSON}",
so the path that you create is
result/{nearestResultJson}
and not just
result/nearestResultJson
v
May be it's confusion to pass in line.
So I mixed up in compose and navigate code
i
Yeah, the whole
{nearestResultJson}
is the placeholder pattern that you replace with the actual argument. You don't put braces in the final string you navigate to
v
yeah it's working fine now. But other problem is my
day
attritube is dropping the value.
When I am printing the value NavigationGraph
Copy code
SetupMainActivityView { nearestResult ->
    Log.e("nearestResult ","$nearestResult")
    val nearestResultJson = Uri.encode(Gson().toJson(nearestResult))
    navController.navigate(ScreenRoute.Result.route + "/$nearestResultJson")
}
it giving me this correct output
But on receiver end I am getting drop value output
I fixed the problem. It causing because of Gson
Thank you so much guys @Ian Lake @Chrimaeon.
🎉 1
c
Consider moving to moshi! 😅
i
The correct answer, of course, is to not pass data classes at all (it is absolutely the fasted way to get to an unsolvable without refactoring your entire app
TransactionTooLargeException
), but clearly you're already deep down that bad behavior hole
v
okk thanks 👍
385 Views