无需过多介绍,我将告诉您如何快速轻松地组织应用程序的便捷体系结构。 对于不熟悉mvvm模式和Kotlin协程的人,该材料将很有用。
因此,我们有一个简单的任务:接收和处理网络请求,并在视图中显示结果。
我们的动作:从活动(片段)中调用所需的方法ViewModel-> ViewModel访问改造句柄,通过协程执行请求->将响应作为事件发送到实时数据->在活动中,接收将数据传输到视图的事件。
项目设置
依存关系
清单
<manifest ...> <uses-permission android:name="android.permission.INTERNET" /> </manifest>
改造设置
创建一个Kotlinovsky
NetworkService对象。 这将是我们的网络客户端-单身人士
UPD单例用于易于理解。 评论指出使用控制反转更合适,但这是一个单独的主题。
object NetworkService { private const val BASE_URL = " http://www.mocky.io/v2/"
api界面
我们对假服务使用锁定的请求。
暂停乐趣,从这里开始corutin的魔力。
我们用关键字
suspend fun ...标记我们的功能。
从2.6.0版开始,学习到了与Kotlin暂停功能一起使用的改造,现在,它可以直接执行网络请求并返回带有数据的对象:
interface Api { @GET("5dcc12d554000064009c20fc") suspend fun getUsers( @Query("page") page: Int ): ResponseWrapper<Users> @GET("5dcc147154000059009c2104") suspend fun getUsersError( @Query("page") page: Int ): ResponseWrapper<Users> }
ResponseWrapper是用于我们的网络请求的简单包装器类:
class ResponseWrapper<T> : Serializable { @SerializedName("response") val data: T? = null @SerializedName("error") val error: Error? = null }
日期类
用户 data class Users( @SerializedName("count") var count: Int?, @SerializedName("items") var items: List<Item?>? ) { data class Item( @SerializedName("first_name") var firstName: String?, @SerializedName("last_name") var lastName: String? ) }
视图模型
我们创建一个抽象
BaseViewModel类,所有ViewModel都将从该类继承。 在这里我们更详细地介绍:
abstract class BaseViewModel : ViewModel() { var api: Api = NetworkService.retrofitService()
大事记
Google的一个很酷的解决方案是将日期类包装在Event wrapper类中,在其中可以有几种状态,通常是LOADING,SUCCESS和ERROR。
data class Event<out T>(val status: Status, val data: T?, val error: Error?) { companion object { fun <T> loading(): Event<T> { return Event(Status.LOADING, null, null) } fun <T> success(data: T?): Event<T> { return Event(Status.SUCCESS, data, null) } fun <T> error(error: Error?): Event<T> { return Event(Status.ERROR, null, error) } } } enum class Status { SUCCESS, ERROR, LOADING }
运作方式如下。 在网络请求期间,我们创建一个状态为LOADING的事件。 我们正在等待服务器的响应,然后将数据包装到事件中,并以指定的状态进一步发送。 在视图中,我们检查事件的类型,并根据状态为视图设置不同的状态。 架构模式MVI基于相同的哲学。
ActivityViewModel
class ActivityViewModel : BaseViewModel() {
最后
主要活动
class MainActivity : AppCompatActivity() { private lateinit var activityViewModel: ActivityViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) activityViewModel = ViewModelProviders.of(this).get(ActivityViewModel::class.java) observeGetPosts() buttonOneClickListener() buttonTwoClickListener() }
源代码