Skip to content

Commit dfe146d

Browse files
committed
AndroidBaseLibrary1.2.0
更改弹窗请求相关设计 增加示例
1 parent b0b0b83 commit dfe146d

File tree

15 files changed

+265
-75
lines changed

15 files changed

+265
-75
lines changed

app/build.gradle

+16-3
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,23 @@ dependencies {
4040
implementation 'androidx.appcompat:appcompat:1.3.1'
4141
implementation 'com.google.android.material:material:1.3.0'
4242
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
43-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1")
44-
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1")
43+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1"
44+
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
45+
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1"
46+
47+
implementation "com.squareup.retrofit2:retrofit:2.9.0"
48+
implementation 'com.squareup.retrofit2:converter-gson:2.7.0'
49+
implementation("com.squareup.okhttp3:okhttp:4.10.0")
50+
implementation 'com.github.fengzhizi715:saf-logginginterceptor:v1.6.13'
51+
implementation 'com.google.code.gson:gson:2.8.6'
52+
implementation 'com.github.getActivity:ToastUtils:10.5'
4553
}
4654

4755
dependencies {
4856
implementation 'com.github.wsdydeni:AndroidBaseLibraryNetwork:1.2.0'
49-
}
57+
}
58+
59+
dependencies {
60+
// debugImplementation because LeakCanary should only run in debug builds.
61+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10'
62+
}

app/src/main/AndroidManifest.xml

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
34
package="wsdydeni.widget.library">
45

6+
<uses-permission android:name="android.permission.INTERNET" />
7+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
8+
59
<application
610
android:name="wsdydeni.widget.library.MyApplication"
711
android:allowBackup="true"
812
android:icon="@mipmap/ic_launcher"
913
android:label="@string/app_name"
1014
android:roundIcon="@mipmap/ic_launcher_round"
1115
android:supportsRtl="true"
12-
android:theme="@style/Theme.AndroidBaseLibrary">
16+
android:usesCleartextTraffic="true"
17+
android:theme="@style/Theme.AndroidBaseLibrary"
18+
tools:targetApi="m">
1319
<activity
1420
android:windowSoftInputMode="adjustNothing"
1521
android:name=".MainActivity"

app/src/main/java/wsdydeni/widget/library/MainActivity.kt

+73-3
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,28 @@ import android.view.MotionEvent
44
import android.view.View
55
import android.widget.EditText
66
import android.widget.LinearLayout
7+
import android.widget.TextView
78
import androidx.core.content.ContextCompat
89
import androidx.lifecycle.Lifecycle
10+
import androidx.lifecycle.lifecycleScope
11+
import com.hjq.toast.ToastUtils
12+
import kotlinx.coroutines.Job
13+
import kotlinx.coroutines.launch
914
import wsdydeni.library.android.base.BaseActivity
10-
import wsdydeni.library.android.base.BaseViewModel
15+
import wsdydeni.library.android.base.BaseActivityHandler
1116
import wsdydeni.library.android.utils.another.LogUtil
1217
import wsdydeni.library.android.utils.density.AutoDensity
1318
import wsdydeni.library.android.utils.display.PixelUtil
1419
import wsdydeni.library.android.utils.immersion.getNavBarHeight
1520
import wsdydeni.library.android.utils.immersion.getStatusBarHeight
1621
import wsdydeni.library.android.utils.immersion.showStatusBarView
1722
import wsdydeni.library.android.utils.keyboard.addKeyboardMonitor
23+
import wsdydeni.library.android.utils.lifecycle.launchAndRepeatWithViewLifecycle
24+
import wsdydeni.library.android.utils.lifecycle.repeatOnLifecycle
25+
import wsdydeni.widget.library.base.DialogDismissEffect
26+
import wsdydeni.widget.library.base.DialogShowEffect
27+
import wsdydeni.widget.library.base.ToastShowEffect
28+
import wsdydeni.widget.library.dialog.LoadingDialog
1829

1930
class MainActivity : BaseActivity(R.layout.activity_main) {
2031

@@ -26,6 +37,10 @@ class MainActivity : BaseActivity(R.layout.activity_main) {
2637

2738
override var immersionStatus = true
2839

40+
private var loadingDialog : LoadingDialog? = null
41+
42+
private val myHandler = BaseActivityHandlers(this)
43+
2944
override fun initView() {
3045
addKeyboardMonitor { keyboardHeight, _, _ ->
3146
if(keyboardHeight > 1000) {
@@ -60,6 +75,28 @@ class MainActivity : BaseActivity(R.layout.activity_main) {
6075
}
6176
}
6277
showStatusBarView(findViewById(R.id.fillStatusBarView), ContextCompat.getColor(this, R.color.color_6d7174))
78+
79+
findViewById<TextView>(R.id.send_btn).setOnClickListener {
80+
lifecycleScope.launch {
81+
createLoadingDialog(job = mainViewModel.getArticle())
82+
mainViewModel.setEffect { DialogShowEffect }
83+
}
84+
}
85+
}
86+
87+
private fun createLoadingDialog(text: String = "加载中", isCanCancelByReturn: Boolean = true, job: Job? = null) {
88+
this.loadingDialog = LoadingDialog(this,job)
89+
.setLoadingText(text)
90+
.isCanCancelByReturn(isCanCancelByReturn)
91+
}
92+
93+
override fun initData() {
94+
observeEffect()
95+
launchAndRepeatWithViewLifecycle {
96+
mainViewModel.articleList.collect {
97+
mainViewModel.setEffect { ToastShowEffect("加载成功") }
98+
}
99+
}
63100
}
64101

65102
/**
@@ -75,7 +112,40 @@ class MainActivity : BaseActivity(R.layout.activity_main) {
75112
return super.dispatchTouchEvent(ev)
76113
}
77114

78-
private fun observeEffect(viewModel: BaseViewModel) {
79-
Lifecycle.State.STARTED
115+
private val mainViewModel by lazy { MainViewModel() }
116+
117+
private fun observeEffect() {
118+
lifecycleScope.launch {
119+
repeatOnLifecycle(Lifecycle.State.STARTED) {
120+
mainViewModel.effect.collect { effect ->
121+
when(effect) {
122+
is DialogShowEffect -> {
123+
if(!isDestroyed && !isFinishing) {
124+
myHandler.post {
125+
if(!isDestroyed && !isFinishing) {
126+
loadingDialog?.let {
127+
if(!it.isShowing) it.show()
128+
}
129+
}
130+
}
131+
}
132+
}
133+
is DialogDismissEffect -> {
134+
loadingDialog?.let { dialog ->
135+
dialog.dismissCancelJob(effect.isCancel)
136+
loadingDialog = null
137+
}
138+
}
139+
is ToastShowEffect -> {
140+
ToastUtils.show(effect.text)
141+
}
142+
}
143+
}
144+
}
145+
}
146+
}
147+
148+
companion object {
149+
class BaseActivityHandlers(activity: BaseActivity) : BaseActivityHandler(activity)
80150
}
81151
}

app/src/main/java/wsdydeni/widget/library/MainFragment.kt

-9
This file was deleted.

app/src/main/java/wsdydeni/widget/library/MainViewModel.kt

+26-26
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,41 @@
11
package wsdydeni.widget.library
22

33
import androidx.lifecycle.viewModelScope
4-
import kotlinx.coroutines.CoroutineExceptionHandler
5-
import kotlinx.coroutines.Dispatchers
6-
import kotlinx.coroutines.Job
7-
import kotlinx.coroutines.launch
4+
import kotlinx.coroutines.*
5+
import kotlinx.coroutines.flow.*
86
import wsdydeni.library.android.utils.another.LogUtil
9-
import wsdydeni.library.android_network.network.BaseResponse
107
import wsdydeni.library.android_network.network.associatedView
118
import wsdydeni.widget.library.base.BaseViewModel
9+
import wsdydeni.widget.library.base.DialogDismissEffect
10+
import wsdydeni.widget.library.base.DialogShowEffect
11+
import wsdydeni.widget.library.base.ToastShowEffect
12+
import wsdydeni.widget.library.data.network.ArticleList
13+
import wsdydeni.widget.library.data.network.WandroidService
14+
import wsdydeni.widget.library.data.network.getApiService
1215

1316
class MainViewModel : BaseViewModel() {
1417

15-
class TestResponse : BaseResponse<Int>() {
16-
override fun getResponseCode(): String = "200"
17-
override fun getResponseData(): Int = 20
18-
override fun getResponseMsg(): String = "success"
19-
override fun isSuccess(): Boolean = true
20-
}
18+
private val articleService by lazy { getApiService<WandroidService>() }
2119

22-
private suspend fun request1() : TestResponse {
23-
return TestResponse()
20+
private val coroutineExceptionHandler = CoroutineExceptionHandler { _, _ ->
21+
viewModelScope.launch { setEffect { DialogDismissEffect(true) } }
2422
}
2523

26-
fun send() {
27-
val coroutineExceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
28-
coroutineContext[Job]?.cancel()
29-
LogUtil.d("MainViewModel coroutineExceptionHandler send" + throwable.message)
30-
}
31-
viewModelScope.launch(Dispatchers.IO + coroutineExceptionHandler) {
32-
associatedView(suspend { request1() },{
33-
// show dialog
34-
},{
35-
// close dialog
36-
}) { errorMsg, errorCode ->
37-
// close dialog
38-
// show error message
24+
private val _articleLists = MutableSharedFlow<ArticleList>()
25+
val articleList = _articleLists.asSharedFlow()
26+
27+
fun getArticle() : Job {
28+
return viewModelScope.launch(Dispatchers.IO + coroutineExceptionHandler, start = CoroutineStart.LAZY) {
29+
associatedView(
30+
request = suspend { articleService.getArticleList() },
31+
onRequestSuccess = { delay(1000L)
32+
setEffect { DialogDismissEffect() } },
33+
onRequestError = { errorMsg, _ ->
34+
setEffect { DialogDismissEffect(true) }
35+
setEffect { ToastShowEffect(errorMsg) }
36+
}
37+
).collect {
38+
_articleLists.emit(it)
3939
}
4040
}
4141
}

app/src/main/java/wsdydeni/widget/library/MyApplication.kt

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package wsdydeni.widget.library
22

33
import android.app.Application
4+
import com.hjq.toast.ToastUtils
45
import wsdydeni.library.android.utils.another.LogUtil
56
import wsdydeni.library.android.utils.density.AutoDensity
67
import wsdydeni.library.android.utils.density.DesignDraft
@@ -9,6 +10,7 @@ class MyApplication : Application() {
910
override fun onCreate() {
1011
super.onCreate()
1112
LogUtil.init(true)
13+
ToastUtils.init(this)
1214
AutoDensity.instance.init(this, DesignDraft(designSize = 360f))
1315
}
1416
}

app/src/main/java/wsdydeni/widget/library/base/ViewModelEffect.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ sealed class ViewModelEffect
44

55
object DialogShowEffect : ViewModelEffect()
66

7-
object DialogDismissEffect : ViewModelEffect()
7+
class DialogDismissEffect(val isCancel: Boolean = false) : ViewModelEffect()
8+
9+
class ToastShowEffect(val text: String) : ViewModelEffect()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package wsdydeni.widget.library.data.network
2+
3+
data class ArticleList(
4+
val curPage: Int,
5+
val datas: List<Article>,
6+
val offset: Int,
7+
val over: Boolean,
8+
val pageCount: Int,
9+
val size: Int,
10+
val total: Int
11+
)
12+
13+
data class Article(
14+
val adminAdd: Boolean,
15+
val apkLink: String,
16+
val audit: Int,
17+
val author: String,
18+
val canEdit: Boolean,
19+
val chapterId: Int,
20+
val chapterName: String,
21+
val collect: Boolean,
22+
val courseId: Int,
23+
val desc: String,
24+
val descMd: String,
25+
val envelopePic: String,
26+
val fresh: Boolean,
27+
val host: String,
28+
val id: Int,
29+
val isAdminAdd: Boolean,
30+
val link: String,
31+
val niceDate: String,
32+
val niceShareDate: String,
33+
val origin: String,
34+
val prefix: String,
35+
val projectLink: String,
36+
val publishTime: Long,
37+
val realSuperChapterId: Int,
38+
val route: Boolean,
39+
val selfVisible: Int,
40+
val shareDate: Long,
41+
val shareUser: String,
42+
val superChapterId: Int,
43+
val superChapterName: String,
44+
val tags: List<Tag>,
45+
val title: String,
46+
val type: Int,
47+
val userId: Int,
48+
val visible: Int,
49+
val zan: Int
50+
)
51+
52+
data class Tag(
53+
val name: String,
54+
val url: String
55+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package wsdydeni.widget.library.data.network
2+
3+
import com.google.gson.annotations.SerializedName
4+
import wsdydeni.library.android_network.network.BaseResponse
5+
import java.io.Serializable
6+
7+
data class DataWrapper<T>(
8+
@SerializedName("data") var data: T,
9+
@SerializedName("errorMsg") var message : String,
10+
@SerializedName("errorCode") var code : Int
11+
) : Serializable, BaseResponse<T>() {
12+
13+
override fun getResponseCode(): String = code.toString()
14+
15+
override fun getResponseData(): T = data
16+
17+
override fun getResponseMsg(): String = message
18+
19+
override fun isSuccess(): Boolean = code == 0
20+
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package wsdydeni.widget.library.data.network
2+
3+
import com.google.gson.Gson
4+
import com.safframework.http.interceptor.AndroidLoggingInterceptor
5+
import okhttp3.OkHttpClient
6+
7+
import retrofit2.Retrofit
8+
import retrofit2.converter.gson.GsonConverterFactory
9+
import java.util.concurrent.TimeUnit
10+
11+
inline fun <reified T> getApiService() : T {
12+
val retrofit = Retrofit.Builder()
13+
.baseUrl("https://www.wanandroid.com")
14+
.client(getOkhttp())
15+
.addConverterFactory(GsonConverterFactory.create(Gson()))
16+
.build()
17+
return retrofit.create(T::class.java)
18+
}
19+
20+
21+
fun getOkhttp() : OkHttpClient {
22+
return OkHttpClient.Builder()
23+
.connectTimeout(2000L,TimeUnit.MILLISECONDS)
24+
.readTimeout(2000L,TimeUnit.MILLISECONDS)
25+
.addNetworkInterceptor(AndroidLoggingInterceptor.build())
26+
.build()
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package wsdydeni.widget.library.data.network
2+
3+
import retrofit2.http.GET
4+
5+
interface WandroidService {
6+
@GET("/article/list/0/json")
7+
suspend fun getArticleList() : DataWrapper<ArticleList>
8+
}

0 commit comments

Comments
 (0)