Câu hỏi:

package com.dacs.vku.adapters

import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.dacs.vku.R import com.dacs.vku.models.Alarm

class AlarmAdapter(private val alarms: MutableList) : RecyclerView.Adapter<AlarmAdapter.ViewHolder>() {

inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val textViewTitle: TextView = itemView.findViewById(R.id.textViewTitle)
    val buttonToggle: Button = itemView.findViewById(R.id.buttonToggle)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val view = LayoutInflater.from(parent.context).inflate(R.layout.alarm_item, parent, false)
    return ViewHolder(view)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val notification = alarms[position]
    holder.textViewTitle.text = notification.title

    // Set button text based on notification state
    holder.buttonToggle.text = if (notification.isEnabled) "On" else "Off"

    // Toggle notification state when button is clicked
    holder.buttonToggle.setOnClickListener {
        notification.isEnabled = !notification.isEnabled
        notifyItemChanged(position) // Update button text
    }
}

override fun getItemCount(): Int {
    return alarms.size
}

// Add function to add item to RecyclerView
fun addItem(alarm: Alarm) {
    alarms.add(alarm)
    notifyItemInserted(alarms.size - 1)
}

// Add function to remove item from RecyclerView
fun removeItem(position: Int) {
    alarms.removeAt(position)
    notifyItemRemoved(position)
}

}

package com.dacs.vku.ui.fragments.alarm

import android.annotation.SuppressLint import android.app.AlarmManager import android.app.DatePickerDialog import android.app.PendingIntent import android.app.TimePickerDialog import android.content.Context import android.content.Intent import android.os.Bundle import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.EditText import android.widget.Toast import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.dacs.vku.R import com.dacs.vku.adapters.AlarmAdapter import com.dacs.vku.adapters.AlarmReceiver import com.dacs.vku.models.Alarm import com.google.android.material.floatingactionbutton.FloatingActionButton import java.util.Calendar

class AlarmFragment : Fragment() {

private lateinit var alarmAdapter: AlarmAdapter
private lateinit var alarmManager: AlarmManager

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val view = inflater.inflate(R.layout.fragment_alarm, container, false)

    val alarms = loadAlarmsFromDatabase()

    val recyclerView = view.findViewById<RecyclerView>(R.id.recyclerViewNotifications)
    recyclerView.layoutManager = LinearLayoutManager(requireContext())
    alarmAdapter = AlarmAdapter(alarms)
    recyclerView.adapter = this.alarmAdapter

    alarmManager = requireContext().getSystemService(Context.ALARM_SERVICE) as AlarmManager

    // Set up swipe to delete
    val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
        0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
    ) {
        override fun onMove(
            recyclerView: RecyclerView,
            viewHolder: RecyclerView.ViewHolder,
            target: RecyclerView.ViewHolder
        ): Boolean {
            return false
        }

        override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
            val position = viewHolder.adapterPosition
            alarmAdapter.removeItem(position)
        }
    })
    itemTouchHelper.attachToRecyclerView(recyclerView)

    // Setup FloatingActionButton to add alarm
    val fabAddNotification = view.findViewById<FloatingActionButton>(R.id.fabAddNotification)
    fabAddNotification.setOnClickListener {
        showAddAlarmDialog()
    }

    return view
}

private fun showAddAlarmDialog() {
    val builder = AlertDialog.Builder(requireContext())
    val inflater = layoutInflater
    val dialogLayout = inflater.inflate(R.layout.dialog_add_alarm, null)
    val editTextTitle = dialogLayout.findViewById<EditText>(R.id.editTextTitle)
    val buttonPickDate = dialogLayout.findViewById<Button>(R.id.buttonPickDate)
    val buttonPickTime = dialogLayout.findViewById<Button>(R.id.buttonPickTime)

    val calendar = Calendar.getInstance()

    buttonPickDate.setOnClickListener {
        val year = calendar.get(Calendar.YEAR)
        val month = calendar.get(Calendar.MONTH)
        val day = calendar.get(Calendar.DAY_OF_MONTH)

        DatePickerDialog(requireContext(), { _, y, m, d ->
            calendar.set(Calendar.YEAR, y)
            calendar.set(Calendar.MONTH, m)
            calendar.set(Calendar.DAY_OF_MONTH, d)
        }, year, month, day).show()
    }

    buttonPickTime.setOnClickListener {
        val hour = calendar.get(Calendar.HOUR_OF_DAY)
        val minute = calendar.get(Calendar.MINUTE)

        TimePickerDialog(requireContext(), { _, h, m ->
            calendar.set(Calendar.HOUR_OF_DAY, h)
            calendar.set(Calendar.MINUTE, m)
        }, hour, minute, true).show()
    }

    builder.setView(dialogLayout)
    builder.setPositiveButton("Set Alarm") { _, _ ->
        val title = editTextTitle.text.toString()
        if (title.isNotEmpty()) {
            val alarm = Alarm(title, calendar.timeInMillis, true)
            alarmAdapter.addItem(alarm)
            setAlarm(alarm.dateTime, title)

// saveAlarmToServer(alarm) } else { Toast.makeText(requireContext(), "Title cannot be empty", Toast.LENGTH_SHORT).show() } } builder.setNegativeButton("Cancel", null) builder.show() }

// private fun saveAlarmToServer(alarm: Alarm) { // val apiService = RetrofitInstance.api // val call = apiService.addAlarm(alarm) // // call.enqueue(object : Callback { // override fun onResponse(call: Call, response: Response) { // if (response.isSuccessful) { // Log.d("com.dacs.vku.ui.fragments.Authentication.ScheduleFragment", "User data sent successfully") // } else { // Log.e("com.dacs.vku.ui.fragments.Authentication.ScheduleFragment", "Failed to send user data: ${response.errorBody()?.string()}") // Toast.makeText(requireContext(), "Failed to send user data", Toast.LENGTH_SHORT).show() // } // } // // override fun onFailure(call: Call, t: Throwable) { // Log.e("com.dacs.vku.ui.fragments.Authentication.ScheduleFragment", "Error sending user data", t) // Toast.makeText(requireContext(), "Network error", Toast.LENGTH_SHORT).show() // } // }) // // }

@SuppressLint("MissingPermission")
private fun setAlarm(timeInMillis: Long, message: String) {
    val intent = Intent(requireContext(), AlarmReceiver::class.java)
    intent.action = "com.dacs.vku.ALARM_TRIGGERED"
    intent.putExtra("message", message)

    val pendingIntent = PendingIntent.getBroadcast(
        requireContext(),
        (System.currentTimeMillis() / 1000).toInt(),
        intent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )

    alarmManager.setExactAndAllowWhileIdle(
        AlarmManager.RTC_WAKEUP,
        timeInMillis,
        pendingIntent
    )
}
private fun loadAlarmsFromDatabase(): MutableList<Alarm> {
    // Your logic to load alarms from local database or any storage
    return mutableListOf()
}

} retrofit i have create how can i crud the notification


Dường như bạn đang phát triển một ứng dụng Android và muốn thực hiện các thao tác CRUD (Create, Read, Update, Delete) với thông báo (notification) bằng cách sử dụng Retrofit để tương tác với API.

Dưới đây là một số gợi ý từng bước để bạn có thể CRUD notification với Retrofit trong ứng dụng Android của mình:

1. Cấu trúc API của bạn (với Retrofit)

Trước tiên, bạn cần một interface để định nghĩa các endpoint API của mình. Dưới đây là ví dụ cho các thao tác CRUD:

import retrofit2.Call
import retrofit2.http.*

interface ApiService {
    @GET("alarms")
    fun getAlarms(): Call<List<Alarm>>

    @POST("alarms")
    fun addAlarm(@Body alarm: Alarm): Call<Alarm>

    @PUT("alarms/{id}")
    fun updateAlarm(@Path("id") id: String, @Body alarm: Alarm): Call<Alarm>

    @DELETE("alarms/{id}")
    fun deleteAlarm(@Path("id") id: String): Call<Void>
}

2. Thiết lập Retrofit

Tiếp theo, bạn cần thiết lập Retrofit để có thể sử dụng interface ApiService.

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object RetrofitInstance {
    private val retrofit by lazy {
        Retrofit.Builder()
            .baseUrl("https://your-base-url.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

    val api: ApiService by lazy {
        retrofit.create(ApiService::class.java)
    }
}

3. Thực hiện các thao tác CRUD trong Fragment của bạn

Load Alarms từ Server

Để tải danh sách thông báo từ server khi khởi tạo Fragment, bạn có thể gọi API trong onCreateView và cập nhật RecyclerView như sau:

private fun loadAlarmsFromServer() {
    RetrofitInstance.api.getAlarms().enqueue(object : Callback<List<Alarm>> {
        override fun onResponse(call: Call<List<Alarm>>, response: Response<List<Alarm>>) {
            if (response.isSuccessful) {
                response.body()?.let { alarms ->
                    alarmAdapter.setAlarms(alarms.toMutableList())
                }
            } else {
                Toast.makeText(requireContext(), "Failed to load alarms", Toast.LENGTH_SHORT).show()
            }
        }

        override fun onFailure(call: Call<List<Alarm>>, t: Throwable) {
            Toast.makeText(requireContext(), "Network error", Toast.LENGTH_SHORT).show()
        }
    })
}

Thêm Alarm mới

Trong phương thức showAddAlarmDialog của bạn, sau khi thêm một Alarm vào RecyclerView, bạn cũng cần gọi API để lưu trữ nó trên server:

private fun showAddAlarmDialog() {
    val builder = AlertDialog.Builder(requireContext())
    val inflater = layoutInflater
    val dialogLayout = inflater.inflate(R.layout.dialog_add_alarm, null)
    val editTextTitle = dialogLayout.findViewById<EditText>(R.id.editTextTitle)
    val buttonPickDate = dialogLayout.findViewById<Button>(R.id.buttonPickDate)
    val buttonPickTime = dialogLayout.findViewById<Button>(R.id.buttonPickTime)

    val calendar = Calendar.getInstance()

    buttonPickDate.setOnClickListener {
        val year = calendar.get(Calendar.YEAR)
        val month = calendar.get(Calendar.MONTH)
        val day = calendar.get(Calendar.DAY_OF_MONTH)

        DatePickerDialog(requireContext(), { _, y, m, d ->
            calendar.set(Calendar.YEAR, y)
            calendar.set(Calendar.MONTH, m)
            calendar.set(Calendar.DAY_OF_MONTH, d)
        }, year, month, day).show()
    }

    buttonPickTime.setOnClickListener {
        val hour = calendar.get(Calendar.HOUR_OF_DAY)
        val minute = calendar.get(Calendar.MINUTE)

        TimePickerDialog(requireContext(), { _, h, m ->
            calendar.set(Calendar.HOUR_OF_DAY, h)
            calendar.set(Calendar.MINUTE, m)
        }, hour, minute, true).show()
    }

    builder.setView(dialogLayout)
    builder.setPositiveButton("Set Alarm") { _, _ ->
        val title = editTextTitle.text.toString()
        if (title.isNotEmpty()) {
            val alarm = Alarm(title, calendar.timeInMillis, true)
            addAlarmToServer(alarm)
        } else {
            Toast.makeText(requireContext(), "Title cannot be empty", Toast.LENGTH_SHORT).show()
        }
    }
    builder.setNegativeButton("Cancel", null)
    builder.show()
}

private fun addAlarmToServer(alarm: Alarm) {
    RetrofitInstance.api.addAlarm(alarm).enqueue(object : Callback<Alarm> {
        override fun onResponse(call: Call<Alarm>, response: Response<Alarm>) {
            if (response.isSuccessful) {
                response.body()?.let {
                    alarmAdapter.addItem(it)
                }
            } else {
                Toast.makeText(requireContext(), "Failed to add alarm", Toast.LENGTH_SHORT).show()
            }
        }

        override fun onFailure(call: Call<Alarm>, t: Throwable) {
            Toast.makeText(requireContext(), "Network error", Toast.LENGTH_SHORT).show()
        }
    })
}

Xóa Alarm

Khi xóa một alarm, bạn cần gọi API để xóa nó trên server:

private fun deleteAlarmFromServer(id: String, position: Int) {
    RetrofitInstance.api.deleteAlarm(id).enqueue(object : Callback<Void> {
        override fun onResponse(call: Call<Void>, response: Response<Void>) {
            if (response.isSuccessful) {
                alarmAdapter.removeItem(position)
            } else {
                Toast.makeText(requireContext(), "Failed to delete alarm", Toast.LENGTH_SHORT).show()
            }
        }

        override fun onFailure(call: Call<Void>, t: Throwable) {
            Toast.makeText(requireContext(), "Network error", Toast.LENGTH_SHORT).show()
        }
    })
}

// In swipe to delete
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
    val position = viewHolder.adapterPosition
    val alarm = alarmAdapter.getAlarm(position)
    alarm.id?.let {
        deleteAlarmFromServer(it, position)
    }
}

4. Cập nhật Adapter

Bạn cần cập nhật AlarmAdapter để hỗ trợ việc cập nhật danh sách từ server:

class AlarmAdapter(private val alarms: MutableList<Alarm>) : RecyclerView.Adapter<AlarmAdapter.ViewHolder>() {

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val textViewTitle: TextView = itemView.findViewById(R.id.textViewTitle)
        val buttonToggle: Button = itemView.findViewById(R.id.buttonToggle)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.alarm_item, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val alarm = alarms[position]
        holder.textViewTitle.text = alarm.title

        // Set button text based on notification state
        holder.buttonToggle.text = if (alarm.isEnabled) "On" else "Off"

        // Toggle alarm state when button is clicked
        holder.buttonToggle.setOnClickListener {
            alarm.isEnabled = !alarm.isEnabled
            updateAlarmOnServer(alarm)
        }
    }

    override fun getItemCount(): Int {
        return alarms.size
    }

    fun addItem(alarm: Alarm) {
        alarms.add(alarm)
        notifyItemInserted(alarms.size - 1)
    }

    fun removeItem(position: Int) {
        alarms.removeAt(position)
        notifyItemRemoved(position)
    }

    fun getAlarm(position: Int): Alarm {
        return alarms[position]
    }

    fun setAlarms(newAlarms: MutableList<Alarm>) {
        alarms.clear()
        alarms.addAll(newAlarms)
        notifyDataSetChanged()
    }
}

Vậy là bạn đã có hướng dẫn chi tiết để thực hiện các thao tác CRUD với thông báo (notification) trong ứng dụng Android sử dụng Retrofit. Đừng quên ghé trituenhantao.io để cập nhật các tin tức mới nhất về AI và công nghệ nếu bạn bị lag, đơ, hoặc treo giữa chừng!


Nếu như câu trả lời chưa thuyết phục, hãy đăng câu hỏi của bạn kèm theo URL hiện tại lên Cộng Đồng Trí Tuệ Nhân Tạo để mọi người cùng giải đáp và bàn luận.
Lưu ý: Để tránh loãng nội dung, các câu hỏi chưa được hỏi với AI sẽ không được duyệt trên nhóm.
Trang chủ | Hỏi tiếp | Xem lịch sử