我在大学项目中遇到问题,我需要在Android设备上显示来自arduino的实时读数。 arduino和蓝牙链接工作正常。在android方面,我启动一个新线程来检索这些值并将它们添加到arraylist FullSignal。
private synchronized void theloop(){
AsyncTask.execute(new Runnable() {
@Override
public void run() {
try
{
while(btSocket.isConnected() ){
if(!pause) {
BufferedReader r = new BufferedReader(new InputStreamReader(btSocket.getInputStream()));
String total = "";
String line;
if ((line = r.readLine()) != null) {
total = (line);
}
if (!total.equals("")) {
double xtoadd = ((new Date().getTime()) - startOfRun) / 1000;
DataPoint dp = new DataPoint(xtoadd, Double.parseDouble(total));
FullSignal.add(dp);
sleep(10);
}
}
else{
sleep(10);
这个线程正在做我想要的事情并将读数放入arraylist(它们到达的时间和值)。然后我有另一个每50ms调用一次Update_Graph方法的线程,并传入当前的FullSignal arraylist。
private synchronized void Update_Graph_loop() {
Thread thread = new Thread()
{
@Override
public void run() {
try {
while(!ending) {
if(!pause){
Update_Graph(FullSignal);
sleep(50);
}
else{
sleep(50);
}
}
} catch (InterruptedException e) {
Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
};
thread.start();
}
它调用的Update_Graph会做一些数学运算,让图表显示从arduino读取的值以及它们何时到达。
private synchronized void Update_Graph(ArrayList<DataPoint> FS)
{
graph = (GraphView) findViewById(R.id.graph);
series = new LineGraphSeries<DataPoint>();
for (int i = dpToDisp.length - 1; i >= 0; i--) {
DataPoint dp = FS.get(FS.size() - (dpToDisp.length - i));
dpToDisp[i] = new DataPoint(((dp.getX() * 1000 + startOfRun) - (new Date().getTime())) / 1000, dp.getY());
}
series.resetData(dpToDisp);
series.setThickness(20);
series.setColor(Color.RED);
graph.removeAllSeries();
graph.addSeries(series);
}
应用程序的行为与我想要的一段时间(通常在5 - 25秒之间)然后崩溃。 Screenshot of app running before crash
控制台显示Null Object Reference错误,但没有显示导致它的代码行。
E/AndroidRuntime: FATAL EXCEPTION: main
Process: app.stephen.com.samsungs2test, PID: 28668
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
at com.jjoe64.graphview.GridLabelRenderer.drawVerticalSteps(GridLabelRenderer.java:1302)
at com.jjoe64.graphview.GridLabelRenderer.draw(GridLabelRenderer.java:1071)
at com.jjoe64.graphview.GraphView.drawGraphElements(GraphView.java:299)
at com.jjoe64.graphview.GridLabelRenderer.draw(GridLabelRenderer.java:1062)
at com.jjoe64.graphview.GraphView.drawGraphElements(GraphView.java:299)
at com.jjoe64.graphview.GraphView.onDraw(GraphView.java:323)
at android.view.View.draw(View.java:16068)
崩溃的方式似乎并不依赖于时间或内存问题,这让我觉得这是一个多线程的问题。
我已将所有方法设为私有和同步。我可以做任何其他步骤来使我的程序线程安全吗?或者任何人都可以看到问题可能出现在哪里?
答案 0 :(得分:1)
我不有一个解决方案,但这里有一些随意的想法:
synchronized
方法的含义,至少从你如何使用它来Update_Graph_loop
GraphView.onDraw
方法中取消装箱整数的空引用,该方法在UI线程上运行,将synchronized关键字添加到方法不会阻止GraphView.onDraw
访问您在已同步的方法中使用的对象LineGraphSeries
,也许这就是问题的根源2个可能的原因:
a)GraphView
引用了您传递给它的对象,并且在View
正在绘制时正在修改该对象
b)这不是线程同步问题,您只是将一些损坏的数据传递给 GraphView
,不知何故
如果问题是a),可以试试这个:
而不是从其他线程调用GraphView
上的方法,在其上发布一个runnable,以便它将在UI线程上运行
graph.post(new Runnable(){
@Override
public void run(){
graph.removeAllSeries();
graph.addSeries(series);
}
});