SunnyWeather 第一阶段 项目学习笔记

SunnyWeather 第一阶段 项目学习笔记

在此记录项目开发过程种学到的。

MVVM项目架构

MVVM是一种高级的项目架构模式。分别为 Model-View-ViewModel ,类似的架构有MVP、MVC。

Model是数据模型部分、View是界面展示部分、View Model是实现业务逻辑和界面展示分离的程序结构。

一个优秀的项目架构处理包含以上三种,还应该包含仓库、数据源等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1CwSnjuF-1689129418641)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\image-20230712093801391.png)]

一般情况,会按照以上结构实现以下项目结构:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fJzJlYZZ-1689129418643)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\image-20230712093942545.png)]

logic用于存放业务逻辑相关的代码,ui用于存放界面展示的代码。

logic又存放了dao、model、network,分别用于存放数据访问的对象、对象模型、以及网络相关的代码。

ui包含place和weather,分别对应两个主要界面。

全局Context

com.sunnyweather.android包下简历一个SunnyWeatherApplication类,代码如下:

class SunnyWeatherApplication:Application() {
    companion object{
        const val TOKEN = "uYjcEJAykI0e"
        @SuppressLint("StaticFieldLeak")
        lateinit var context: Context
    }

    override fun onCreate() {
        super.onCreate()
        context = applicationContext
    }
}

TOKEN是申请的令牌值,也顺便放在这里。

数据模型

logic/model下创建数据类,data class即数据类。

代码如下:

data class PlaceResponse(val status:String, val places:List<Place>)
data class Place(val name:String , val location:Location, @SerializedName("formatted_address") val address:String)
data class Location(val lng:String, val lat:String)

由于JSON种的一些字段可能与Kotlin命名的规范不一样,因此这里使用了@SerializedName注解,建立映射关系。

网络层

定义搜索API的Retrofit接口

新建PlaceService接口,代码如下:

interface PlaceService {
    @GET("v2/place?token=${SunnyWeatherApplication.TOKEN}&lang=zh_CN")
    fun searchPlaces(@Query("query")query: String):Call<PlaceResponse>
}

@GET是请求范围注解内的地址,@Query是实现动态传参。

Retrofit构建器

建立ServiceCreator,代码如下:

object ServiceCreator {
    private const val BASE_URL = "https://api.caiyunapp.com/"
    private val retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
    fun <T> create(serviceClass: Class<T>):T = retrofit.create(serviceClass)
    inline fun <reified T> create():T = create(T::class.java)
}

统一网络数据源访问入口

对所有网络请求的API进行封装。

新建SunnyWeatherNetwork


object SunnyWeatherNetWork {
    private val placeService  = ServiceCreator.create<PlaceService>()
    suspend fun searchPlaces(query:String) = placeService.searchPlaces(query).await()
    private suspend fun <T> Call<T>.await():T{
        return suspendCoroutine { continuation ->
            enqueue(object :Callback<T>{
                override fun onResponse(call: Call<T>, response: Response<T>) {
                    val body = response.body()
                    if (body!=null)continuation.resume(body)
                    else continuation.resumeWithException(
                        RuntimeException("response body is null")
                    )
                }

                override fun onFailure(call: Call<T>, t: Throwable) {
                    continuation.resumeWithException(t)
                }
            })
        }
    }
}

仓库层

logic下新建单例类Respository,代码实例如下:

object Repository {
    fun searchPlaces(query:String) = liveData(Dispatchers.IO){
        val  result = try {
            val placeResponse = SunnyWeatherNetWork.searchPlaces(query)
            if (placeResponse.status == "OK"){
                val places = placeResponse.places
                Result.success(places)
            }else   {
                Result.failure(RuntimeException("response status is ${placeResponse.status}"))
            }
        }catch (e:Exception){
            Result.failure<List<Place>>(e)
        }
        emit(result)
    }
}

ViewModel

class PlaceViewModel:ViewModel() {
    private val searchLiveData = MutableLiveData<String>()
    val placeList = ArrayList<Place>()
    val placeLiveData = Transformations.switchMap(searchLiveData){
        query->Repository.searchPlaces(query)
    }
    fun searPlaces(query:String){
        searchLiveData.value = query
    }
}
witchMap(searchLiveData){
        query->Repository.searchPlaces(query)
    }
    fun searPlaces(query:String){
        searchLiveData.value = query
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值