Home > Software design >  Why it says " List contains no element matching the predicate." for android jetpack compos
Why it says " List contains no element matching the predicate." for android jetpack compos

Time:06-23

I have Onboarding Screens for my project, and it work correctly, but I want to show users it just once, and I was using shared preferences for it, and when debug the project it is throw an error like that in logcat,

List contains no element matching the predicate.

, and in android emulator I can see main screen, but app crash quickly, when I open app again on simulator, onboarding screen shows just 1 second and open main screen, than app crash, I do not know why? I guess problem is because of this line of code,

if (!sharedPreferences.getBoolean("firstTime", true)) {
                    navController.navigate("main")
                }else{

but I am not sure.

mainscreen:

@Composable
 fun MainScreen(
     navController: NavController,

 ) {

     
     Column(
         Modifier
             .fillMaxSize()

         ,
         horizontalAlignment = Alignment.CenterHorizontally
     ) {

      Text(
                     "WELCOME TO",
                     modifier = Modifier
                         .width(300.dp)

                     ,
                     textAlign = TextAlign.Start,
                     fontSize = 15.sp,
                     color = custom,
                     fontWeight = FontWeight.Medium

                 )
}

nav:

@OptIn(ExperimentalPagerApi::class)
@Composable
fun NavScreen(
    sharedPreferences: SharedPreferences
) {


    val navController = rememberNavController()


    NavHost(navController = navController, startDestination = "onBoard") {

        composable("onBoard",  ) {

            OnBoardScreen(navController = navController, sharedPreferences)
        }
        composable("main") {
            MainScreen(navController = navController)
        }
}

viewmodel:

class OnBoardViewModel (

)  : ViewModel() {
    private val _currentPage = MutableStateFlow(0)
    val currentPage: StateFlow<Int> get() = _currentPage

    fun setCurrentPage(currentPage: Int) {
        _currentPage.value = currentPage
    }

}

MainActivity:

@AndroidEntryPoint
class MainActivity : ComponentActivity(

) {

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
       
        setContent {
            CustomTheme {
                    Surface(color = MaterialTheme.colors.background) {
                        val sharedPreferences = getSharedPreferences("onBoardingScreen", MODE_PRIVATE)

                        NavScreen(sharedPreferences)
                }
             }
         }
     }
   }



@ExperimentalPagerApi
@Composable
fun OnBoardScreen(
    navController: NavController,
    sharedPreferences: SharedPreferences
) {
    val scaffoldState = rememberScaffoldState()
    val onBoardViewModel : OnBoardViewModel = viewModel()
    val currentPage = onBoardViewModel.currentPage.collectAsState()


    val pagerState = rememberPagerState(
        pageCount = onBoardItem.size,
        initialOffscreenLimit = 2,
        initialPage = 0,
        infiniteLoop = false
    )

    Scaffold(
        modifier = Modifier.fillMaxSize(),
        scaffoldState = scaffoldState
    ) {
        Surface(
            modifier = Modifier.fillMaxSize()
        ) {

            if (!sharedPreferences.getBoolean("firstTime", true)) {
                navController.navigate("main")
            }else{
                val editor = sharedPreferences.edit()
                editor.putBoolean("firstTime", false)
                editor.apply()
            }

            LaunchedEffect(Unit) {
                onBoardViewModel.currentPage
                    .collect {
                        pagerState.animateScrollToPage(
                            page = currentPage.value
                        )
                    }
            }

            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .background(
                        brush = Brush.verticalGradient(
                            colors = listOf(
                                white,
                                grey
                            )
                        )
                    )
            ) {
                Column(
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    HorizontalPager(
                        state = pagerState
                    ) { page ->
                        Column(
                            modifier = Modifier
                                .padding(top = 60.dp)
                                .fillMaxWidth(),
                            horizontalAlignment = Alignment.CenterHorizontally
                        ) {

                            Text(
                                text = onBoardItem[page].desc,
                                modifier = Modifier
                                    .padding(30.dp),
                                color = custom,
                                fontSize = 18.sp,
                                textAlign = TextAlign.Center
                            )
                            Spacer(modifier = Modifier.padding(10.dp))

                            Image(
                                painter = painterResource(id = onBoardItem[page].image),
                                contentDescription = "OnBoardImage",
                                modifier = Modifier
                                    .height(500.dp)
                                    .fillMaxWidth(),

                            )

                        }
                    }

                    PagerIndicator(onBoardItem.size, pagerState.currentPage)
                }

                Box(
                    modifier = Modifier
                        .align(Alignment.BottomCenter)
                ) {
                    Row(
                        modifier = Modifier
                            .padding(bottom = 30.dp)
                            .fillMaxWidth(),
                        horizontalArrangement = if (pagerState.currentPage != 2 ) {
                            Arrangement.SpaceBetween
                        } else {
                            Arrangement.Center
                        }
                    ) {
                        if (pagerState.currentPage == 2) {

                            CompositionLocalProvider(LocalRippleTheme provides NoRippleTheme) {
                            Text(
                                text = "Start",
                                color = custom,
                                modifier = Modifier
                                    .padding(start = 280.dp, bottom = 40.dp)

                                    .clickable {
                                        navController.navigate("main")


                                    },
                                fontSize = 18.sp,
                                fontWeight = FontWeight.Medium


                            )
                        }

                        } else {
                            CompositionLocalProvider(LocalRippleTheme provides NoRippleTheme) {
                            Text(
                                text = "Skip",
                                color = custom,
                                modifier = Modifier
                                    .padding(start = 25.dp, bottom = 42.dp)
                                    .clickable {
                                        navController.navigate("main")

                                    },
                                fontSize = 18.sp,
                                fontWeight = FontWeight.Medium
                            )
                        }

                            CompositionLocalProvider(LocalRippleTheme provides NoRippleTheme) {
                            Text(
                                text = "Next",
                                color = custom,
                                modifier = Modifier
                                    .clickable {
                                        onBoardViewModel.setCurrentPage(pagerState.currentPage   1)
                                    }
                                    .padding(end = 25.dp, bottom = 42.dp),
                                fontSize = 18.sp,
                                fontWeight = FontWeight.Medium
                            )
                        }
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun PagerIndicator(size: Int, currentPage: Int) {
    Row(
        horizontalArrangement = Arrangement.SpaceBetween,
        modifier = Modifier.padding(top = 40.dp)
    ) {
        repeat(size) {
            IndicateIcon(
                isSelected = it == currentPage
            )
        }
    }
}

@Composable
fun IndicateIcon(isSelected: Boolean) {
    val width = animateDpAsState(
        targetValue = if (isSelected) 10.dp else 10.dp
    )

    Box(
        modifier = Modifier
            .padding(2.dp)
            .height(10.dp)
            .width(width.value)
            .clip(CircleShape)
            .background(
                if (isSelected) custom else customColor
            )
    )
}

CodePudding user response:

I think the problem is that you are calling navController.navigate("main") during composition while not ensuring that it is called only once when the navigation should happen, thus creating a situation where navController.navigate("main") is called repeatedly in quick succession. I think that might be the cause and the exception might be the effect.

Wrap the navigation call (that is now directly part of the composition) into a LaunchedEffect

    if (!sharedPreferences.getBoolean("firstTime", true)) {
        LaunchedEffect(Unit) {
            navController.navigate("main")
        }
    } else {
        val editor = sharedPreferences.edit()
        editor.putBoolean("firstTime", false)
        editor.apply()
    }
  • Related