Firebase данные меняются навсегда - PullRequest
0 голосов
/ 01 февраля 2020

я новичок в создании приложения и попытке создать приложение со списком задач, используя android studio, firebase и kotlin. В MainActivity я показываю список задач, которые хранятся в пожарной базе. затем есть кнопка, чтобы добавить новое задание и сохранить его в базе данных. если я щелкну на задаче в MainActivity, приложение перейдет в EditTaskActivity, который содержит некоторый элемент EditText, и если пользователь заполнит этот EditText, а затем нажмет кнопку «Сохранить изменение» в EditTaskActivity, оно должно сохранить изменения данных в базе данных Firebase. Но проблема в том, что когда я нажимаю кнопку «Сохранить изменение», данные в базе данных постоянно меняются между старыми и новыми данными, и приложение перестает работать.

Это моя основная деятельность код:

class MainActivity : AppCompatActivity() {

    private lateinit var titlePage: TextView
    private lateinit var subtitlePage: TextView
    private lateinit var endPage: TextView
    private lateinit var rvTasks: RecyclerView
    private var list: ArrayList<Task> = arrayListOf()
    private lateinit var reference: DatabaseReference
    private lateinit var btnAddNew: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        titlePage=findViewById(R.id.title_page)
        subtitlePage=findViewById(R.id.subtitle_page)
        endPage=findViewById(R.id.end_page)

        btnAddNew=findViewById(R.id.btn_addnew)

        rvTasks = findViewById(R.id.rv_taskList)
        rvTasks.setHasFixedSize(true)
        rvTasks.layoutManager = LinearLayoutManager(this)
        reference = FirebaseDatabase.getInstance().reference.child("TaskListApp")
        reference.addValueEventListener( object: ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot){
                for(dataSnapshot1 in dataSnapshot.children){
                    var task: Task? = dataSnapshot1.getValue<Task>(Task::class.java)
                    if (task != null) {
                        list.add(task)
                    }
                }
                val taskAdapter = TaskAdapter(list,assets)
                rvTasks.adapter = taskAdapter
                taskAdapter.notifyDataSetChanged()
            }
            override fun onCancelled(databaseError: DatabaseError){
                Toast.makeText(applicationContext, "No Data", Toast.LENGTH_SHORT).show()
            }
        } )

        btnAddNew.setOnClickListener { v ->
            if(v.id == R.id.btn_addnew){
                val moveToAddNew = Intent(this@MainActivity, AddNewTask::class.java)
                startActivity(moveToAddNew)
            }
        }
    }

}

Это мой код TaskAdapter:

class TaskAdapter(private val taskList: ArrayList<Task>, assets: AssetManager): RecyclerView.Adapter<TaskAdapter.ListViewHolder>() {

    lateinit var someContext: Context

    inner class ListViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
        var taskTitle: TextView = itemView.findViewById(R.id.task_title)
        var taskDesc: TextView = itemView.findViewById(R.id.task_desc)
        var taskDate: TextView = itemView.findViewById(R.id.task_date)
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
        val view: View = LayoutInflater.from(parent.context).inflate(R.layout.item_tasks, parent, false)
        someContext = parent.context
        return ListViewHolder(view)
    }

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

    override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
        val task = taskList[position]

        holder.taskTitle.text = task.taskTitle
        holder.taskDesc.text = task.taskDesc
        holder.taskDate.text = task.taskDate
        holder.itemView.setOnClickListener {
            val moveToEdit = Intent(someContext, EditTask::class.java)
            moveToEdit.putExtra("tasktitle", task.taskTitle)
            moveToEdit.putExtra("taskdesc", task.taskDesc)
            moveToEdit.putExtra("taskdate", task.taskDate)
            moveToEdit.putExtra("taskkey", task.taskKey)
            someContext.startActivity(moveToEdit)
        }

    }
}

, и это мой код EditTaskActivity:

class EditTask : AppCompatActivity() {

    private lateinit var pageTitle: TextView
    private lateinit var addNewTaskTitle: TextView
    private lateinit var inputTaskTitle: EditText
    private lateinit var addNewTaskDesc: TextView
    private lateinit var inputNewTaskDesc: EditText
    private lateinit var addNewTaskDueDate: TextView
    private lateinit var inputNewTaskDueDate: EditText

    private lateinit var btnSaveChange: Button
    private lateinit var btnDeleteTask: Button
    private lateinit var btnCancel: Button

    private lateinit var reference: DatabaseReference
    private lateinit var taskKey: String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_edit_task)
        taskKey = intent?.getStringExtra("taskkey").toString()
        pageTitle=findViewById(R.id.add_new_task_title_page)
        pageTitle.typeface=CircularBlack

        addNewTaskTitle=findViewById(R.id.new_task_title)
        addNewTaskTitle.typeface=CircularMedium

        inputTaskTitle=findViewById(R.id.add_task_title)
        inputTaskTitle.typeface=CircularBook
        inputTaskTitle.setText(intent.getStringExtra("tasktitle"))

        addNewTaskDesc=findViewById(R.id.new_task_desc)
        addNewTaskDesc.typeface=CircularMedium

        inputNewTaskDesc=findViewById(R.id.add_task_desc)
        inputNewTaskDesc.typeface=CircularBook
        inputNewTaskDesc.setText(intent.getStringExtra("taskdesc"))

        addNewTaskDueDate=findViewById(R.id.new_task_time)
        addNewTaskDueDate.typeface=CircularMedium

        inputNewTaskDueDate=findViewById(R.id.add_task_time)
        inputNewTaskDueDate.setText(intent.getStringExtra("taskdate"))

        reference = FirebaseDatabase.getInstance().reference.child("TaskListApp").child("Task$taskKey")

        btnSaveChange=findViewById(R.id.btn_save_change)
        btnSaveChange.setOnClickListener{ v ->
            if(v.id==R.id.btn_save_change) {
                reference.addValueEventListener(object : ValueEventListener {
                    override fun onDataChange(dataSnapshot: DataSnapshot) {
                        dataSnapshot.ref.child("taskTitle").setValue(inputTaskTitle.text.toString())
                        dataSnapshot.ref.child("taskDesc").setValue(inputNewTaskDesc.text.toString())
                        dataSnapshot.ref.child("taskDate").setValue(inputNewTaskDueDate.text.toString())
                        startActivity(Intent(this@EditTask, MainActivity::class.java))
                    }

                    override fun onCancelled(databaseError: DatabaseError) {
                        Toast.makeText(
                            applicationContext,
                            "Action Cancelled, Error Occured",
                            Toast.LENGTH_SHORT
                        ).show()
                        startActivity(Intent(this@EditTask, MainActivity::class.java))
                    }
                })
            }
        }
        btnDeleteTask=findViewById(R.id.btn_delete_task)
        btnDeleteTask.setOnClickListener{v ->
            if(v.id==R.id.btn_delete_task){

                reference.removeValue().addOnCompleteListener {
                    if(it.isSuccessful){
                        startActivity(Intent(this@EditTask, MainActivity::class.java))
                    } else {
                        Toast.makeText(applicationContext, "Failed to delete task", Toast.LENGTH_SHORT).show()
                    }
                }

            }
        }

        btnCancel=findViewById(R.id.btn_cancel_edit)
        btnCancel.setOnClickListener{ v ->
            if(v.id == R.id.btn_cancel_edit) {
                startActivity(Intent(this@EditTask, MainActivity::class.java))
            }
        }
    }
}

, а это мой код активности AddNewTask:

class AddNewTask : AppCompatActivity(), View.OnClickListener {

    private lateinit var pageTitle: TextView
    private lateinit var addNewTaskTitle: TextView
    private lateinit var inputTaskTitle: EditText
    private lateinit var addNewTaskDesc: TextView
    private lateinit var inputNewTaskDesc: EditText
    private lateinit var addNewTaskDueDate: TextView
    private lateinit var inputNewTaskDueDate: EditText
    private lateinit var btnCreateTask: Button
    private lateinit var btnCancel: Button

    private lateinit var reference: DatabaseReference
    var taskNum: Int = Random.nextInt()

    private var taskKey: String = taskNum.toString()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_add_new_task)
        pageTitle=findViewById(R.id.add_new_task_title_page)
        pageTitle.typeface=CircularBlack

        addNewTaskTitle=findViewById(R.id.new_task_title)
        inputTaskTitle=findViewById(R.id.add_task_title)
        addNewTaskDesc=findViewById(R.id.new_task_desc)
        inputNewTaskDesc=findViewById(R.id.add_task_desc)
        addNewTaskDueDate=findViewById(R.id.new_task_time)
        inputNewTaskDueDate=findViewById(R.id.add_task_time)

        btnCreateTask=findViewById(R.id.btn_save_task)
        btnCreateTask.setOnClickListener(this)
        btnCancel=findViewById(R.id.btn_cancel)
        btnCancel.setOnClickListener(this)
    }

    override fun onClick(v: View) {
        when(v.id){
            R.id.btn_save_task -> {
                reference = FirebaseDatabase.getInstance().reference.child("TaskListApp").
                        child("Task$taskNum")
                reference.addValueEventListener(object: ValueEventListener{
                    override fun onDataChange(dataSnapshot: DataSnapshot) {
                        dataSnapshot.ref.child("taskTitle").setValue(inputTaskTitle.text.toString())
                        dataSnapshot.ref.child("taskDesc").setValue(inputNewTaskDesc.text.toString())
                        dataSnapshot.ref.child("taskDate").setValue(inputNewTaskDueDate.text.toString())
                        dataSnapshot.ref.child("taskKey").setValue(taskKey)
                        startActivity(Intent(this@AddNewTask, MainActivity::class.java))
                    }

                    override fun onCancelled(databaseError: DatabaseError) {
                        Toast.makeText(applicationContext, "Action Cancelled", Toast.LENGTH_SHORT).show()
                        startActivity(Intent(this@AddNewTask, MainActivity::class.java))
                    }
                })
            }
            R.id.btn_cancel -> {
                startActivity(Intent(this@AddNewTask, MainActivity::class.java))
            }
        }
    }
}

Ответы [ 2 ]

1 голос
/ 01 февраля 2020

Попробуйте использовать прослушиватель событий с одним значением вместо прослушиватель событий со значением

Использовать

reference.addListenerForSingleValueEvent

вместо

reference.addValueEventListener

Поскольку слушатель события значения равен , все время вызывайте , когда данные превращаются в дочерний объект Firebase, но слушатель события с одним значением является , вызывается только один раз . Так что, возможно, это сгенерировало проблему для вас.

0 голосов
/ 01 февраля 2020

вы можете использовать ChildEventListener также с ValueEventListener.

Слушатель значения будет запускать метод каждый раз, когда данные изменяются в БД, и возвращать все данные

ChildEventListener также будет запускать метод каждый раз, когда когда данные изменяются в БД, но возвращается элемент, который изменяется.

ChildEventListener listener= new ChildEventListener(){

    onCancelled(DatabaseError error) {
    // This method will be triggered in the event that this listener either failed at the server, or is removed as a result of the security and Firebase rules.
    }

    onChildAdded(DataSnapshot snapshot, String previousChildName){
     // triggered when a new child is added to the location to which this listener was added.

    //check and add new item to your adapter here
    }

    onChildChanged(DataSnapshot snapshot, String previousChildName){
     //  triggered when the data at a child location has changed.
    }

    onChildMoved(DataSnapshot snapshot, String previousChildName) {
    // triggered when a child location's priority changes.
    }

    onChildRemoved(DataSnapshot snapshot) {
    // triggered when a child is removed from the location to which this listener was added.
    }
}

Затем удалите ваш слушатель значения после прочтения всех элементов и добавьте дочерний слушатель, чтобы наблюдать за новыми элементами и изменениями

   reference.addValueEventListener( object: ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot){
            for(dataSnapshot1 in dataSnapshot.children){
                var task: Task? = dataSnapshot1.getValue<Task>(Task::class.java)
                if (task != null) {
                    list.add(task)
                }
            }
            val taskAdapter = TaskAdapter(list,assets)
            rvTasks.adapter = taskAdapter
            taskAdapter.notifyDataSetChanged()
            reference.removeListener(this);
            reference.addValueEventListener(listener);
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...