Java Android传感器回调行为

Java Android传感器回调行为,java,android,multithreading,callback,Java,Android,Multithreading,Callback,我正在和一个朋友一起开发一个android应用程序,通过数值积分加速度来跟踪运动。我们是机械工程专业的学生,很难理解android应用程序中使用的线程中事件的顺序是如何发生的。例如,UI线程似乎在调用它的代码完成执行之前运行。请参阅以下代码,该代码仅尝试获取当前加速度并存储以前的加速度,以供以后在梯形积分中使用: import java.util.Arrays; import android.hardware.Sensor; import android.hardware.SensorEvent

我正在和一个朋友一起开发一个android应用程序,通过数值积分加速度来跟踪运动。我们是机械工程专业的学生,很难理解android应用程序中使用的线程中事件的顺序是如何发生的。例如,UI线程似乎在调用它的代码完成执行之前运行。请参阅以下代码,该代码仅尝试获取当前加速度并存储以前的加速度,以供以后在梯形积分中使用:

import java.util.Arrays;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity implements SensorEventListener {
  float[] current;
  float[] last;
  SensorManager sm;
  Sensor accelerometer;
  TextView Display;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    current = new float[] {0, 0, 0};
    last = new float[] {0, 0, 0};
    sm = (SensorManager)getSystemService(SENSOR_SERVICE);
    accelerometer = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    sm.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
    Display = (TextView)findViewById(R.id.text_box);
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }

  @Override
  public void onSensorChanged(SensorEvent event) { 
    last = current;
    current = event.values;

    if (last != current) {
      Display.setText(Arrays.toString(current)+"\n"+Arrays.toString(last)+"\nThe numbers are not the same!!!");
    } else { 
      Display.setText(Arrays.toString(current)+"\n"+Arrays.toString(last)+"\nThe numbers are the same!!!");
    }
  }

  @Override
  public void onAccuracyChanged(Sensor sensor, int accuracy) {

  }
}

结果是TextView始终显示“数字相同”文本。加速度值会发生变化,但打印的当前值和最后值始终相同(即“[.4423、.12234,9.8234]\n[.4423、.12234,9.8234]\n值相同”)。我们在代码中放置了一个计数器,以查看if语句检测到值不同的频率,并且它只增加到一,我假设这发生在第一次迭代中。我想不出什么好的理论来解释为什么这些值会随着时间而变化,但是当前值和最后一个值从来没有什么不同。UI线程能否在传感器管理器线程更新last之前以某种方式获取其值?如果我没有显式地创建线程执行顺序,我应该处理线程执行顺序吗?

好的,那么问题是对Java工作方式的根本误解。我们正在传递指向数组的指针。我以前使用C++,并且认为java不使用指针,将数组设置为彼此相等,这就等于通过值。这样做实际上只是将对当前和最后一个变量的引用设置为events.value数组的引用,这意味着setText函数被告知打印来自同一引用的值。这是一个痛苦的学习方式,教授给我们这个项目是第三个人对我说:“如果你懂C++,你就会明白java”,当他应该说去读一本关于细节的书……< 要运行上述代码,我们更改了:

last = current;
current = event.values;
为此:

System.arraycopy(current,0,last,0,3);
System.arraycopy(event.values, 0, current, 0, 3);

复制event.values还可以解决将来可能遇到的一个令人讨厌的副作用。您不能直接保存事件的任何值(例如,将event.values分配给全局变量),因为这些值可能会被框架重用(即使用指向相同结构的指针)。来自Android文档:“注意:应用程序不拥有作为参数传递的事件对象,因此无法保留该对象。该对象可能是内部池的一部分,可由框架重用。”