因此,我的应用程序从JSON文件读取数据,并将其存储在名为“ DataWarehouse”的类中,并通知所有观察者获取新数据。
观察者之一是使用graphView lib的绘图仪。画线。由于新坐标的排序和计算需要花费大量时间,因此我在线程“ CalcCoordinatesThread”中进行了此操作。 但是我收到一条错误消息,并且该线程甚至没有运行。
这是我第一次在Android中使用Threads,我真的不知道自己在做什么错,我已经花了将近一天的时间。非常感谢您的帮助。
谢谢。
堆栈跟踪:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.tobias.infinity_racing_driverless, PID: 13911
java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:724)
at com.example.tobias.infinity_racing_driverless.PlotterRunnable.start(PlotterRunnable.kt:49)
at com.example.tobias.infinity_racing_driverless.PlotterRunnable.update(PlotterRunnable.kt:37)
at com.example.tobias.infinity_racing_driverless.DataWarehouse.notifyObservers(DataWarehouse.kt:34)
at com.example.tobias.infinity_racing_driverless.DataWarehouse.setValues(DataWarehouse.kt:54)
at com.example.tobias.infinity_racing_driverless.JsonParser.onPostExecute(JsonParser.kt:58)
at com.example.tobias.infinity_racing_driverless.JsonParser.onPostExecute(JsonParser.kt:12)
at android.os.AsyncTask.finish(AsyncTask.java:695)
at android.os.AsyncTask.-wrap1(Unknown Source:0)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
at android.os.Handler.dispatchMessage(Handler.java:105)
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)
CalcCoordinatesThread:
class CalcCoordinatesThread(private var uiHandler: MainScreen.UiHandler) : HandlerThread("CalcCoordinatesThread") {
private var handler: Handler? = null
//calc blue Cones
private fun calcBlueLines(blueCones: ArrayList<Cone>): LineGraphSeries<DataPoint> {
var blueLines = LineGraphSeries<DataPoint>()
var blueConeArrayList = ArrayList<DataPoint>()
var blueIterator = 0
val sortedBlueCones = blueCones.sortedWith(compareBy({ it.xCoordinate })) as MutableList<Cone>
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++
}
blueConeArrayList.clear()
return blueLines
}
//calc yellow Cones
private fun calcYellowLines(yellowCones: ArrayList<Cone>): LineGraphSeries<DataPoint> {
var yellowLines = LineGraphSeries<DataPoint>()
var yellowConeArrayList = ArrayList<DataPoint>()
var yellowIterator = 0
val sortedYellowCones = yellowCones.sortedWith(compareBy({ it.xCoordinate })) as MutableList<Cone>
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++
}
yellowConeArrayList.clear()
return yellowLines
}
//Handler gets and sends new Messages
private fun getHandler(looper: Looper): Handler {
return object : Handler(looper) {
override fun handleMessage(msg: Message?) {
super.handleMessage(msg)
//get Message with coordinates of Cones
val coordinates = msg?.obj as Array<ArrayList<Cone>>
//calc Lines
var blueLines = calcBlueLines(coordinates[0])
var yellowLines = calcYellowLines(coordinates[1])
//Send Message of new LineSeries
val lineMessage = Message()
lineMessage.obj = arrayOf<LineGraphSeries<DataPoint>>(blueLines, yellowLines)
uiHandler.sendMessage(lineMessage)
}
}
}
//Handler gets Message with new coordinates of Cones
fun sendCoordinates(coordinates: Array<ArrayList<Cone>>) {
val message = Message()
message.obj = coordinates
handler?.sendMessage(message)
}
//start looper
override fun onLooperPrepared() {
super.onLooperPrepared()
handler = getHandler(looper)
}
}
绘图仪:
class PlotterRunnable(private var calcCoordinatesThread: CalcCoordinatesThread) : Observer, Runnable {
private var thread: Thread = Thread(this)
var blueLines = LineGraphSeries<DataPoint>()
var yellowLines = LineGraphSeries<DataPoint>()
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() {
if(!thread.isAlive)
{
start()
run()
}
}
override fun run() {
val coordinateArray = arrayOf<ArrayList<Cone>>(DataWarehouse.blueConesList, DataWarehouse.yellowConesList)
calcCoordinatesThread.sendCoordinates(coordinateArray)
}
fun start(){
thread.start()
}
}
主要:
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
private lateinit var plotter: PlotterRunnable
private lateinit var uiHandler: UiHandler
private lateinit var calcCoordinatesThread: CalcCoordinatesThread
private lateinit var engineTempObserver: EngineTempObserver
private lateinit var speedObserver: SpeedObserver
//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
engineTempObserver = EngineTempObserver(engineTempText)
speedObserver = SpeedObserver(speedText)
uiHandler = UiHandler(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
start()
}
})
}
//start monitoring
private fun start() {
calcCoordinatesThread = CalcCoordinatesThread(uiHandler)
plotter = PlotterRunnable(calcCoordinatesThread)
val timer = Timer("schedule", true)
timer.scheduleAtFixedRate(500, 500) {
//Start
if (started) {
val jsonParser = JsonParser()
jsonParser.execute()
}
}
}
override fun onDestroy() {
super.onDestroy()
calcCoordinatesThread.quit()
}
class UiHandler(var graphView: GraphView) : Handler() {
override fun handleMessage(msg: Message?) {
super.handleMessage(msg)
var lines = msg?.obj as Array<LineGraphSeries<DataPoint>>
var blueLine = lines[0]
var yellowLine = lines[1]
graphView.addSeries(blueLine)
graphView.addSeries(yellowLine)
}
}
}