refactor: jetpack compose(2/n)
This commit is contained in:
@@ -50,6 +50,7 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:4.9.1")
|
||||
implementation 'androidx.preference:preference:1.2.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
|
||||
implementation 'androidx.activity:activity-compose:1.8.2'
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
android:exported="true"
|
||||
android:label="@string/title_activity_post"
|
||||
android:theme="@style/Theme.Material3.DayNight.NoActionBar" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
@@ -37,11 +42,7 @@
|
||||
<activity
|
||||
android:name=".ui.activity.MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.lsp.view.repository.network.retrofit
|
||||
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
@@ -12,8 +14,16 @@ object ServiceCreator {
|
||||
*
|
||||
*/
|
||||
fun <T> create(serviceClass: Class<T>, source: String): T {
|
||||
val loggingInterceptor = HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
}
|
||||
|
||||
val client = OkHttpClient.Builder().addInterceptor(loggingInterceptor).build()
|
||||
|
||||
|
||||
val retrofit = Retrofit.Builder()
|
||||
.baseUrl(source)
|
||||
.client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
return retrofit.create(serviceClass)
|
||||
|
||||
@@ -3,26 +3,43 @@ package com.lsp.view.ui.compose
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.items
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.lsp.view.bean.Post
|
||||
import com.lsp.view.ui.compose.theme.LspViewTheme
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil.compose.AsyncImage
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.compose.SubcomposeAsyncImageContent
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
private const val TAG = "Compose_PostActivity"
|
||||
class PostActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -41,16 +58,40 @@ class PostActivity : ComponentActivity() {
|
||||
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun PostList(viewModel: PostViewModel = viewModel()) {
|
||||
val uiState by viewModel.uiState.collectAsState()
|
||||
val postList by viewModel.postData.collectAsState()
|
||||
val listState = rememberLazyStaggeredGridState()
|
||||
|
||||
LaunchedEffect(listState) {
|
||||
snapshotFlow { listState.layoutInfo }
|
||||
.map { layoutInfo ->
|
||||
layoutInfo.visibleItemsInfo.lastOrNull()?.index == postList.lastIndex
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.collect { reachedEnd ->
|
||||
//避免初次加载数据时,list未绘制导致被判断为到达底部
|
||||
if (reachedEnd && listState.firstVisibleItemIndex != 0) {
|
||||
viewModel.fetchPost()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyVerticalStaggeredGrid(
|
||||
state = listState,
|
||||
columns = StaggeredGridCells.Adaptive(200.dp),
|
||||
verticalItemSpacing = 4.dp,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
content = {
|
||||
items(postList) {
|
||||
PostItem(it)
|
||||
items(items=postList, key = {
|
||||
it.postId//提供key以保持列表顺序稳定
|
||||
}) {
|
||||
Row(Modifier.animateItemPlacement(tween(durationMillis = 250))) {
|
||||
PostItem(it)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -59,10 +100,26 @@ fun PostList(viewModel: PostViewModel = viewModel()) {
|
||||
|
||||
@Composable
|
||||
fun PostItem(post:Post){
|
||||
AsyncImage(
|
||||
SubcomposeAsyncImage(
|
||||
model = post.sampleUrl,
|
||||
contentScale = ContentScale.Crop,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.fillMaxWidth().wrapContentHeight()
|
||||
loading ={
|
||||
Box(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(300.dp)) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.size(50.dp)
|
||||
.align(Alignment.Center))
|
||||
}
|
||||
},
|
||||
success = {
|
||||
SubcomposeAsyncImageContent()
|
||||
},
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(5.dp))
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.lsp.view.ui.compose
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.lsp.view.bean.YandPost
|
||||
@@ -36,9 +35,8 @@ class PostViewModel:ViewModel() {
|
||||
_uiState.value.safeModel,
|
||||
_uiState.value.page
|
||||
)
|
||||
Log.d("PostViewModel",data.size.toString())
|
||||
postData.value = data
|
||||
|
||||
_uiState.value.page ++
|
||||
postData.value += data
|
||||
} catch (e: NetworkErrorException) {
|
||||
//todo network error
|
||||
}
|
||||
@@ -46,4 +44,5 @@ class PostViewModel:ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user