API响应retrofit2上出现空指针异常,尽管响应操作成功

问题描述 投票:0回答:1

问题:

我正在尝试将 ID 参数传递到对话框屏幕以按 ID 查看所需的数据。尽管响应过程已成功完成(如堆栈跟踪所示),但场所的数据始终返回 NullPointerException。以下几行中使用此 API 的相同步骤与项目的其他部分完美配合。

如图所示,响应状态成功,API 数据已获取,但仍然提供此错误。

如果有人能帮忙的话。

错误:

API响应步骤:

//对话框屏幕

@Composable
fun FetchVenueInfo(
    onDismiss: ()-> Unit,
    onConfirm:()->Unit,
    mainViewModel: MainViewModel = hiltViewModel()
) {
    val context = LocalContext.current
    LaunchedEffect(key1 = Unit) {
        if (!mainViewModel.isVenuesByIdInitialized.value) {
            mainViewModel.getVenuesById(mainViewModel.venueId.value)
            mainViewModel.isVenuesByIdInitialized.value = true
        }
    }
    when (val state = mainViewModel.venuesByIdState.collectAsState().value) {
        is VenuesByIdState.Empty -> {  }
        is VenuesByIdState.Loading -> {  }
        is VenuesByIdState.Error -> {
            Toast.makeText(context, state.message, Toast.LENGTH_SHORT).show()
        }
        is VenuesByIdState.Success -> {
            CustomDialog(
                onDismiss = { onDismiss() },
                onConfirm = { onConfirm() },
                venuesResponse = state.data.body()!!
            )
        }
    }
}

@Composable
fun CustomDialog(
    onDismiss: ()-> Unit,
    onConfirm:()->Unit,
    venuesResponse: VenuesResponse
) {
    val dark = LocalTheme.current.isDark
    Dialog(
        onDismissRequest = {
            onDismiss()
        },
        properties = DialogProperties(
            usePlatformDefaultWidth = false
        )
    ) {
       Card(
            elevation = CardDefaults.cardElevation(8.dp),
            shape = RoundedCornerShape(15.dp),
            modifier = Modifier
                .fillMaxWidth(0.95f)
                .border(
                    2.dp, color = MaterialTheme.colorScheme.primary,
                    shape = RoundedCornerShape(15.dp)
                )
       ) {
            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(15.dp),
                verticalArrangement = Arrangement.spacedBy(25.dp)
            ){
                Text(venueResponse.name!!) // <- NullPointerException
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                ) {
                    AsyncImage(
                        model = venuesResponse.image, // <- NullPointerException
                        contentDescription = "Image"
                    )
                }
            }
       }
    }
}

//点击打开对话框

@Composable
fun MainScreen(
    matchByIdResponseItem: MatchByIdResponseItem,
    mainViewModel: MainViewModel = hiltViewModel()
) {
    if (mainViewModel.isDialogShown) {
        FetchStadiumInfo(
            onDismiss = { mainViewModel.onDismiss() },
            onConfirm = {}
        )
    }
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(
                 interactionSource = remember { MutableInteractionSource() },
                 indication = ripple(
                      bounded = true,
                      color = MaterialTheme.colorScheme.primary
                 ),
                 onClick = {
                      mainViewModel.setId(matchByIdResponseItem.fixture!!.venue!!.id!!)
                      mainViewModel.onDialogOpened()
                 }
            )
            .padding(top = 1.dp),
       colors = CardDefaults.cardColors(
            containerColor = Color.Transparent
       )
    ) {
       //...
    }
}

//视图模型

@HiltViewModel
class MainViewModel @Inject constructor(private val mainRepository: MainRepository): ViewModel() {
      private var _venuesByIdState = MutableStateFlow<VenuesByIdState>(VenuesByIdState.Empty)
      val venuesByIdState: StateFlow<VenuesByIdState> = _venuesByIdState
      //Call Limit
      private var _isVenuesByIdInitialized = mutableStateOf(false)
      var isVenuesByIdInitialized: MutableState<Boolean> = _isVenuesByIdInitialized
      var isDialogShown by mutableStateOf(false)
         private set
      private var _venueId = mutableIntStateOf(0)
      val venueId: MutableState<Int> = _venueId
      fun onDialogOpened(){
         isDialogShown = true
      }
      fun onDismiss() {
         isDialogShown = false
      }
      fun setId(id: Int) {
         viewModelScope.launch {
             _venueId.intValue = id
         }
      }

      suspend fun getVenuesById(id: Int) {
          _venuesByIdState.value = VenuesByIdState.Loading

          try {
              val venueByIdResponse = mainRepository.getVenuesById(id)
              _venuesByIdState.value = VenuesByIdState.Success(data = venueByIdResponse)
              Log.d("Tag", "Success")
          }
          catch (exception: HttpException) {
              _venuesByIdState.value = VenuesByIdState.Error("Something went wrong")
          }
          catch (exception: IOException) {
              _venuesByIdState.value = VenuesByIdState.Error("IO Exception")
          }
      }
}
sealed class VenuesByIdState {
    object Empty: VenuesByIdState()
    object Loading: VenuesByIdState()
    class Success(val data: Response<VenuesResponse>): VenuesByIdState()
    class Error(val message: String): VenuesByIdState()
}
class MainRepository @Inject constructor(
    private val mainApiService: MainApi 
) {
    suspend fun getVenuesById(id: Int): Response<VenuesResponse> = mainApiService.getVenuesById(id)
}
interface MainApi {
    @Headers("api-key: $API_KEY")
    @GET(Constants.GET_VENUES)
    suspend fun getVenuesById(
        @Query(Constants.VENUE_BY_ID_PARAM) id: Int
    ): Response<VenuesResponse>
}
android android-jetpack-compose retrofit2
1个回答
0
投票

您的日志仅显示 API 已成功返回数据。但它并没有给你任何提示:Retrofit/OkHttp/Gson 是否能够成功地将响应数据映射到你的

Response<VenuesResponse>
类上。

您尚未提供

VenuesResponse
类,但如果字段名称或 JSON 响应的层次结构与您的 Kotlin 类不匹配,则可能会发生以下情况:所有字段都将设置为
null

我建议您按如下方式更新日志语句:

Log.d("Tag", "Success: $venueByIdResponse ")

并检查此时值是否已经为空。


此外,请确保使用正确的变量名称。这可能只是一个错字,但是

Text(venueResponse.name!!)

甚至不应该编译,因为

venueResponse
不存在,它应该是
venuesResponse

© www.soinside.com 2019 - 2024. All rights reserved.