即使在重新创建对象后,AsyncTask也不会在设备旋转后启动

时间:2017-04-12 20:36:21

标签: android android-asynctask

我有一个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()永远不会被调用或正在运行。为什么呢?

1 个答案:

答案 0 :(得分:0)

我需要在开始另一个工作人员之前停止前一个工作人员。

在顺序处理中,所有异步任务都在单个线程中运行,因此必须在上一个任务结束之前等待。如果需要立即执行代码,则需要在不同的线程中并行处理任务。

因此,在running=false中添加prepareResume以阻止上一位工作人员解决此问题。