【问题标题】:Firebase not getting data from onDataChange methodFirebase 没有从 onDataChange 方法获取数据
【发布时间】:2017-06-28 19:52:23
【问题描述】:

我了解 Firebase 异步获取数据,我正在尝试在数据加载到我的 recyclerView 适配器之前设置数据,以便它显示在 recyclerview 中。但是当我启动应用程序时,它只获得了我最初设置的“EMPTY”字符串,而且似乎 firebase 甚至没有进入 onDataChange 方法

CoursesFragment.kt

class CoursesFragment : android.support.v4.app.Fragment(), Contract.View {
    val TAG: String = CoursesFragment::class.java.name
    val presenter: Contract.Presenter.CoursePresenter = CoursePresenter(this)
    var tempDataList: MutableList<String> = mutableListOf()
    var dataArray: Array<String> = arrayOf("EMPTY")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        tempDataList = presenter.retrieveCourseNames()
        for (i in 0 until tempDataList.size) dataArray[i] = tempDataList[i]
    }

    override fun onCreateView(inflater: android.view.LayoutInflater?, container: android.view.ViewGroup?,
                              savedInstanceState: Bundle?): android.view.View? {
        // Inflate the layout for this fragment
        val v = inflater!!.inflate(R.layout.fragment_courses, container, false)

//        Gets cardview widget and sets property
        val rView = v.findViewById<RecyclerView>(R.id.recyclerView_courses)
        rView.setHasFixedSize(true)

//        Creates the 2 column recycler view with the cards
        val layoutMan = GridLayoutManager(context, 1)
        rView.layoutManager = layoutMan
        //        Sets up cardview in recycler view

        val adapter = CourseRecyclerAdapter(dataArray, presenter)
        adapter.notifyDataSetChanged()
        rView.adapter = adapter

//        actually inflates view
        return v
    }

    //    ======================== INTERFACE OVERRIDE METHODS ========================

    //    CourseContract
    override fun showToastMessage(message: String) {
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
    }

    //    ======================== USER METHODS ========================
//    New Instance Method
    companion object {
        fun newInstance(page: Int = 0): CoursesFragment {
            val argPage: String = "ARG_PAGE"
            val args: Bundle = Bundle()
            args.putInt(argPage, page)
            val fragment = CoursesFragment()
            fragment.arguments = args
            return fragment
        }
    }
}

CoursePresenter.kt

class CoursePresenter(val courseView: Contract.View) : Contract.Presenter.CoursePresenter {
    val courseInstance = com.alexoladele.cvap.MVP.Course.Model.Course()
    override fun retrieveCourseNames(): MutableList<String> {
        val returnList: MutableList<String> = mutableListOf()
        courseInstance.getCourseNamesFromDB(object : MyCallBack{
            override fun doCallback(dbValue: String) {
                returnList.add(dbValue)
            }
        })
        return returnList
    }

    fun testToast() {
        courseView.showToastMessage("TOAST TEST")
    }
    override fun onCourseClick(cardPosition: Int) {
        testToast()
    }
}

Course.kt

class Course (val name: String = "GENERIC", val content: String = "PLACEHOLDER") : Contract.Model.CourseModel {
    val dbReference: DatabaseReference = FirebaseDatabase.getInstance().reference
    val courseRef = dbReference.child("Course")
    val courseNames = mutableListOf<String>()

    override fun getCourseNamesFromDB(callback: MyCallBack) {
        courseRef.addValueEventListener(object : ValueEventListener {
            override fun onCancelled(p0: DatabaseError?) {
//                TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
            }

            override fun onDataChange(p0: DataSnapshot) {
                val tempString = p0.value as String
                Log.d(TAG, "onDataChange: Value from DB is: $tempString");

                callback.doCallback(tempString)
            }
        })
    }
}
interface MyCallBack {
    fun doCallback(dbValue: String)
}

编辑:我已经在 CoursePresenter 中尝试过了

override fun retrieveCourseNames(dataArray: Array<String>): Array<String> {
//        val returnList: MutableList<String> = mutableListOf()
        courseInstance.getCourseNamesFromDB(object : MyCallBack{
            override fun doCallback(dbValue: String) {
                val returnList = mutableListOf<String>()
                returnList.add(dbValue)
                for (i in 0 until returnList.size)
                     dataArray[i] = returnList[i]
            }
        })

        return dataArray
    }

【问题讨论】:

    标签: android firebase firebase-realtime-database kotlin android-mvp


    【解决方案1】:

    我通过完全取消回调来修复它!我在 onDataChange() 方法中设置了 recyclerView 适配器,因此我没有在获取数据之前设置布局,这可能会导致它加载有点慢并且可能违反 MVP,但它可以工作!!!

    【讨论】:

    • 在后台线程中设置适配器并不是一个好主意,因为您会收到诸如No Adapter attached :skipping layout 之类的警告。除此之外,这个答案根本没有解决问题的异步部分。
    • 请查看我编辑的答案中的链接。
    【解决方案2】:

    要解决这个问题,您需要在 CoursePresenter.kt 文件中的覆盖 doCallback 函数中声明并使用 val returnList。这样就不会得到空字符串,因为您等待它才能使用它。

    更多信息,您可以从以下帖子中查看我的答案:

    【讨论】:

    • 那么我将如何在该函数中返回 returnList?
    • 无论你想用它做什么,只要在那个函数中使用它。
    • 对不起,我只是想澄清一下。所以 returnList 从我传递给 CourseFragment 中的 dataArray 以传递给适配器的数据库中返回可变的项目列表。你是说我应该把它传递给这个函数中的dataArray变量吗?
    • 是的,试一试。
    • 我试过这样做,但在创建视图之前它仍然没有从数据库中获取值。见主帖中的编辑
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多