我有一个REST服务器,它从远程ADC中吐出数据,我需要将数据图形化以便进行演示。我使用AsyncTask将数据采集移出主线程以防止NetworkOnMainThreadException
。我写了这个:
package inostiot.inostiot;
// imports
public class MonitorActivity extends AppCompatActivity {
private GraphWorker worker;
@Override
protected void onSaveInstanceState(Bundle outState) {
worker.cancel(true);
outState.putBundle("state", worker.prepareResume());
outState.putBoolean("resuming", true);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_monitor);
Intent intent = getIntent();
Bundle extras = intent.getExtras();
String ip = extras.getString("ip");
LineChart chart = (LineChart) findViewById(R.id.chart);
XAxis x = chart.getXAxis();
YAxis y = chart.getAxisLeft();
// More chart setup here, ignore
if (savedInstanceState != null) {
boolean resuming = savedInstanceState.getBoolean("resuming", false);
if (resuming) {
worker = new GraphWorker(this, ip, chart, true);
worker.resume(savedInstanceState.getBundle("state"));
worker.execute();
}
} else {
worker = new GraphWorker(this, ip, chart, false);
worker.execute();
}
}
}
class GraphWorker extends AsyncTask<Void, Object, Void> {
private LineChart chart;
private boolean resuming;
private boolean running = true;
private String ip;
private Activity parent;
private ArrayList<ADCPort> ports;
private ArrayList<WalkingDataset> walkingDatasets;
private ArrayList<LineDataSet> lineDataSets;
GraphWorker(Activity parent, String ip, LineChart chart, boolean resuming) {
this.parent = parent;
if (!resuming) {
ports = new ArrayList<>();
walkingDatasets = new ArrayList<>();
this.ip = ip;
}
this.chart = chart;
this.resuming = resuming;
lineDataSets = new ArrayList<>();
}
@Override
public Void doInBackground(Void...params) {
ADC adc = new ADC(ip);
if (!resuming) {
if (!adc.auth()) throw new RuntimeException("Server invalid!");
ports.add(new ColoredADCPort(0, "#FF0000"));
walkingDatasets.add(new WalkingDataset(10));
// More ports are initialized here, just copy-paste an
// color change
}
while (running) {
try {
ports = adc.readPorts(ports);
publishProgress((Object)ports);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (ADCException e) {
e.printStackTrace();
break;
}
}
return null;
}
void resume(Bundle data) {
this.ports = (ArrayList<ADCPort>) data.getSerializable("ports");
this.walkingDatasets = (ArrayList<WalkingDataset>) data.getSerializable("walkingDatasets");
this.ip = data.getString("ip");
this.chart.invalidate();
}
Bundle prepareResume() {
Bundle data = new Bundle();
data.putSerializable("ports", ports);
data.putSerializable("walkingDatasets", walkingDatasets);
data.putString("ip", ip);
return data;
}
@Override
protected void onProgressUpdate(Object... values) {
ArrayList<ADCPort> ports = (ArrayList<ADCPort>) values[0];
lineDataSets.clear();
for (int i = 0; i < ports.size(); i++) {
ColoredADCPort port = (ColoredADCPort) ports.get(i);
WalkingDataset dataset = walkingDatasets.get(i);
dataset.add(port.getValue());
LineDataSet lineDataSet = new LineDataSet(dataset, String.format(Locale.ENGLISH, "Sensor %d", i));
lineDataSet.setCircleColor(Color.parseColor(port.getColor()));
lineDataSet.setColor(Color.parseColor(port.getColor()));
lineDataSet.setDrawValues(false);
lineDataSets.add(lineDataSet);
}
final LineData data = new LineData();
for (LineDataSet set : lineDataSets) {
data.addDataSet(set);
}
chart.setData(data);
chart.postInvalidate();
super.onProgressUpdate();
}
public void stopRunner() {
this.running = false;
}
}
Activity上有一个来自LineChart
的{{1}},并且AsyncTask应该使用从服务器获取的新图表数据来更新UI。但是,在设备轮换之后和MPAndroidCharts
resume()
方法之后调用以恢复对象状态,并且在调用GraphWorker
之后,execute()
永远不会被调用或正在运行。为什么呢?
答案 0 :(得分:0)
我需要在开始另一个工作人员之前停止前一个工作人员。
在顺序处理中,所有异步任务都在单个线程中运行,因此必须在上一个任务结束之前等待。如果需要立即执行代码,则需要在不同的线程中并行处理任务。
因此,在running=false
中添加prepareResume
以阻止上一位工作人员解决此问题。