代码之家  ›  专栏  ›  技术社区  ›  OEThe11

在Jetpack Compose Navigation中传递pokemon名称以从API端点提取其信息

  •  0
  • OEThe11  · 技术社区  · 3 年前

    我用Jetpack Compose创建了一个口袋妖怪应用程序。我有两个屏幕。一个屏幕显示口袋妖怪的名字,另一个屏幕显示选定口袋妖怪的详细信息。我想实现的是,在选定口袋妖怪后,将其名称传递到url,并将信息显示在第二个屏幕上。

    const val POKE_DETAILS = "api/v2/pokemon/{name}/"
    

    网络文件

    interface NetworkingService{
        @GET(Endpoints.POKE_LIST)
        suspend fun getListResponse(
            @Query("limit") limit: String = "151"
        ): Response<GetPokemonListResponse>
    
        @GET(Endpoints.POKE_DETAILS)
        suspend fun getDetailsResponse(
            @Path("name") name: String
        ): GetPokemonDetailResponse
    
    }
    
    object PokemonNetworkObject{
        val moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
        val retroFit: Retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(MoshiConverterFactory.create(moshi))
            .build()
    
        val networkingServices: NetworkingService by lazy {
            retroFit.create(NetworkingService::class.java)
        }
        val apiClient = ApiClient(networkingServices)
    }
    

    合成屏幕

    @Preview
    @Composable
    fun PokemonListPage(pokemonViewModel: PokemonListViewModel = viewModel(), navController: NavController){
    
        val pokeList = pokemonViewModel.pokemonStateData.collectAsState().value
    
        Surface(
            modifier = Modifier
                .fillMaxHeight()
                .fillMaxWidth(),
        ) {
            Scaffold(topBar =
            {
                TopAppBar(
                    backgroundColor = Color.DarkGray,
                    elevation = 0.dp,
                ) {
                    Row(modifier = Modifier
                        .fillMaxWidth(),
                        horizontalArrangement = Arrangement.Center
                    ){
                        Text(
                            text = "POKEDEX",
                            fontWeight = FontWeight.Bold,
                            fontSize = 25.sp,
                            color = Color.Magenta
                        )
                    }
                }
            }, backgroundColor = Color.DarkGray){
                PokemonCards(pokemons = pokeList!!, navController = navController))
            }
    
    
    
    //        PokemonCards(pokemons = pokeList!!)
        }
    }
    
    @Composable
    private fun PokemonCards(pokemons: List<PokeListEntity>, navController: NavController) {
        LazyColumn{
            items(pokemons){ pokemon ->
                PokemonCard(pokemon = pokemon, navController = navController)
            }
            }
        }
    
    @Composable
    private fun PokemonCard(pokemon: PokeListEntity, navController: NavController) {
        Card(
            modifier = Modifier
                .width(500.dp)
                .requiredHeight(100.dp)
                .padding(10.dp),
            backgroundColor = Color.Cyan,
            shape = RoundedCornerShape(corner = CornerSize(10.dp)),
            elevation = 5.dp
        ) {
            Row(
                modifier = Modifier
                    .padding(start = 16.dp, end = 16.dp),
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.SpaceBetween
            ) {
                Text(
                    text = pokemon.name,
                    fontSize = 25.sp,
                    fontWeight = FontWeight.Bold
                )
    
                Button(
                    onClick = { 
                      navController.navigate(route = "pokemon_detail_screen/${pokemon.name}")
                    }) {
                    Text(text = "INFO")
                }
            }
        }
    }
    

    详细信息屏幕

     @Preview
        @Composable
        fun PokemonDetailScreen(
    detailViewModel: DetailViewModel = viewModel(), 
    navController: NavController,
    pokemonName: String // This Variable
    ) {
        
            val details by detailViewModel.detailState.observeAsState()
        
            Surface(
                modifier = Modifier
                    .fillMaxWidth()
                    .fillMaxHeight(),
                color = Color.DarkGray
            ) {
                DetailCard(field = details!!)
        
            }
        }
        
        @Composable
        private fun DetailCard(field: GetPokemonDetailResponse) {
            Card(
                modifier = Modifier
                    .requiredHeight(300.dp)
                    .fillMaxWidth()
                    .padding(10.dp),
                backgroundColor = Color.Cyan,
                shape = RoundedCornerShape(corner = CornerSize(15.dp)),
                elevation = 10.dp
            ) {
                Column(
                    modifier = Modifier
                        .fillMaxHeight()
                        .fillMaxWidth()
                        .padding(10.dp),
                    verticalArrangement = Arrangement.SpaceEvenly,
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    DetailFields("Name:", field = field.name)
                    Divider(thickness = 4.dp)
                    DetailFields("Height:", field = "${field.height}.in")
                    Divider(thickness = 4.dp)
                    DetailFields("Weight:", field = "${field.weight}.lbs")
                }
            }
        }
        
        @Composable
        private fun DetailFields(title: String, field: String) {
            Column() {
                Text(
                    title,
                    fontSize = 20.sp
                )
                Text(
                    field,
                    fontSize = 30.sp,
                    fontWeight = FontWeight.Bold
                )
            }
        
        }
    

    主要活动

    class MainActivity : ComponentActivity() {
    
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
              PokeDexComposeTheme {
                  Surface(
                      modifier = Modifier.fillMaxSize()
                    ) {
                      val navController = rememberNavController()
                      NavHost(
                          navController = navController,
                          startDestination = "pokemon_list_page"
                      ) {
                          composable("pokemon_list_page") {
                              PokemonListPage(navController = navController)
                          }
                          composable(
                              "pokemon_detail_screen/{name}",
                              arguments = listOf(
                                  navArgument("name") {
                                      type = NavType.StringType
                                  }
                              )
                          ) {
                              // The navBackStackEntry contains the arguments
                              val pokemonName = remember {
                                  it.arguments?.getString("name")
                              }
    
                              PokemonDetailScreen(
                                  pokemonName = pokemonName?.lowercase() ?: "",
                                  navController = navController)
                          }
                      }
    //                  val pokeListViewModel = viewModel<PokemonListViewModel>()
    //                  PokemonListPage(pokeListViewModel)
                  }
              }
            }
        }
    }
    

    这对我来说还是很新鲜。欢迎提出任何建议。谢谢


    使现代化 我已经创建了一个导航组件,但我不知道在详细信息屏幕中在哪里传递Pokemoname字符串值

    *如果你想测试一些东西,这里有一份项目副本。 https://drive.google.com/drive/folders/1gLH_Q3jYLhn-6ad0LMBeZHb8HyT8FszC?usp=sharing

    0 回复  |  直到 3 年前