Android:重复执行功能,直到按下按钮

时间:2019-02-26 19:01:34

标签: android function kotlin repeat

因此,我希望每秒调用一次函数“ start()”,直到按下按钮为止。

该函数读取JSON文件并在GraphView库的帮助下通知绘图仪打印折线图。

我尝试了此操作,但应用程序不断崩溃:

private val timer = Timer("schedule", true)
timer.scheduleAtFixedRate(1000,1000)
{
   start()
}

Json Parser:连接到URL,提取json并从中提取数据。

object JsonParser {

var blueConeArray = arrayListOf<Cone>()
var yellowConeArray = arrayListOf<Cone>()

//Parse Json File extract Data and store them in DataWarehouse
fun parse(url: String) {

    getRequest(url, success = { response ->

        //create Parser
        val parser = Parser()
        val stringBuilder = StringBuilder(response)

        //Read Json File + get Data
        val jsonObject : JsonObject = parser.parse(stringBuilder) as JsonObject

        //Get Cones from JsonObject
        val blueCoordinates : JsonArray<JsonObject>? = jsonObject.array("BlueCoordinates")
        val yellowCoordinates : JsonArray<JsonObject>? = jsonObject.array("YellowCoordinates")

        //Store Blue Cones
        for(coordinate in blueCoordinates!!)
        {
            var x_blue = coordinate.double("x")
            var y_blue = coordinate.double("y")

            var blueCone =  BlueCone(x_blue!!, y_blue!!)
            blueConeArray.add(blueCone)
        }

        //Store Yellow Cones
        for(coordinate in yellowCoordinates!!)
        {
            var x_yellow = coordinate.double("x")
            var y_yellow = coordinate.double("y")
            var yellowCone = YellowCone(x_yellow!!, y_yellow!!)
            yellowConeArray.add(yellowCone)
        }

        //Store everything in Data Warehouse
       DataWarehouse.setValues(newEngineTemp = jsonObject.string("engineTemp"),
                                newSpeed = jsonObject.string("speed"),
                                newBlueCones = blueConeArray,
                                newYellowCones = yellowConeArray)
        blueConeArray.clear()
        yellowConeArray.clear()

    }, failure = { error ->
        println(error)
    })
}

//connect to URL pull Json File
private fun getRequest(url: String, success: (String) -> Unit, failure: (FuelError) -> Unit) {

    Fuel.get(url).responseString { request, response, result ->

        val (data, error) = result
        if (error != null) {
            Log.v("Error", error.toString())
            failure(error)
        } else {
            val onSuccess = data ?: return@responseString
            success(onSuccess)
        }
    }
}

}

DataWarehouse:存储来自Json Parser的数据并通知观察者

object DataWarehouse : Subject {

//List of Observers
private val MAXOBSERVER = 100
private var amountOfObservers = 0
private var observerList = arrayListOf<Observer>()

//Data from car
private var engineTemp: String? = ""
private var speed: String? = ""
private lateinit var blueCones : ArrayList<Cone>
private lateinit var yellowCones : ArrayList<Cone>

//register Observers + save them in Array
override fun registerObserver(DataObserver: Observer) {

    if (amountOfObservers < MAXOBSERVER) {
        observerList.add(DataObserver)
        amountOfObservers++
    }
}

//notify Observer from Array, that needs the new Value
override fun notifyObservers() {
    for (observer in observerList) {
        observer.update()
    }
}

//set values from parsed Jason File
fun setValues(newEngineTemp: String?, newSpeed: String? ,newBlueCones: ArrayList<Cone>, newYellowCones: ArrayList<Cone>) {

    //set new Values
    engineTemp = newEngineTemp
    speed = newSpeed
    blueCones = newBlueCones
    yellowCones = newYellowCones

    //notify all Observers
    notifyObservers()
}

//Return values to Observers
fun getEngineTemp(): String? {
    return engineTemp
}

fun getSpeed(): String? {
    return speed
}

fun getBlueCones(): ArrayList<Cone> {

    return blueCones
}

fun getYellowCones(): ArrayList<Cone> {

    return yellowCones
}

}

GraphView绘图仪:首先在(0/0)创建数据点,以便“ resetData()”起作用。

class Plotter(graphView: GraphView) : Observer {

private var graphView = graphView

private lateinit var sortedBlueCones: MutableList<Cone>
private lateinit var sortedYellowCones: MutableList<Cone>

private var blueConeArrayList = ArrayList<DataPoint>()
private var yellowConeArrayList = ArrayList<DataPoint>()

private var blueLines = LineGraphSeries<DataPoint>()
private var yellowLines = LineGraphSeries<DataPoint>()

private var blueIterator = 0
private var yellowIterator = 0

private var firstDraw = true

init {

    //First Values so resetData works
    yellowLines.appendData((DataPoint(0.toDouble(), 0.toDouble())), true, 1000)
    blueLines.appendData((DataPoint(0.toDouble(), 0.toDouble())), true, 1000)

    register()
}

//Register at Data Warehouse
override fun register() {
    DataWarehouse.registerObserver(this)
}

//Get new Cones from Data Warehouse and sort them by X Values
override fun update() {

    sortedBlueCones = DataWarehouse.getBlueCones().sortedWith(compareBy({ it.xCoordinate })) as MutableList<Cone>
    sortedYellowCones = DataWarehouse.getYellowCones().sortedWith(compareBy({ it.xCoordinate })) as MutableList<Cone>

    draw()
}

//Draw Line Graph and Point Graph
private fun draw() {

        //Blue Cones
        for (i in sortedBlueCones) {

            var x: Double = sortedBlueCones.get(blueIterator).xCoordinate
            var y: Double = sortedBlueCones.get(blueIterator).yCoordinate

            var dataPoint = DataPoint(x, y)
            blueConeArrayList.add(dataPoint)
            val blueConeArray = arrayOfNulls<DataPoint>(blueConeArrayList.size)
            blueConeArrayList.toArray(blueConeArray)

            blueLines.resetData(blueConeArray)

            blueIterator++
        }


        //Yellow Cones
        for (i in sortedYellowCones) {
            var x: Double = sortedYellowCones.get(yellowIterator).xCoordinate
            var y: Double = sortedYellowCones.get(yellowIterator).yCoordinate

            var dataPoint = DataPoint(x, y)
            yellowConeArrayList.add(dataPoint)
            val yellowConeArray = arrayOfNulls<DataPoint>(yellowConeArrayList.size)
            yellowConeArrayList.toArray(yellowConeArray)

            yellowLines.resetData(yellowConeArray)

            yellowIterator++
        }

    //Set Values of Lines
    blueLines.setColor(Color.BLUE)
    blueLines.setDrawDataPoints(true)
    blueLines.setDataPointsRadius(10.toFloat())

    yellowLines.setColor(Color.YELLOW)
    yellowLines.setDrawDataPoints(true)
    yellowLines.setDataPointsRadius(10.toFloat())

    //Draw
    graphView.addSeries(blueLines)
    graphView.addSeries(yellowLines)

    blueIterator = 0
    yellowIterator = 0
}

}

错误堆栈:它看起来像是graphView的问题,但是当我使用Button手动触发该函数时,它工作得很好。每当我在计时器中包装“ start()”或“ readJson()”时,应用程序就会崩溃。

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.tobias.infinity_racing_driverless, PID: 16341
java.lang.IllegalArgumentException: The order of the values is not correct. X-Values have to be ordered ASC. First the lowest x value and at least the highest x value.
    at com.jjoe64.graphview.series.BaseSeries.checkValueOrder(BaseSeries.java:532)
    at com.jjoe64.graphview.series.BaseSeries.resetData(BaseSeries.java:412)
    at com.example.tobias.infinity_racing_driverless.Plotter.draw(Plotter.kt:69)
    at com.example.tobias.infinity_racing_driverless.Plotter.update(Plotter.kt:52)
    at com.example.tobias.infinity_racing_driverless.DataWarehouse.notifyObservers(DataWarehouse.kt:32)
    at com.example.tobias.infinity_racing_driverless.DataWarehouse.setValues(DataWarehouse.kt:46)
    at com.example.tobias.infinity_racing_driverless.JsonParser$parse$1.invoke(JsonParser.kt:55)
    at com.example.tobias.infinity_racing_driverless.JsonParser$parse$1.invoke(JsonParser.kt:14)
    at com.example.tobias.infinity_racing_driverless.JsonParser$getRequest$1.invoke(JsonParser.kt:78)
    at com.example.tobias.infinity_racing_driverless.JsonParser$getRequest$1.invoke(JsonParser.kt:14)
    at com.github.kittinunf.fuel.core.DeserializableKt$response$1.invoke(Deserializable.kt:105)
    at com.github.kittinunf.fuel.core.DeserializableKt$response$1.invoke(Unknown Source:4)
    at com.github.kittinunf.fuel.core.DeserializableKt$response$asyncRequest$1$1.invoke(Deserializable.kt:192)
    at com.github.kittinunf.fuel.core.DeserializableKt$response$asyncRequest$1$1.invoke(Unknown Source:0)
    at com.github.kittinunf.fuel.core.RequestExecutionOptionsKt$sam$java_lang_Runnable$0.run(Unknown Source:2)
    at android.os.Handler.handleCallback(Handler.java:789)
    at android.os.Handler.dispatchMessage(Handler.java:98)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6541)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

1 个答案:

答案 0 :(得分:0)

1)计时器在工作线程上调度任务。我猜是因为 start()函数正在更新工作线程上的GraphView(UI)而发生错误。因此,请尝试将start函数包装在UI / Main处理程序中,如下所示。

private val timer = Timer("schedule", true)
timer.scheduleAtFixedRate(1000,1000)
{
  Handler(Looper.getMainLooper()).post {
            start()
        }
}

2)但是,如果再次花时间读取json文件,最好只将Grapview更新代码包装在Handler中,而不是整个start()函数。因此, start()函数中的代码必须像下面的

fun start()
{
    // your code to read the json file

    // wrap the notify grapview plotter inside Handler
    Handler(Looper.getMainLooper()).post {
        // code to notify Grapview plotter 
    }
}
相关问题