【问题标题】:How to properly apply AsyncTask?如何正确应用 AsyncTask?
【发布时间】:2013-06-17 15:28:34
【问题描述】:

我正在编写以下代码,我研究了其他问题,例如 AsyncTask Android exampleHow to properly use AsyncTask 但我仍然有问题,你能告诉我我错过了什么吗?非常感谢!!!

所以,在 UI 中,我有一个开始按钮、一个停止按钮和一个文本视图。 我从加速度计传感器获取数据并存储在 csv 文件中。 不使用 AsyncTask,代码可以正常工作,但是使用它时(如下所示),出现此错误:a_datatest 无法解析为变量

所以,基本上我想要的是在单击开始按钮后立即开始在后台写入加速度计数据,然后单击停止按钮后,文本视图显示“数据已存储!”

感谢您的帮助!

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Criteria;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements SensorEventListener, OnClickListener {

    private SensorManager sensorManager;
    private LocationManager locationManager;
    private Button start_bt;
    private Button stop_bt;
    private TextView result_view;
    private boolean started = false;
    String towers;    
    FileOutputStream fos;
    String FILENAME = "AccelOutput";

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

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Criteria crit = new Criteria();
        towers = locationManager.getBestProvider(crit, false);
        start_bt = (Button) findViewById(R.id.startButton);
        stop_bt = (Button) findViewById(R.id.stopButton);
        result_view = (TextView) findViewById(R.id.resultTextView);
        start_bt.setOnClickListener(this);
        stop_bt.setOnClickListener(this);

    }

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

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

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (started) {
            Sensor sensortype = event.sensor;

            if (sensortype.getType() == Sensor.TYPE_ACCELEROMETER) {

                double a_x = event.values[0];
                double a_y = event.values[1];
                double a_z = event.values[2];
                double a_a = event.accuracy;
                double a_ts = event.timestamp;
                long a_timestamp = System.currentTimeMillis();
                AccelData a_data = new AccelData(a_timestamp, a_ts, a_x, a_y, a_z, a_a);                
                String a_datatest = a_data.toString();

                new writeData().execute();
            }       
        }
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.startButton) {
            started = true;
            Sensor accel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            sensorManager.registerListener(this, accel, SensorManager.SENSOR_DELAY_FASTEST);
        } else if(v.getId() == R.id.stopButton) {
            started = false;
            sensorManager.unregisterListener(this);
        }
    }

    private class writeData extends AsyncTask<Void, Void, String>{

        @Override
        protected String doInBackground(Void... params) {
            // TODO Auto-generated method stub
            File sdCard = Environment.getExternalStorageDirectory();
            File directory = new File (sdCard.getAbsolutePath() + "/output");
            directory.mkdirs();

            String a_filename = "accelerometer.csv";
            File a_file = new File(directory, a_filename);
            FileOutputStream a_fOut = null;
            try {
                a_fOut = new FileOutputStream(a_file, true);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            OutputStreamWriter a_osw = new OutputStreamWriter(a_fOut);
            try {
                a_osw.write(a_datatest + "\n");
                a_osw.flush();
                a_osw.close();
            } catch (IOException e) {

                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
              result_view.setText("Data Stored!"); 
        }
    }
}

【问题讨论】:

  • a_dataset 是 onSensorChanged() 的局部变量,它在 doInBackGround 内不可见。

标签: android android-asynctask store accelerometer onclicklistener


【解决方案1】:

在类范围内声明变量。即作为成员变量使用

您在onSensorChanged 方法中声明a_datatest,因此它在此范围之外没有有效性。所以你不能在doInBackGround方法中使用它

delcare 类内喜欢

private String a_datatest;

在 onSensorChanged 方法中使用 like

a_datatest = a_data.toString();

【讨论】:

  • 我认为它正在处理您提到的更改。非常感谢!
【解决方案2】:

我不认为AsyncTask 是实现这一目标的最佳方式。 AsyncTask 设计用于一次性操作,例如从服务器下载一组数据。 AsyncTask 启动,在后台执行某些操作,然后向 UI 线程报告。虽然可以停止 AsyncTask,但它不会按您想要的方式工作。

我建议为此使用Service。您可以通过按下按钮开始读取值,然后停止停止按钮的Service onClick。

【讨论】:

  • 是的,就像我说的,代码在没有 AsyncTask 的情况下工作正常,但我想使用 AsyncTask 的原因是在我开始记录数据后一段时间,UI 冻结,这意味着你无法停止通过停止按钮进行日志记录,因此您必须将应用程序换掉并终止应用程序。我想把所有的写作任务都放在后台,这样它就不会干扰 UI。你认为我走在正确的轨道上吗?
  • 您有 100% 的权利使用后台线程,这样您就不会阻塞 UI。我只是说我认为你不应该使用AsyncTask
  • 据我了解,我可以使用 AsyncTask 或使用 Handler,这样我就可以将一些任务放在后台运行。有没有更好的方法,或者基本上什么是最合适的方法?谢谢。
  • 根据您的描述 - 启动后台进程,运行一段时间,然后停止用户输入,我会使用 AsyncTask 以外的任何内容。 Handler 将是一个不错的选择。基本上任何正常的后台线程设置都比AsyncTask 更有意义。正如我所说,AsyncTask 旨在用于一次性操作 - 例如获取这张照片,或发布此状态更新。它并不是一个可以随意停下来的听众。
猜你喜欢
  • 1970-01-01
  • 2021-02-15
  • 1970-01-01
  • 2012-12-24
  • 2019-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多