从附着在Android上的传感器连续获取数据(线程,异步任务,服务)



我已将一个传感器与Android Phone连接。传感器测量响应并在应用程序上显示相应的结果。我试图使用Java Timer,但现在计划移动到Thread

在连续模式下,应用程序将完全禁用,不需要任何用户吸引。用户需要设置一些预采集设置,然后按下开始按钮。启动该按钮后,main GUI会不断更新,但在操作过程中,用户无法与应用程序交互。用户需要再次按下"开始"按钮来停止应用程序。此时启动按钮将充当停止按钮。

我是Android的新手,所以我在网上学习,发现Asyntask是更好的选择,而不是thread。然后有人还提到Service也可以更好地运行长进程或Concurrent。我希望我的应用程序运行很长一段时间没有停止或内存泄漏。

你认为我的情况怎样比较好?在此期间,我尝试使用AsyncTask .

这是我使用AsynTask的代码。我希望这段代码连续运行并更新UI线程。UI有一个图表,它将与来自后台的数据更新。

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
final Button button = (Button) findViewById(R.id.button1); //This button will start and stop the app.
button.setOnClickListener(addOnButtonClick(button));
}

//从main按钮被按下,然后从按钮信号,Aysnctask将被调用。我刚刚实现了doInBackground函数。

 View.OnClickListener addOnButtonClick(final Button button){
        return  new View.OnClickListener()
        {
            public void onClick(View v)
            {
                new AsyncTaskActivity().doInBackground();
//Here i want to add one flag, which will be activated as 'true`when the
//button will be pressed once and `fasle` when the button will be pressed //second time. 
//True-> activity run, false ->activity stop.
                }
            };
        }
 public class AsyncTaskActivity extends AsyncTask<Void , Void, Void>{

        @Override
        protected Void doInBackground(Void... params){

                nativeData = getDatafromsensor(); //Data from native.
                DataPoint[] data = new DataPoint[Size];
                for (int i=0; i<Size; i++) {
                    double x = i;
                    double y = nativeData[i];
                    DataPoint v = new DataPoint(x, y);
                    data[i] = v;
                    }
                }
                series.resetData(data);
            }
return null;
        }

我认为Service可能是长期发展的方式,但以下是AsyncTask的发展方式。

你应该非常仔细地阅读AsyncTask文档的"用法"部分,这样你就能理解UI线程方法和后台线程方法之间的交互。在您的onClick()方法中,您直接调用doInBackground(),这是一个禁忌。你调用execute(),结果doInBackground()在另一个线程上被调用。

AsyncTask有一个更新进度的方法。它意味着用于更新(例如)进度条(必须从UI线程完成),而后台线程仍在运行。你可以用它来实现你的目标。

下面是一些示例代码:

创建AsyncTask的子类来运行数据捕获线程:

public class SensorTask extends AsyncTask<Void, List<Double>, Void> {
    protected void onPreExecute() {
        // runs on the UI thread
        // TODO set up your UI for data acquisition
    }
    protected Void doInBackground(Void... params) {
        // TODO initialize sensor for acquisition
        while (! isCancelled()) {
            nativeData = getDatafromsensor(); //Data from native.
            List<Double> sensorData = new ArrayList<Double>();
            for (int i = 0; i < nativeData.length; i++) {
                sensorData.add(new Double(nativeData[i]);
            }
            publishProgress(sensorData);  // this invokes onProgressUpdate on UI thread
            Thread.sleep(DELAY_TIME);  // if you need to
        }
        // TODO sensor cleanup
    }
    protected void onProgressUpdate(List<Double>... values) {
        // runs on the UI thread
        // TODO update your UI with the sensor data
    }
    protected void onCancelled(Void result) {
        // runs on the UI thread
        // TODO update UI for acquisition complete
    }
}

你可以这样启动它:

    public void onClick(View v) {
        // you need to keep a reference to the task so you can cancel it later
        if (mSensorTask != null) {
            // task already exists -- if running, stop it
            mSensorTask.cancel(false);
            mSensorTask = null;
        } else {
            // task doesn't exist -- make a new task and start it
            mSensorTask = new SensorTask();
            mSensorTask.execute();    
            // this will make doInBackground() run on background thread
        }
    };

这是很重要的:确保你在活动的onPause()方法中取消任务,所以线程只在活动当前时运行。


编辑:使用全局数组的优点是消除了额外的对象分配。只要确保同步访问数据数组即可。下面是为使用全局数组编写AsyncTask代码的另一种方法:

public class SensorTask extends AsyncTask<Void, Void, Void> {
    protected void onPreExecute() {
        // runs on the UI thread
        // TODO set up your UI for data acquisition
    }
    protected Void doInBackground(Void... params) {
        // TODO initialize sensor for acquisition
        while (! isCancelled()) {
            synchronized (nativeData) {
                nativeData = getDatafromsensor(); // Data from native.
            }
            publishProgress(null);  // this invokes onProgressUpdate on UI thread
            Thread.sleep(DELAY_TIME);  // if you need to
        }
        // TODO sensor cleanup
    }
    protected void onProgressUpdate(Void... values) {
        // runs on the UI thread
        synchronized (nativeData) {
            // TODO update your UI with the sensor data
        }
    }
    protected void onCancelled(Void result) {
        // runs on the UI thread
        // TODO update UI for acquisition complete
    }
}

我使用了您的技术,并在pre中设置了图形索引并初始化了条件。在background的事情中,我调用本机函数并从传感器获得数据。在publish中,我以图形形式显示该数据,为此我使用了GraphView库。下面是代码

public class AsyncTaskActivity extends AsyncTask<Void, Double, Void> {

    protected void onPreExecute() {
            viewport.setMinY(0);
            viewport.setMaxY(8000);
            viewport.setMinX(0);
            viewport.setMaxX(330);
            staticLabelsFormatter = new StaticLabelsFormatter(graph);
            staticLabelsFormatter.setHorizontalLabels(new String[]{"400", "500", "600", "730"});
            graph.getGridLabelRenderer().setLabelFormatter(staticLabelsFormatter);
        } 

    protected Void doInBackground(Void... params) {
        while (!isCancelled()) {
            synchronized (nativeData) {
            nativeData = getDatafromsensor(); // Data from native.
        }
        publishProgress(null);  // this invokes onProgressUpdate on UI thread
    }
    }
    protected void onProgressUpdate(Void... values) {
///This one here
            series.setBackgroundColor(Color.rgb((int) spec_data[WeightSize], (int) spec_data[WeightSize+1], (int) spec_data[WeightSize+2]));
            series.resetData(data);
    }
    protected void onCancelled(Void result) {
        Log.d("Updates", "I am In Cancelled");
        if (mSensorTask != null)
            mSensorTask.cancel(true);

    }
}

问题:

问题是,在ProgressUpdate,当我设置背景颜色。它经常闪烁。就像有时它不会显示超过30秒,即使图形完全变化。我需要睡觉吗?但"为什么"的图表正在瞬间改变?

最新更新