个人作业Android学习系统开发日志六
Android实现:
CodeLog:
entity:
package com.example.learningmanagement.entity
import com.google.gson.annotations.SerializedName
import java.util.Date
data class CodeLog(
val id: String = "",
@SerializedName("date")
val date: Date,
val estimate: Double = 0.0,
val analysis: String = "",
val codingStandard: String = "",
val designDetails: String = "",
val code: String = "",
val workloadMeasurement: String = "",
val postmortemAnalysis: String = "",
val improvementPlan: String = "",
val totalHours: Double = 0.0,
val userId: Int
)
adapter:
package com.example.learningmanagement.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.learningmanagement.databinding.ItemCodeLogBinding
import com.example.learningmanagement.entity.CodeLog
import java.text.SimpleDateFormat
import java.util.Locale
class CodeLogAdapter : ListAdapter<CodeLog, CodeLogAdapter.ViewHolder>(CodeLogDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemCodeLogBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val codeLog = getItem(position)
holder.bind(codeLog)
}
class ViewHolder(private val binding: ItemCodeLogBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(codeLog: CodeLog) {
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
binding.tvDate.text = "日期: ${dateFormat.format(codeLog.date)}"
binding.tvEstimate.text = "估计时间: ${codeLog.estimate}小时"
binding.tvAnalysis.text = "需求分析: ${codeLog.analysis}"
binding.tvCodingStandard.text = "代码规范: ${codeLog.codingStandard}"
binding.tvDesignDetails.text = "设计内容: ${codeLog.designDetails}"
binding.tvCode.text = "代码: ${codeLog.code}"
binding.tvWorkloadMeasurement.text = "工作量计算: ${codeLog.workloadMeasurement}"
binding.tvPostmortemAnalysis.text = "事后总结: ${codeLog.postmortemAnalysis}"
binding.tvImprovementPlan.text = "改进计划: ${codeLog.improvementPlan}"
binding.tvTotalHours.text = "合计时间: ${codeLog.totalHours}小时"
}
}
class CodeLogDiffCallback : DiffUtil.ItemCallback<CodeLog>() {
override fun areItemsTheSame(oldItem: CodeLog, newItem: CodeLog): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: CodeLog, newItem: CodeLog): Boolean {
return oldItem == newItem
}
}
}
service:
package com.example.learningmanagement.service
import com.example.learningmanagement.entity.ApiResponse
import com.example.learningmanagement.entity.CodeLog
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path
interface CodeLogService {
@POST("dailyLog/add")
suspend fun addCodeLog(@Body codeLog: CodeLog): ApiResponse<Any>
@GET("dailyLog/selectAll/{userId}")
suspend fun getCodeLogs(@Path("userId") userId: String): ApiResponse<List<CodeLog>>
}
fragment:
package com.example.learningmanagement.ui.fragment
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.learningmanagement.adapter.CodeLogAdapter
import com.example.learningmanagement.databinding.FragmentCodeLogBinding
import com.example.learningmanagement.entity.CodeLog
import com.example.learningmanagement.network.ServiceCreater
import com.example.learningmanagement.service.CodeLogService
import com.example.learningmanagement.ui.MainActivity
import com.example.learningmanagement.utils.PrefsHelper
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
class CodeLogFragment : Fragment() {
private var _binding: FragmentCodeLogBinding? = null
private val binding get() = _binding!!
private val codeLogService = ServiceCreater.create<CodeLogService>()
private val codeLogAdapter = CodeLogAdapter()
private lateinit var prefs: PrefsHelper
override fun onAttach(context: Context) {
super.onAttach(context)
prefs = PrefsHelper(context)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentCodeLogBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupRecyclerView()
loadCodeLogs()
// 更新标题
(activity as? MainActivity)?.updateWeekTitle("编程记录")
}
private fun setupRecyclerView() {
binding.rvCodeLogs.apply {
layoutManager = LinearLayoutManager(context)
adapter = codeLogAdapter
}
}
fun loadCodeLogs() {
if (!isAdded) return
lifecycleScope.launch {
try {
val userId = prefs.getUserId()
if (userId != null) {
try {
val response = codeLogService.getCodeLogs(userId)
if (!isAdded || _binding == null) return@launch
if (response.code == "200") {
response.data?.let { logs ->
if (logs.isNotEmpty()) {
// 只显示最新的一条记录
val latestLog = logs.maxByOrNull { it.date }
latestLog?.let {
codeLogAdapter.submitList(listOf(it))
binding.rvCodeLogs.visibility = View.VISIBLE
binding.tvEmptyData.visibility = View.GONE
} ?: showEmptyView()
} else {
showEmptyView()
}
} ?: showEmptyView()
} else {
showToast("获取数据失败: ${response.msg}")
showEmptyView()
}
} catch (e: Exception) {
if (!isAdded || _binding == null) return@launch
showToast("网络请求错误: ${e.message}")
showEmptyView()
}
} else {
if (!isAdded || _binding == null) return@launch
showToast("用户未登录")
showEmptyView()
}
} catch (e: Exception) {
if (!isAdded || _binding == null) return@launch
showToast("加载失败: ${e.message}")
showEmptyView()
}
}
}
private fun showEmptyView() {
binding.rvCodeLogs.visibility = View.GONE
binding.tvEmptyData.visibility = View.VISIBLE
}
private fun showToast(message: String) {
if (isAdded) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
}
// 获取当前日期的方法
fun getCurrentDate(): String {
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
return dateFormat.format(Date())
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
// 供MainActivity调用的添加方法
fun showAddCodeLogDialog() {
(activity as? MainActivity)?.showAddCodeLogDialog()
}
}
xml:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tvCurrentDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="当前日期: 2023-01-01"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="16dp" />
<EditText
android:id="@+id/etEstimate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="估计时间(小时)"
android:inputType="numberDecimal"
android:layout_marginBottom="8dp" />
<EditText
android:id="@+id/etAnalysis"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="需求分析/学习新技术内容"
android:inputType="textMultiLine"
android:minLines="2"
android:layout_marginBottom="8dp" />
<EditText
android:id="@+id/etCodingStandard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="采用的代码规范"
android:inputType="textMultiLine"
android:minLines="2"
android:layout_marginBottom="8dp" />
<EditText
android:id="@+id/etDesignDetails"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="具体设计内容"
android:inputType="textMultiLine"
android:minLines="2"
android:layout_marginBottom="8dp" />
<EditText
android:id="@+id/etCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="代码"
android:inputType="textMultiLine"
android:minLines="2"
android:layout_marginBottom="8dp" />
<EditText
android:id="@+id/etWorkloadMeasurement"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="工作量计算"
android:inputType="textMultiLine"
android:minLines="2"
android:layout_marginBottom="8dp" />
<EditText
android:id="@+id/etPostmortemAnalysis"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="事后总结"
android:inputType="textMultiLine"
android:minLines="2"
android:layout_marginBottom="8dp" />
<EditText
android:id="@+id/etImprovementPlan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="改进计划"
android:inputType="textMultiLine"
android:minLines="2"
android:layout_marginBottom="8dp" />
<EditText
android:id="@+id/etTotalHours"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="合计时间(小时)"
android:inputType="numberDecimal"
android:layout_marginBottom="8dp" />
</LinearLayout>
</ScrollView>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvCodeLogs"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvEmptyData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂无编程记录数据"
android:textSize="18sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/pink_500" />
<TextView
android:id="@+id/tvEstimate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp" />
<TextView
android:id="@+id/tvAnalysis"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp" />
<TextView
android:id="@+id/tvCodingStandard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp" />
<TextView
android:id="@+id/tvDesignDetails"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp" />
<TextView
android:id="@+id/tvCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp" />
<TextView
android:id="@+id/tvWorkloadMeasurement"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp" />
<TextView
android:id="@+id/tvPostmortemAnalysis"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp" />
<TextView
android:id="@+id/tvImprovementPlan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp" />
<TextView
android:id="@+id/tvTotalHours"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>

浙公网安备 33010602011771号