简体   繁体   English

我想每X秒执行一次代码,但是handler.postDelayed无法正常工作

[英]I want to execute code every X seconds, but handler.postDelayed not working

Okay so I want to register the accelerometer values every X seconds to my database. 好的,我想每隔X秒将加速度计值注册到我的数据库中。 He takes the first delay, but ignores the second handler.postDelayed, does anybody know what it can be? 他采用第一个延迟,但是忽略了第二个handler.postDelayed,有人知道它可以是什么吗? I've tried with a Timer, but that didn't work either so I'm kinda running out of options here... 我已经尝试过使用计时器,但是那也不起作用,所以我在这里的选件有点用光了……

Here's the code: 这是代码:

public class MainActivity extends AppCompatActivity implements SensorEventListener{

private Button receiveButton;
private ListView listView;

private DatabaseReference database;

private ArrayAdapter<String> adapter;
private List<String> items;

private SensorManager sensorManager;
private Sensor senAccelerometer;

private Handler handler = new Handler();
private final int delay = 5000; //in milliseconds

private Accelerometer accelerometer;

private float xValue;
private float yValue;
private float zValue;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    senAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    sensorManager.registerListener(this, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);

    receiveButton = findViewById(R.id.receiveButton);
    listView = findViewById(R.id.listView);

    database = FirebaseDatabase.getInstance().getReference("Accelerometer");

    items = new ArrayList<>();


    items.add("X Value: " + Float.toString(xValue));
    items.add("Y Value: " + Float.toString(yValue));
    items.add("Z Value: " + Float.toString(zValue));
    updateUI();

    receiveButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            database.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    Accelerometer accelerometer = dataSnapshot.getValue(Accelerometer.class);
                    xValue = accelerometer.xValue;
                    yValue = accelerometer.yValue;
                    zValue = accelerometer.zValue;
                    for (Iterator<String> iterator = items.iterator(); iterator.hasNext();){
                        iterator.next();
                        iterator.remove();
                    }
                    items.add("X Value: " + Float.toString(xValue));
                    items.add("Y Value: " + Float.toString(yValue));
                    items.add("Z Value: " + Float.toString(zValue));
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            });
            updateUI();
        }
    });
}

private void updateUI(){
    if(adapter == null){
        adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, items);
        listView.setAdapter(adapter);

    } else{
        adapter.notifyDataSetChanged();
    }
}

@Override
public void onSensorChanged(final SensorEvent sensorEvent) {
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            if(sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                accelerometer = new Accelerometer(sensorEvent.values[0], sensorEvent.values[1], sensorEvent.values[2]);
            }
            database.setValue(accelerometer);
            handler.postDelayed(this, delay);
        }
    }, delay);
}

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

}
}

Thanks in advance! 提前致谢!

You should use this pattern: 您应该使用以下模式:

Handler handler = new Handler()
Runnable yourRunnable = new Runnable()
    {

        @Override
        public void run() {
            doYourAction();
            handler.postDelayed(yourRunnable, UPDATE_INTERVAL);
        }
    };

You could try a recursive call with AsyncTask. 您可以尝试使用AsyncTask进行递归调用。 Something like: 就像是:

public void checkAccelerometer() {
    final Handler handler = new Handler();
    new AsyncTask<Void, Void, Void>() {
        @Override
        protected void onPreExecute() {
            //Update UI if you want/need to
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(Void... voids) {
            //Do your thing
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    checkAccelerometer();
                }
            }, 5000);
            super.onPostExecute(aVoid);
        }
    }.execute();
}

This will execute your code in a background thread and call itself after 5 seconds to continue repeatedly. 这将在后台线程中执行您的代码,并在5秒钟后调用自身以继续重复。 If you want a way to stop this loop you could just throw everything into an if statement at the beginning and check for a boolean that you can control elsewhere. 如果您想停止循环,可以将所有内容放在开头的if语句中,然后检查可以在其他位置控制的布尔值。

I've solved it, I had to put it in the oncreate method. 我已经解决了它,我不得不将它放在oncreate方法中。 Because if you put it in the onSensorChanged it will be executed every time the data changes. 因为如果将其放在onSensorChanged中,它将在每次数据更改时执行。 So if you execute the data outside of the onSensorChanged, it will be executed only once which will make sure it doesn't infinitely update every .5 ms. 因此,如果您在onSensorChanged之外执行数据,则该数据将仅执行一次,以确保不会每隔0.5毫秒无限更新一次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM