Strohhut
Strohhut

Reputation: 542

Android: Application my be doing too much work on its main thread

So I get this error even when Debugging on a Connected Device.

My App reads a JSON File via an HTTP connection stores it and notifies all Observers to get their new data. One of the Observers is a Plotter using the grapView Lib.

As I searched for some Solutions I ended up to implement the JSON Parser as an AsyncTask.

But the Same error still occurs.

My Question now is: What else can I do so Main Thread blocked?

Main:

class MainScreen : AppCompatActivity() {

//define variables
private lateinit var start: Button

private lateinit var graphView: GraphView

private lateinit var engineTempText: TextView
private lateinit var speedText: TextView

private val timer = Timer("schedule", true)

private var started = false

//find GUI fields/buttons
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main_screen)

    start = findViewById(R.id.startButton)

    graphView = findViewById(R.id.graphView)

    engineTempText = findViewById(R.id.engineTempText)
    speedText = findViewById(R.id.speedText)

    //Register Observers at DataWarehouse
    val engineTempObserver = EngineTempObserver(engineTempText)
    val speedObserver = SpeedObserver(speedText)
    val plotter = Plotter(graphView)

    //Wait till Button is pressed to start
    start.setOnClickListener(View.OnClickListener {

        //end
        if (started) {
            timer.cancel()
            timer.purge()
            started = false
        }

        //start
        else {
            started = true

            val timer = Timer("schedule", true)
            timer.scheduleAtFixedRate(500,500) {

                Handler(Looper.getMainLooper()).post {
                    //Start
                    start()
                }
            }
        }

    })
}

//start monitoring
private fun start() {
    val jsonParser = JsonParser()
    jsonParser.execute()
}

}

JSON Parser:

class JsonParser : AsyncTask<Void, Void, JsonObject>() {

//connect to URL get Json File Data
override fun doInBackground(vararg params: Void): JsonObject {

    val response = URL("https://api.myjson.com/bins/14oooa").readText()
    //http://10.0.2.2:80/test.json

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

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

    return jsonObject

}

//Parse Json File extract Data and store them in DataWarehouse
override fun onPostExecute(jsonObject: JsonObject) {

    //Arrays to Store Coordinates saved in Cone class
    val blueConeArray = arrayListOf<Cone>()
    val yellowConeArray = arrayListOf<Cone>()


    //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!!) {
        val x_blue = coordinate.double("x")
        val y_blue = coordinate.double("y")

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

    //Store Yellow Cones
    for (coordinate in yellowCoordinates!!) {
        val x_yellow = coordinate.double("x")
        val y_yellow = coordinate.double("y")
        val 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()

}

}

Plotter:

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

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

    blueConeArrayList.clear()
    yellowConeArrayList.clear()
}

}

Upvotes: 0

Views: 104

Answers (1)

Andres S
Andres S

Reputation: 471

onPostExecute(jsonObject: JsonObject) is called on the main thread, it looks like you're doing a lot of work there (for loops and db saving). Try to do that in the background and then return only what needs to be done in the main thread.

Other than that those errors (which are actually warnings) can mostly be ignored, especially if working on an older phone or an emulator. If it doesn't actually cause any visible lag you should be fine as long as the lag time isn't major and constantly happening.

Upvotes: 1

Related Questions