diff --git a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/m/BaseRepository.kt b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/m/BaseRepository.kt index 699d904..c1fb19f 100644 --- a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/m/BaseRepository.kt +++ b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/m/BaseRepository.kt @@ -18,8 +18,6 @@ open class BaseRepository { * @param requestBlock 请求的整体逻辑 * @return Flow */ - protected suspend fun flowRequest(requestBlock: suspend FlowCollector.() -> Unit) = - flow { - requestBlock() - }.flowOn(Dispatchers.IO) // 通过 flowOn 切换到 io 线程 + protected fun flowRequest(requestBlock: suspend FlowCollector.() -> Unit) = + flow(block = requestBlock).flowOn(Dispatchers.IO) // 通过 flowOn 切换到 io 线程 } \ No newline at end of file diff --git a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameFragment.kt b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameFragment.kt index 5a6aeb7..0ff9ebe 100644 --- a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameFragment.kt +++ b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameFragment.kt @@ -8,6 +8,7 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.viewbinding.ViewBinding +import com.alibaba.android.arouter.launcher.ARouter /** * @Author: QuYunShuo @@ -38,6 +39,8 @@ abstract class BaseFrameFragment(private val v override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + // ARouter 依赖注入 + ARouter.getInstance().inject(this) initView() } } \ No newline at end of file diff --git a/Lib_Common/src/main/java/com/quyunshuo/common/bean/TestBean.kt b/Lib_Common/src/main/java/com/quyunshuo/common/bean/TestBean.kt new file mode 100644 index 0000000..1e8f278 --- /dev/null +++ b/Lib_Common/src/main/java/com/quyunshuo/common/bean/TestBean.kt @@ -0,0 +1,3 @@ +package com.quyunshuo.common.bean + +data class TestBean(val msgTest: String) \ No newline at end of file diff --git a/Lib_Common/src/main/java/com/quyunshuo/common/constant/NetUrl.kt b/Lib_Common/src/main/java/com/quyunshuo/common/constant/NetUrl.kt new file mode 100644 index 0000000..bbd4ebe --- /dev/null +++ b/Lib_Common/src/main/java/com/quyunshuo/common/constant/NetUrl.kt @@ -0,0 +1,11 @@ +package com.quyunshuo.common.constant + +/** + * @Author: QuYunShuo + * @Time: 2020/8/29 + * @Class: NetUrl + * @Remark: 请求公共地址 统一放在此类 + */ +object NetUrl { + const val url1 = "https://api.com/" +} \ No newline at end of file diff --git a/Lib_Common/src/main/java/com/quyunshuo/common/constant/SpKey.kt b/Lib_Common/src/main/java/com/quyunshuo/common/constant/SpKey.kt new file mode 100644 index 0000000..65212f9 --- /dev/null +++ b/Lib_Common/src/main/java/com/quyunshuo/common/constant/SpKey.kt @@ -0,0 +1,11 @@ +package com.quyunshuo.common.constant + +/** + * @Author: QuYunShuo + * @Time: 2020/8/29 + * @Class: SpKey + * @Remark: 本地存储的键 放在此类中 + */ +object SpKey { + const val IS_FIRST_START = "is_first_start" +} \ No newline at end of file diff --git a/Lib_Common/src/main/java/com/quyunshuo/common/net/NetRequest.kt b/Lib_Common/src/main/java/com/quyunshuo/common/net/NetRequest.kt new file mode 100644 index 0000000..dd8d5a7 --- /dev/null +++ b/Lib_Common/src/main/java/com/quyunshuo/common/net/NetRequest.kt @@ -0,0 +1,23 @@ +package com.quyunshuo.common.net + +import com.quyunshuo.common.net.api.ApiCommonService +import com.quyunshuo.common.net.api.ApiHomeService + +/** + * @Author: QuYunShuo + * @Time: 2020/8/29 + * @Class: NetRequest + * @Remark: 对ApiService动态代理对象统一管理 + */ +object NetRequest { + + // Home Service + val homeService by lazy(mode = LazyThreadSafetyMode.NONE) { + NetServiceCreator.create(ApiHomeService::class.java) + } + + // 公共接口 + val commonService by lazy(mode = LazyThreadSafetyMode.NONE) { + NetServiceCreator.create(ApiCommonService::class.java) + } +} \ No newline at end of file diff --git a/Lib_Common/src/main/java/com/quyunshuo/common/net/NetServiceCreator.kt b/Lib_Common/src/main/java/com/quyunshuo/common/net/NetServiceCreator.kt new file mode 100644 index 0000000..5b2e66a --- /dev/null +++ b/Lib_Common/src/main/java/com/quyunshuo/common/net/NetServiceCreator.kt @@ -0,0 +1,61 @@ +package com.quyunshuo.common.net + +import com.quyunshuo.base.BuildConfig +import com.quyunshuo.common.constant.NetUrl +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import java.util.concurrent.TimeUnit + +/** + * @Author: QuYunShuo + * @Time: 2020/8/29 + * @Class: NetServiceCreator + * @Remark: Retrofit动态代理对象获取封装 + */ +object NetServiceCreator { + + private const val BASE_URL = NetUrl.url1 + + private const val CONNECT_TIME_OUT = 15L + + private const val READ_TIME_OUT = 20L + + private val BODY by lazy(mode = LazyThreadSafetyMode.NONE) { + HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY) + } + + private val NONE by lazy(mode = LazyThreadSafetyMode.NONE) { + HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.NONE) + } + + private val okHttpClient by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { + OkHttpClient.Builder() + .connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS) // 连接超时 + .readTimeout(READ_TIME_OUT, TimeUnit.SECONDS) // 读取超时 + .addInterceptor(if (BuildConfig.DEBUG) BODY else NONE) // 请求日志拦截器 + .retryOnConnectionFailure(true) // 失败重连 + .build() + } + + private val retrofit by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { + Retrofit.Builder() + .baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) // Gson转换器 + .client(okHttpClient) + .build() + } + + /** + * 获取service动态代理对象 + * @param serviceClass 接口Class对象 + */ + fun create(serviceClass: Class): T = retrofit.create(serviceClass) + + /** + * 获取service动态代理对象 + * 范型实化 + */ + inline fun create(): T = create(T::class.java) +} \ No newline at end of file diff --git a/Lib_Common/src/main/java/com/quyunshuo/common/net/api/ApiCommonService.kt b/Lib_Common/src/main/java/com/quyunshuo/common/net/api/ApiCommonService.kt new file mode 100644 index 0000000..5ceb0ac --- /dev/null +++ b/Lib_Common/src/main/java/com/quyunshuo/common/net/api/ApiCommonService.kt @@ -0,0 +1,9 @@ +package com.quyunshuo.common.net.api + +/** + * @Author: QuYunShuo + * @Time: 2020/8/29 + * @Class: ApiCommonService + * @Remark: 公共接口 + */ +interface ApiCommonService \ No newline at end of file diff --git a/Lib_Common/src/main/java/com/quyunshuo/common/net/api/ApiHomeService.kt b/Lib_Common/src/main/java/com/quyunshuo/common/net/api/ApiHomeService.kt new file mode 100644 index 0000000..dc3c433 --- /dev/null +++ b/Lib_Common/src/main/java/com/quyunshuo/common/net/api/ApiHomeService.kt @@ -0,0 +1,19 @@ +package com.quyunshuo.common.net.api + +import com.quyunshuo.common.bean.TestBean +import retrofit2.http.GET +import retrofit2.http.Query + +/** + * @Author: QuYunShuo + * @Time: 2020/8/29 + * @Class: ApiService + * @Remark: Home接口 + */ +interface ApiHomeService { + + // Retrofit 2.6版本开始支持协程 只需要将抽象方法写成挂起函数即可 + @GET() + suspend fun getTestData(@Query("test") test: String): TestBean + +} \ No newline at end of file diff --git a/Lib_Main/src/main/java/com/quyunshuo/main/MainRepository.kt b/Lib_Main/src/main/java/com/quyunshuo/main/MainRepository.kt index 6ed557b..8507934 100644 --- a/Lib_Main/src/main/java/com/quyunshuo/main/MainRepository.kt +++ b/Lib_Main/src/main/java/com/quyunshuo/main/MainRepository.kt @@ -1,6 +1,7 @@ package com.quyunshuo.main import com.quyunshuo.base.mvvm.m.BaseRepository +import com.quyunshuo.common.net.NetRequest /** * @Author: QuYunShuo @@ -17,4 +18,35 @@ class MainRepository : BaseRepository() { flowRequest { emit("嘿嘿") } + + /** + * 模拟使用网络请求接口 + * 需要写成挂起函数 + */ + suspend fun mockRequest() = + flowRequest { + // 发起请求 + // 并行请求可以使用 async await + // 例如 + // // 创建一个新的协程进行请求 + // val deferredRealtime = async { + // SendRequest.getRealtimeWeather(lng, lat) + // } + // // 创建一个新的协程进行请求 + // val deferredDaily = async { + // SendRequest.getDailyWeather(lng, lat) + // } + // // 对两个请求获取结果 + // val realtimeResponse = deferredRealtime.await() + // val dailyResponse = deferredDaily.await() + // 这两个协程是并行的 不是串行 + + val testData = NetRequest.homeService.getTestData("mock") + + // 处理请求结果 + // {if testData ... } + + // 将请求结果或者是调用者需要的数据进行发射出去 + emit(testData.msgTest) + } } \ No newline at end of file diff --git a/Lib_Main/src/main/java/com/quyunshuo/main/MainViewModel.kt b/Lib_Main/src/main/java/com/quyunshuo/main/MainViewModel.kt index fdb9d24..9bc8e2f 100644 --- a/Lib_Main/src/main/java/com/quyunshuo/main/MainViewModel.kt +++ b/Lib_Main/src/main/java/com/quyunshuo/main/MainViewModel.kt @@ -1,10 +1,14 @@ package com.quyunshuo.main +import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.quyunshuo.base.mvvm.vm.BaseViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.onCompletion +import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch /** @@ -26,4 +30,26 @@ class MainViewModel : BaseViewModel() { } } } + + fun getTestString() { + viewModelScope.launch { + mRepository.getString() + .onStart { + // 获取数据之前 + // 可以做loading图之类的 + } + .catch { + // 处理异常 获取数据产生的异常 + } + .onCompletion { + // 获取数据完成时 + } + .collectLatest { + // 拿到想要的数据 + Log.d("qqq", "getTestString: $it") + } + // onStart() catch() onCompletion() 都是可选的 是flow的操作符 + // 例如 mRepository.getString().collectLatest { // 拿到想要的结果 } + } + } } \ No newline at end of file diff --git a/README.md b/README.md index ca07b17..ec666eb 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,15 @@ note: 1. 测试打包脚本 Activity/Fragment 中 可以使用 lifecycleScope,与Activity/Fragment绑定了生命周期 无需手动取消 ViewModel 中 可以使用 viewModelScope,它与ViewModel绑定了生命周期 无需手动取消 lifecycleScope和viewModelScope 默认的调度器是Main +} + +第三方库{ + 屏幕适配 AndroidAutoSize : https://github.com/JessYanCoding/AndroidAutoSize + 本地存储 MMKV : https://github.com/Tencent/MMKV + 路由 ARouter : https://github.com/alibaba/ARouter +} + +网络{ + 关于请求接口的代理接口,建议按接口的使用范围进行划分,比如公用接口单独写在一个接口里,Home页用的接口单独写在一个接口里... + 然后在NetRequest类中统一委托延时初始化实例,调用者直接通过NetRequest进行选择性调用相应的代理接口 } \ No newline at end of file