android 获取数据并在API响应后插入LazyColumn(Jetpack合成)

cgh8pdjw  于 2023-02-02  发布在  Android
关注(0)|答案(1)|浏览(116)

我对Jetpack Compose和Kotlin完全陌生,但对Java中的Android开发并不熟悉。想要第一次接触这两种技术,我想做一个非常简单的应用程序,用API中的文本填充LazyColumn。
如果我使用自定义日历来选择一周中的某一天,我希望与服务器通信,并从存储在一周中该天的数据接收响应,以将其与LazyColumn Composables关联。
我已经创建了TodoItem和TodoItemList函数,但是我问这个问题是因为我不知道如何通过与服务器通信和接收数据响应来连接这些值。

读取待办事项请求.kt

package com.example.todo_android.Request.TodoRequest

import com.example.todo_android.Response.TodoResponse.ReadTodoResponse
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Query

interface ReadTodoRequest {
    @GET("/todo/todo/")
    fun requestReadTodo(
        @Header("Authorization") token: String,
        @Query("year") year: Int,
        @Query("month") month: Int,
        @Query("day") day: Int
        ): Call<ReadTodoResponse>
}

读取到响应.kt

package com.example.todo_android.Response.TodoResponse

import com.google.gson.annotations.SerializedName

data class ReadTodoResponse(
    @SerializedName("resultCode")
    val resultCode: Int,
    @SerializedName("data")
    val data: ArrayList<RToDoResponse>
)

// 응답값으로 data의 디테일한 값들
data class RToDoResponse(
    val id: Int,
    val title: String,
    val year: Int,
    val month: Int,
    val day: Int,
    val done: Boolean,
    val writer: String
)

待办事项.kt

package com.example.todo_android.Component

import android.provider.Settings.Global.getString
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.core.content.res.TypedArrayUtils.getString
import com.example.todo_android.Response.TodoResponse.ReadTodoResponse
import com.google.gson.JsonArray
import java.time.MonthDay
import java.time.Year

@Composable
fun TodoItem(Todo: ReadTodoResponse) {
    Card(
        modifier = Modifier
            .padding(12.dp)
            .fillMaxWidth()
            .height(80.dp)
            .background(color = Color.White)

    ) {
        Column(
            modifier = Modifier.fillMaxWidth(),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Text(
                text = Todo.data.toString(),
            )
        }
    }
}

@Composable
fun TodoItemList(Todo: List<ReadTodoResponse>) {
    LazyColumn {
        itemsIndexed(items = Todo) { index, item ->
            TodoItem(Todo = item)
        }
    }
}

日历屏幕.kt

package com.example.todo_android.Screen

import android.util.Log
import androidx.compose.animation.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.example.todo_android.Component.TodoItemList
import com.example.todo_android.Data.Todo.CreateTodo
import com.example.todo_android.Data.Todo.ReadTodo
import com.example.todo_android.Data.Todo.UpdateTodo
import com.example.todo_android.Navigation.Action.RouteAction
import com.example.todo_android.Request.TodoRequest.CreateTodoRequest
import com.example.todo_android.Request.TodoRequest.DeleteTodoRequest
import com.example.todo_android.Request.TodoRequest.ReadTodoRequest
import com.example.todo_android.Request.TodoRequest.UpdateTodoRequest
import com.example.todo_android.Response.TodoResponse.CreateTodoResponse
import com.example.todo_android.Response.TodoResponse.DeleteTodoResponse
import com.example.todo_android.Response.TodoResponse.ReadTodoResponse
import com.example.todo_android.Response.TodoResponse.UpdateTodoResponse
import com.example.todo_android.Util.MyApplication
import com.himanshoe.kalendar.Kalendar
import com.himanshoe.kalendar.color.KalendarThemeColor
import com.himanshoe.kalendar.component.day.config.KalendarDayColors
import com.himanshoe.kalendar.model.KalendarDay
import com.himanshoe.kalendar.model.KalendarEvent
import com.himanshoe.kalendar.model.KalendarType
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

fun createTodo(token: String, year: String, month: String, day: String, title: String) {

    var createTodoResponse: CreateTodoResponse? = null

    var retrofit = Retrofit.Builder()
        .baseUrl("https://plotustodo-ctzhc.run.goorm.io/")
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    var createTodoRequest: CreateTodoRequest = retrofit.create(CreateTodoRequest::class.java)

    createTodoRequest.requestCreateTodo(token, CreateTodo(year, month, day, title))
        .enqueue(object : Callback<CreateTodoResponse> {

            // 실패 했을때
            override fun onFailure(call: Call<CreateTodoResponse>, t: Throwable) {
                Log.e("error", t.message.toString())
            }

            // 성공 했을때
            override fun onResponse(
                call: Call<CreateTodoResponse>,
                response: Response<CreateTodoResponse>,
            ) {
                createTodoResponse = response.body()

                Log.d("createTodo", "token : " + MyApplication.prefs.getData("token", ""))
                Log.d("createTodo", "resultCode : " + createTodoResponse?.resultCode)
                Log.d("createTodo", "data : " + createTodoResponse?.data)

            }
        })
}

fun readTodo(token: String, year: Int, month: Int, day: Int) {

    var readTodoResponse: ReadTodoResponse? = null

    var retrofit = Retrofit.Builder()
        .baseUrl("https://plotustodo-ctzhc.run.goorm.io/")
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    var readTodoRequest: ReadTodoRequest = retrofit.create(ReadTodoRequest::class.java)

    readTodoRequest.requestReadTodo(token, year, month, day)
        .enqueue(object : Callback<ReadTodoResponse> {

            //실패할 경우
            override fun onFailure(call: Call<ReadTodoResponse>, t: Throwable) {
                Log.e("readTodo", t.message.toString())
            }

            //성공할 경우
            override fun onResponse(
                call: Call<ReadTodoResponse>,
                response: Response<ReadTodoResponse>,
            ) {
                readTodoResponse = response.body()

                Log.d("readTodo", "token : " + MyApplication.prefs.getData("token", ""))
                Log.d("readTodo", "resultCode : " + readTodoResponse?.resultCode)
                Log.d("readTodo", "data : " + readTodoResponse?.data)
            }
        })
}

fun updateTodo(
    token: String,
    year: String,
    month: String,
    day: String,
    title: String,
    done: String,
) {

    var updateTodoResponse: UpdateTodoResponse? = null

    var retrofit = Retrofit.Builder()
        .baseUrl("https://plotustodo-ctzhc.run.goorm.io/")
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    var updateTodoRequest: UpdateTodoRequest = retrofit.create(UpdateTodoRequest::class.java)

    updateTodoRequest.requestUpdateTodo(token, UpdateTodo(year, month, day, title, done))
        .enqueue(object : Callback<UpdateTodoResponse> {

            // 실패 했을때
            override fun onFailure(call: Call<UpdateTodoResponse>, t: Throwable) {
                Log.e("updateTodo", t.message.toString())
            }

            // 성공 했을때
            override fun onResponse(
                call: Call<UpdateTodoResponse>,
                response: Response<UpdateTodoResponse>,
            ) {

                if (response.isSuccessful) {
                    updateTodoResponse = response.body()

                    Log.d("updateTodo", "token : " + MyApplication.prefs.getData("token", ""))
                    Log.d("updateTodo", "resultCode : " + updateTodoResponse?.resultCode)
                    Log.d("updateTodo", "data : " + updateTodoResponse?.data)
                } else {
                    Log.e("updateTodo", "resultCode : " + response.body())
                    Log.e("updateTodo", "code : " + response.code())
                }
            }
        })
}

fun deleteTodo(
    token: String,
) {
    var deleteTodoResponse: DeleteTodoResponse? = null

    var retrofit = Retrofit.Builder()
        .baseUrl("https://plotustodo-ctzhc.run.goorm.io/")
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    var deleteTodoRequest: DeleteTodoRequest = retrofit.create(DeleteTodoRequest::class.java)

    deleteTodoRequest.requestDeleteTodo(token)
        .enqueue(object : Callback<DeleteTodoResponse> {

            // 실패 했을때
            override fun onFailure(call: Call<DeleteTodoResponse>, t: Throwable) {
                Log.e("updateTodo", t.message.toString())
            }

            // 성공 했을때
            override fun onResponse(
                call: Call<DeleteTodoResponse>,
                response: Response<DeleteTodoResponse>,
            ) {
                deleteTodoResponse = response.body()

                Log.d("deleteTodo", "token : " + MyApplication.prefs.getData("token", ""))
                Log.d("deleteTodo", "resultCode : " + deleteTodoResponse?.resultCode)
                Log.d("deleteTodo", "data : " + deleteTodoResponse?.data)
            }
        })
}

@ExperimentalMaterial3Api
@Composable
fun CalendarScreen(routeAction: RouteAction) {

    val states = listOf(
        "월간",
        "주간"
    )
    var selectedOption by remember { mutableStateOf(states[1]) }

    val onSelectionChange = { text: String -> selectedOption = text }

    var isVisible by remember { mutableStateOf(true) }

    val token = "Token ${MyApplication.prefs.getData("token", "")}"

//    val year = "2023"
//    val month = "2"
//    val day = "6"
//    val token = "Token ${MyApplication.prefs.getData("token", "")}"
//    val title = "qkrwhdwns"
//    val done = "true"

    var year by remember { mutableStateOf(0) }
    var month by remember { mutableStateOf(0) }
    var day by remember { mutableStateOf(0) }

    val todoList = remember {
        mutableStateListOf<ReadTodoResponse>()
    }

    val title = remember { mutableStateOf("") }
    val done = remember { mutableStateOf("") }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Top
    ) {

        Spacer(modifier = Modifier.height(15.dp))

        Row(
            modifier = Modifier
                .clip(shape = RoundedCornerShape(24.dp))
                .background(Color(0xffe9e9ed))
                .padding(4.dp)
        )
        {
            states.forEach { text ->
                Text(
                    text = text,
                    color =
                    if (text == selectedOption) {
                        Color.Black
                    } else {
                        Color.Gray
                    },
                    fontWeight = FontWeight.Medium,
                    modifier = Modifier
                        .clip(shape = RoundedCornerShape(24.dp))
                        .clickable {
                            onSelectionChange(text)
                            isVisible = !isVisible
                        }
                        .background(
                            if (text == selectedOption) {
                                Color.White
                            } else {
                                Color(0xffe9e9ed)
                            }
                        )
                        .padding(
                            vertical = 5.dp,
                            horizontal = 16.dp,
                        )
                )
            }
        }

        Spacer(modifier = Modifier.height(29.dp))

        AnimatedVisibility(isVisible)
        {
            Kalendar(
                kalendarType = KalendarType.Oceanic(),
                kalendarDayColors = KalendarDayColors(Color.Black, Color.Black),
                kalendarThemeColor = KalendarThemeColor(
                    backgroundColor = Color.White,
                    dayBackgroundColor = Color(0xffFBE3C7),
                    headerTextColor = Color.Black),
                onCurrentDayClick = { kalendarDay: KalendarDay, kalendarEvents: List<KalendarEvent> ->

                    year = kalendarDay.localDate.year
                    month = kalendarDay.localDate.monthNumber
                    day = kalendarDay.localDate.dayOfMonth

                    todoList.clear()

                    readTodo(token, year, month, day)
                })
        }

        AnimatedVisibility(!isVisible) {
            Kalendar(
                kalendarType = KalendarType.Firey,
                kalendarDayColors = KalendarDayColors(Color.Black, Color.Black),
                kalendarThemeColor = KalendarThemeColor(
                    backgroundColor = Color.White,
                    dayBackgroundColor = Color(0xffFBE3C7),
                    headerTextColor = Color.Black),
                onCurrentDayClick = { kalendarDay: KalendarDay, kalendarEvents: List<KalendarEvent> ->

                    year = kalendarDay.localDate.year
                    month = kalendarDay.localDate.monthNumber
                    day = kalendarDay.localDate.dayOfMonth

                    todoList.clear()

                    readTodo(token, year, month, day)
                })
        }

        Spacer(modifier = Modifier.height(29.dp))

        Text(text = day.toString())

        TodoItemList(Todo = todoList)

//        Scaffold(floatingActionButton = {
//            FloatingActionButton(onClick = { /*TODO*/ }) {
//                Icon(imageVector = Icons.Default.Add, contentDescription = "todolist 추가")
//            }
//        }) {
//            LazyColumn {
//                TodoItem()
//            }
//        }

//        Surface(
//            shape = RoundedCornerShape(24.dp),
//            modifier = Modifier
//                .wrapContentSize()
//        ) {}

//        Button(
//            modifier = Modifier
//                .width(300.dp)
//                .height(50.dp),
//            colors = ButtonDefaults.buttonColors(Color(0xffFFBE3C7)),
//            onClick = { readTodo(token, year, month, day) }
//        ) {
//            Text(text = "TODO 조회", color = Color.Black)
//        }
//
//        Spacer(modifier = Modifier.height(30.dp))
//
//        Button(
//            modifier = Modifier
//                .width(300.dp)
//                .height(50.dp),
//            colors = ButtonDefaults.buttonColors(Color(0xffFFBE3C7)),
//            onClick = { createTodo(token, year, month, day, title) }
//        ) {
//            Text(text = "TODO 작성", color = Color.Black)
//        }
//
//        Spacer(modifier = Modifier.height(30.dp))
//
//        Button(
//            modifier = Modifier
//                .width(300.dp)
//                .height(50.dp),
//            colors = ButtonDefaults.buttonColors(Color(0xffFFBE3C7)),
//            onClick = { updateTodo(token, year, month, day, title, done) }
//        ) {
//            Text(text = "TODO 수정", color = Color.Black)
//        }
//
//        Spacer(modifier = Modifier.height(30.dp))
//
//        Button(
//            modifier = Modifier
//                .width(300.dp)
//                .height(50.dp),
//            colors = ButtonDefaults.buttonColors(Color(0xffFFBE3C7)),
//            onClick = { deleteTodo(token) }
//        ) {
//            Text(text = "TODO 삭제", color = Color.Black)
//        }
    }
}
brvekthn

brvekthn1#

有几件事可能会有帮助。
1.您可以在@Composable中使用val scope = rememberCoroutineScope()来创建一个协程作用域,在@Composable dispose时将自动取消作业。
1.对于列表,如果希望在列表大小变化时刷新界面,可以选择val todos = remember { mutableStateListOf<String>() },这样调用todos.add就可以成功更新界面。
1.如果你想在你的TodoItem中修改todos,你可以这样写:

@Composable
fun TodoItem(
    item: TodoItemBean,
    deleteAction: () -> Unit,
) {
    Button(onClick = deleteAction) {
        Text("delete")
    }
}

fun deleteTodo(
    token: String,
    onSuccess: () -> Unit,
    onFail: (e: Throwable) -> Unit
) {
    /**
     * deleteTodoRequest.requestDeleteTodo(token)
            .enqueue(object : Callback<DeleteTodoResponse> {
        
            // 실패 했을때
            override fun onFailure(call: Call<DeleteTodoResponse>, t: Throwable) {
                onFail(t)
            }
        
            // 성공 했을때
            override fun onResponse(
                call: Call<DeleteTodoResponse>,
                response: Response<DeleteTodoResponse>,
            ) {
                deleteTodoResponse = response.body()
                if(deleteTodoResponse.code == 200){ onSuccess() }
                else { onFail(...) }
            }
       }
     */
}
@Composable
fun TodoList() {
    val todos = remember { mutableStateListOf<TodoItemBean>() }
    val scope = rememberCoroutineScope()
    val context = LocalContext.current
    LazyColumn {
        items(todos){ item ->
            TodoItem(item = item, deleteAction = {
                scope.launch {
                    deleteTodo("token", onSuccess = {
                        todos.remove(item)
                    }, onFail = {
                        Toast.makeText(context, "Failed to delete", Toast.LENGTH_SHORT).show()
                    })
                    
                }
            })
        }
    }
}

希望这能帮到你!

相关问题