【问题标题】:App crashes when calling a method from viewmodel从 viewmodel 调用方法时应用程序崩溃
【发布时间】:2022-01-08 20:22:14
【问题描述】:

我正在尝试使用改造向远程服务器发出请求。我正在使用干净的架构来分离关注点。 来自顶级文件

改装电话

@GET("/api/dedicated_trips")
    suspend fun getDedicatedTrips(
        @Header("Authorization") token: String,
    ): DedicatedTripDto

DedicatedTripDto

data class DedicatedTripDto(
    val `data`: List<Data>,
    val error: Boolean
)

数据


data class Data(
    val depot_location: String,
    val depot_name: String,
    val fuel_amount: Int,
    val fuel_in_litres: Int,
    val fuel_receipt: String?,
    val milleage: Int,
    val no_of_vehicles: Int,
    val odometer_reading: String?,
    val partner_email: String,
    val partner_name: String,
    val pump_reading: String?,
    val registration_number: String,
    val status: String,
    val tracking_no: Int,
    val type: String,
    val vehicle_make: String
)

这是我的用例

class GetDedicatedTripUseCase @Inject constructor(
    private val tripRepository: TripRepository
) {

    suspend operator fun invoke(
        token: String,
    ): Flow<Resource<DedicatedTripDto>> = flow {
        try {
            emit(Resource.Loading())
            val response = tripRepository.getDedicatedTrips(token)
            emit(Resource.Success(response))
        } catch (e: HttpException) {
            emit(Resource.Failure(e.localizedMessage ?: "An expected error occurred"))
        } catch (e: IOException) {
            emit(Resource.Failure("Couldn't connect to server, check your internet connection"))
        }
    }

}

资源


sealed class Resource<out T> {
    class Loading<T>: Resource<T>()
    object Empty: Resource<Nothing>()
    data class Success<out T>(val data: T): Resource<T>()
    data class Failure<out T>(val errorMessage: String?): Resource<T>()

    companion object {
        fun <T> loading() = Loading<T>()
        fun <T> success(data: T) = Success(data)
        fun <T> failed(message: String) = Failure<T>(message)
    }
}

在视图模型方面

@HiltViewModel
class TripViewModel @Inject constructor(
    private val getDedicatedTripUseCase: GetDedicatedTripUseCase,
): ViewModel() {

   private var _dedicatedTripsState = MutableStateFlow<Resource<DedicatedTripDto>>(Resource.Empty)
   val dedicatedTripsState get() = _dedicatedTripsState.asStateFlow()

  fun getTrips(
        token: String,
    ) = viewModelScope.launch {
        getDedicatedTripUseCase(token).collect { state->
            when(state) {
                is Resource.Loading -> {
                    _dedicatedTripsState.value = Resource.loading()
                }
                is Resource.Success -> {
                    _dedicatedTripsState.value = Resource.success(state.data)
                }
                is Resource.Failure -> {
                    _dedicatedTripsState.value = Resource.failed(state.errorMessage!!)
                }
            }
        }
    }

}

View 这边是如何调用视图模型的代码

@AndroidEntryPoint
class TripDetailsFragment : Fragment() {

  private val tripViewModel: TripViewModel by viewModels()
   private var token: String? = null

 override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
       tripViewModel.authToken.observe(viewLifecycleOwner) {
            token = "Bearer $it"
           //Here is where I'm invoking the function from the view model
            tripViewModel.getTrips(token!!)
        }
}
}

当我调用该函数时,应用程序崩溃而在 logcat 中没有显示任何错误。

Json 文件

{
    "error": false,
    "data": [
        {
            "tracking_no": 18842224,
            "milleage": 56,
            "odometer_reading": "odometer/starting-odometer-18842224.jpg",
            "fuel_amount": 0,
            "fuel_in_litres": 0,
            "pump_reading": null,
            "fuel_receipt": null,
            "type": "starting",
            "status": "closed",
            "no_of_vehicles": 4,
            "depot_name": "MURANGA TOWN (fomer Fort Hall), Kenya",
            "depot_location": "MURANGA TOWN (fomer Fort Hall), Kenya",
            "vehicle_make": "Isuzu",
            "registration_number": "KDP 234A",
            "partner_name": "DHL",
            "partner_email": "info@dafric.net"
        },
        ...
    ]
}


【问题讨论】:

  • 当您在fun getTrips 中使用调试器时,它会在哪一行崩溃?可能tripViewModel 没有正确初始化。
  • 它不记录任何东西。
  • logcat 为空
  • 正常运行时,logcat 从不为空。确保您选择了正确的模拟器、应用程序和输出模式(尝试 Verbose),并且如果它完全为空,则没有任何过滤器,或者重新启动模拟器。即使应用程序正常运行,那里也有大量输出。
  • 您也可以尝试重新启动 logcat,按钮看起来像一个正方形,里面有一个循环箭头。如果没有系统的某些部分记录应用程序,应用程序就不会崩溃。如果您仍然没有看到任何内容,请尝试重新启动 IDE,如果仍然无法正常工作,请尝试命令行:developer.android.com/studio/command-line/logcat#Syntax 除非我们知道实际错误是什么,否则没有人可以真正帮助您(当您发布完整的堆栈跟踪时)明白了!)

标签: android kotlin retrofit2 viewmodel kotlin-stateflow


【解决方案1】:

您是否在 AndroidManifest 文件中授予互联网权限?

您确定 api 工作正常吗?也许它正在返回错误或其他格式的东西。

尝试逐行放置日志和/或断点以查找问题。

另外,也许有些字段是空的,而您没有意识到。尝试(暂时)将所有数据类型更改为可为空的字符串(字符串?),看看是否有区别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-06
    • 2012-10-01
    相关资源
    最近更新 更多