【问题标题】:Android Real Time Graph app crashing. Possible multi-threading issueAndroid Real Time Graph 应用程序崩溃。可能的多线程问题
【发布时间】:2017-03-10 12:41:14
【问题描述】:

我在大学项目中遇到问题,我需要在 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);

这个线程正在做我想做的事情,并将读数放入数组列表中(它们到达的时间和值)。然后我有另一个线程,它每 50 毫秒调用一次 Update_Graph 方法,并传入当前的 FullSignal 数组列表。

    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

控制台显示空对象引用错误,但未显示导致该错误的代码行。

    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)

它崩溃的方式似乎不依赖于时间或内存问题,这让我认为这是一个多线程问题。

我已将所有方法设为私有并同步。我可以采取任何其他步骤来使我的程序线程安全吗?或者任何人都可以看到问题可能出现在哪里?

【问题讨论】:

  • 您是否有可能从您的 arduino 获得一个空值并将其放入您的 DataPoint?
  • @ZeusNet 不,我有 - if (!total.equals("")) { - 行以确保我只使用实际读数

标签: java android multithreading real-time android-graphview


【解决方案1】:

我没有有一个解决方案,但这里有一些随机的想法:

  • 我认为你误解了synchronized 方法的含义,至少从你如何将它用于Update_Graph_loop
  • 从堆栈跟踪看来,在 GraphView.onDraw 方法中对 Integer 的空引用正在拆箱,该方法在 UI 线程上运行,向方法添加同步关键字不会阻止 GraphView.onDraw 访问对象您在已同步的方法中使用的内容
  • 我看到您传递给 GraphView 的唯一内容是 LineGraphSeries,也许这就是问题的根源

2 个可能的原因:

a) GraphView 具有对您传递给它的对象的引用,并且您正在修改该对象,而 View 正在绘制

b) 这不是线程同步问题,您只是将一些损坏的数据传递给GraphView,不知何故

如果问题是a),可以试试这个:

不要从其他线程调用 GraphView 上的方法,而是在其上发布一个可运行对象,以便它可以在 UI 线程上运行

graph.post(new Runnable(){
    @Override
    public void run(){
        graph.removeAllSeries();
        graph.addSeries(series);        
    }
});

【讨论】:

  • 是的,我需要对同步进行一些阅读。不过,对于您的最后一点,我注释掉了 resetdata 行,以便没有添加新数据,我遇到了同样的问题。感谢回复
  • 尝试评论graph.addSeries(series);
【解决方案2】:

我遇到了类似的问题,实际上我已经将代码放在了一个 runnable() UI 线程中。 如下,我的代码:

runOnUiThread(new Runnable() {
@Override
public void run() {
    if (data[7]%plot_freq==0) { 
    series.appendData(new DataPoint(x, pitch_1),true,500); 
    Log.v("Plot 1","OK"); 
    } 
    if (data_2[7]%plot_freq==0) { 
    series_2.appendData(new DataPoint(x, pitch_2),true,500); 
    Log.v("Plot 2","OK"); 
    } 
    if (data_3[7]%plot_freq==0) { 
    series_3.appendData(new DataPoint(x, pitch_3),true,500); 
    Log.v("Plot 3","OK"); 
    }

你怎么看?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    相关资源
    最近更新 更多