改造 2:在没有互联网的情况下阅读 JSON 时应用程序崩溃

Retrofit 2: App Crashes When Reading JSON Without Internet

我试图阻止我的应用程序在用户没有互联网连接时尝试使用 Gson 和 Retrofit2 读取 json 信息时崩溃。有什么想法吗?

我的代码:

片段

class ManuFragment : Fragment() {
    private lateinit var viewModel: ManuFragmentVM

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        _binding = FragmentManuBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel = ViewModelProvider(this).get(ManuFragmentVM::class.java)

        viewModel.apply {
            manufacturer.observe(requireActivity(), {loadRecyclerView(it)})
            setup()
        }
    }

查看模型

class ManuFragmentVM : ViewModel() {

    val manufacturer = MutableLiveData<List<Manufacturers>>()

    fun setup() {
        viewModelScope.launch(Dispatchers.Default) {
            manufacturer.postValue(CarsRepository().getAllManufacturers())
        }
    }

界面

interface ManufacturerApi {
    @GET("url.json")
    suspend fun fetchAllManufacturers(): List<Manufacturers>
}

存储库

class CarsRepository {

    private fun manufacturerRetrofit(): ManufacturerApi {
        return Retrofit.Builder()
            .baseUrl("https://website.com/")
            .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
            .build()
            .create(ManufacturerApi::class.java)
    }

    suspend fun getAllManufacturers(): List<Manufacturers> {
        return manufacturerRetrofit().fetchAllManufacturers()

    }

看来您只需要将调用包装在 try-catch 中即可:

fun setup() {
    viewModelScope.launch(Dispatchers.IO) {
        try {
            manufacturer.postValue(CarsRepository().getAllManufacturers())
        } catch (ce: CancellationException) {
            throw ce // Needed for coroutine scope cancellation
        } catch (e: Exception) {
            // display error
        }
    }
}

此外,您应该 运行 API 显式调用 IO 调度程序。您的其余代码看起来非常好。

您可以用 try catch 块包裹 manufacturer.postValue(CarsRepository().getAllManufacturers())。如果您想告诉用户该错误,请创建另一个 LiveData 对象,例如val error: MutableLiveData<String> 和 post 来自 catch 块的错误文本。