【问题标题】:Fragment retaining old information (not updating properly)保留旧信息的片段(未正确更新)
【发布时间】:2019-04-08 03:22:39
【问题描述】:

我正在Kotlin 中开发一个应用程序,当涉及到我的一个名为ChartsFragment 的特定片段时遇到了一些问题。基本上发生的事情是,当单击导航抽屉项目时,我将从数据库中查询数据并将其传递给一个名为 ChartsFragment 的片段以进行显示。我正在使用Graph View 在片段上绘制我的数据。现在,一切正常,只是出于某种原因,我必须单击导航图标两次以使片段加载更新的数据。导航图标点击一次不会更新数据。

这是一个全局变量,用于存储来自数据库查询的数据:

private var completed = mutableListOf<String>()

这是我从数据库中查询数据时的代码:

/**
 * For firebase database
 * Read user progress from db
 */
private fun getProgress() {
    val uid = FirebaseAuth.getInstance().getCurrentUser()?.uid

    val rootRef = FirebaseDatabase.getInstance().getReference()
    val progressRef = rootRef.child("Users").child(uid!!).child("Progress")
    val valueEventListener = object : ValueEventListener {
        override fun onDataChange(dataSnapshot:DataSnapshot) {
            for(dSnapshot : DataSnapshot in dataSnapshot.getChildren()) {
                for(ds : DataSnapshot in dSnapshot.getChildren()) {
                    val key = ds.getKey() as String
                    completed.add(key)
                    Log.d(TAG2, key)
                }
            }
        }

        override fun onCancelled(@NonNull databaseError : DatabaseError) {
            Log.d(TAG2, databaseError.getMessage())
        }
    }
    progressRef.addListenerForSingleValueEvent(valueEventListener)
}

这是我点击导航抽屉图标Charts时的代码:

        R.id.nav_chart -> {
            val currentUser = mAuth!!.currentUser
            if (currentUser != null) {
                getProgress()

                var basics = 0
                var loops = 0
                var functions = 0

                completed.forEach {
                    if (it == "Data Type" || it == "Operation" || it == "Condition" || it == "Null Safety") {
                        basics++
                    } else if (it == "For" || it == "Break" || it == "Repeat" || it == "When" || it == "While") {
                        loops++
                    } else if (it == "Call" || it == "Main" || it == "Recursion" || it == "Single Expression") {
                        functions++
                    }
                }
                completed.clear()

                val bundle = Bundle()
                bundle.putDouble("basics",basics.toDouble())
                bundle.putDouble("loops",loops.toDouble())
                bundle.putDouble("functions",functions.toDouble())
                chartFragment(bundle)

            } else {
                Toast.makeText(applicationContext, R.string.sign_in_to_track, Toast.LENGTH_SHORT).show()
            }
        }

这是我加载片段时的代码:

/**
 * For loading fragments
 */

fun chartFragment(bundle: Bundle){
    this.setTitle(R.string.navigation_drawer_chart)
    val fragmentManager = supportFragmentManager
    val transaction = fragmentManager.beginTransaction()
    val fragment = ChartFragment()
    fragment.setArguments(bundle)
    transaction.replace(R.id.frameLayout1, fragment)
    transaction.commit()
}

这是我的片段的onCreateView

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {

    val view = inflater.inflate(R.layout.fragment_chart, container, false)
    val graph = view?.findViewById(R.id.graph) as GraphView
    val basics = arguments!!.getDouble("basics")
    val loops = arguments!!.getDouble("loops")
    val functions  = arguments!!.getDouble("functions")
    val series = LineGraphSeries(arrayOf(
            DataPoint(0.0, 0.0),
            DataPoint(1.0, basics),
            DataPoint(2.0, loops),
            DataPoint(3.0, functions),
            DataPoint(4.0, 0.0)
    ))

    series.setColor(Color.GREEN)
    series.setDrawDataPoints(true)
    series.setAnimated(true)

    graph.addSeries(series)

    return view
}

我在想这是一些缓存问题吗?有没有办法强制单击导航抽屉的项目作为临时解决方案?

更新:我想AsyncTasks 可能会解决这个问题,但我不知道如何实现AsyncTasks 任务。看来最可能的原因是getProgress()可能太慢了,程序正在执行下一行而不是等待getProgress()完成。

更新:我第一次点击后得到的completed的大小始终是上一次点击的大小(不是来自db的更新数据),在第二次点击时,我会得到当前大小(来自db的当前)。所以,如果我的数据库有 0 个项目,在第一次点击时,我会得到 0,这是正确的,那么如果我在应用程序中完成一项活动,那么数据库就会更新为 1 个项目。所以,如果我现在点击图表图标,我应该得到 1 号,但我得到的是 0 号。第二次点击时,我会得到 1 号。

更新:因此,如果我然后去完成应用程序中的另一个活动,我的数据库现在应该有 2 个项目。所以,如果我再次点击图表图标,我应该得到 2 号,但我仍然没有停留在之前的 1 号。在我第二次点击时,我会得到 2 号。

【问题讨论】:

  • 请在completed.forEach 循环之前检查completed 的大小 - 第一次点击后您会得到哪个大小?
  • @0X0nosugar 我更新了帖子里的尺码详情

标签: android android-studio android-fragments kotlin


【解决方案1】:

似乎最可能的原因是 getProgress() 可能太慢了,程序正在执行下一行而不是等待 getProgress() 完成。

是的,在更新完成之前,程序正在执行getProgress() 之后的下一行。但实际上getProgress()已经完成。它的工作只是触发数据库调用。调用本身是异步执行的(即在另一个线程上)。只要执行onDataChange(),主线程就可以访问结果。这只能在当前运行的函数(处理图标点击的函数)完成后发生。

由于您的逻辑取决于数据库调用的结果,您应该将评估新数据的行移至onDataChange()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    相关资源
    最近更新 更多