【问题标题】:Api Call in mvvm Androidmvvm Android中的API调用
【发布时间】:2019-10-05 18:26:08
【问题描述】:

我是 mvvm 的新手,我一直在尝试使用改造在 mvvm 中调用 kotlin 中的 api。 这是我的xml

<TextView
        android:text="TextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView" app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="84dp" app:layout_constraintTop_toTopOf="parent"/>
<Button
        android:text="Button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button" app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintHorizontal_bias="0.498" app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="332dp" app:layout_constraintTop_toBottomOf="@+id/textView"
        android:layout_marginBottom="8dp" app:layout_constraintBottom_toBottomOf="parent"/>

你可以看到我只有两个元素。一键调用API,一键显示调用的结果代码(无论是200还是其他)。

class testViewModel: ViewModel() {
    var testInput :MutableLiveData<Int> = MutableLiveData(1)
    var test :LiveData<Int> = testInput
    fun clicked(){


        test = API_Repository.createCode()
        println(test.value.toString())

    }
}

这是我的视图模型。

fun createCode(): LiveData<Int> {
    var sendUser = CreateCodeUserClass()
    sendUser.setUsername("09360767928")
    var data = MutableLiveData<Int>()
    my_API_Interface!!.CreateCode(sendUser).enqueue(object : retrofit2.Callback<Void> {
        override fun onFailure(call: Call<Void>, t: Throwable) {
            data.value = 10000
            println(data.value.toString())
        }

        override fun onResponse(call: Call<Void>, response: Response<Void>) {
            data.value = response.code()

        }

    })
    return data
}

这是我的 API 调用

class MainActivity : AppCompatActivity() {

    public var viewModel = testViewModel()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewModel = ViewModelProviders.of(this).get(testViewModel::class.java)
            viewModel.test!!.observe(this, Observer { data ->
                print(data.toString())
                textView.text = data.toString()
            })

        button.setOnClickListener {
            viewModel.clicked()
        }
    }
}

这是我的主要活动。当我在我的视图模型中调用 api 时,测试总是为空,它应该是 10000 或其他数字。我认为 createCode 函数在 OnResponse 或 OnFailure 被触发之前完成。但我不知道该怎么做,我想使用 mvvm。

【问题讨论】:

  • 您是否尝试在 testViewModel 类中删除 println(test.value.toString()) ,因为您的 CreateCode(sendUser).enqueue 是异步调用它总是会使 createCode 函数在 OnResponse 或 OnFailure 之前完成触发
  • 我认为这不会改变任何事情。它只是在日志中显示结果。
  • @DayyanNiliSani 你得到答案了吗.....我也刚刚开始 mvvm 并面临类似的问题。

标签: android mvvm kotlin android-mvvm


【解决方案1】:

我猜,您的问题是因为您在 LiveData 的一个对象上观察到活动,但是当您从 api 收到结果时,您只需将该对象替换为新的 LiveData。您应该等待结果并将其写入 ViewModel 中已创建的 LiveData。使用 MediatorLiveData 是可能的。像这样的:

val monthData = MediatorLiveData<MonthData>() /// livedata i subscribed in view

这是我在视图模型中的“api 调用”。这是主要的魔法。我将我的视图模型的 livedata 订阅到我的“api 调用”的结果,并将数据从那里传递给这个 livedata:

fun loadMonthEvents() {
    monthData.addSource(useCase.getCalendarEvents()) {
        monthData.value = it
    }
}

在我的例子中,我在 RxJava 上的 repo,我将它转换为这样的 livedata (UseCase):

fun getCalendarEvents(): LiveData<MonthData?> {
    val result = mutableLiveDataOf<MonthData?>()

    appointmentsRepository.getAppointmentsIn().subscribe { data ->
        result.value = data
    }

    return result
}

希望对您有所帮助。无论如何,如果您仍有问题,请发表评论:)

【讨论】:

  • 嗨@Sergey 你能解释一下吗?我面临同样的问题,得到空响应
  • 嗨,@JahanviKariya,会很酷,如果你分享你的代码,因为你的情况可能会有所不同。但是,如果您确定它是相同的,那么可以:在 TS 的情况下,有 2 个 LiveData——一个在开始时在 ViewModel 中创建,另一个在 Repository 方法 (createCode) 中创建。因此,您将在 UI 中订阅第一个 livedata(来自 ViewModel),然后从 Repository 返回另一个。另外你不能在返回后立即使用livedata(在TS的情况下在createCode之后的下一行),因为api调用是异步的,数据不会立即出现。
猜你喜欢
  • 1970-01-01
  • 2022-12-09
  • 2023-04-03
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
  • 2023-01-21
相关资源
最近更新 更多