从服务更新textView的最简单方法是什么?

时间:2018-09-07 06:41:14

标签: java multithreading service android-asynctask

我正在制作一个包含活动和服务的应用程序。通过按下按钮,服务启动,它在后台从传感器收集数据并将其分类并输出字符串。我想在textView中显示字符串。现在,我可以在日志中看到该变量每秒更新2次,但是当我尝试从服务类更新textView时,除非按下按钮,否则什么都没有发生,每当按下按钮时,该字符串就会显示在textView。

这里最简单的解决方案是什么?我试图将textView设为静态,但仍然无法更新它。您能做到使视图每秒自动更新吗?我可以添加监听器吗?由于我经验不足,所以我希望有一个简单的解决方案,而不必是“好”方案。

这是我的代码

活动:

public class CollectorActivity extends Activity {

private enum State {
    IDLE, COLLECTING, TRAINING, CLASSIFYING
};

private final String[] mLabels = { Globals.CLASS_LABEL_STANDING,
        Globals.CLASS_LABEL_WALKING, Globals.CLASS_LABEL_RUNNING,
        Globals.CLASS_LABEL_OTHER };

private RadioGroup radioGroup;
private final RadioButton[] radioBtns = new RadioButton[4];
private Intent mServiceIntent;
private File mFeatureFile;
public static TextView mCurrentLabel;

private State mState;
private Button btnDelete;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    radioGroup = (RadioGroup) findViewById(R.id.radioGroupLabels);
    radioBtns[0] = (RadioButton) findViewById(R.id.radioStanding);
    radioBtns[1] = (RadioButton) findViewById(R.id.radioWalking);
    radioBtns[2] = (RadioButton) findViewById(R.id.radioRunning);
    radioBtns[3] = (RadioButton) findViewById(R.id.radioOther);

    btnDelete = (Button) findViewById(R.id.btnDeleteData);
    mCurrentLabel = (TextView) findViewById(R.id.textView);

    mState = State.IDLE;
    mFeatureFile = new File(getExternalFilesDir(null),
            Globals.FEATURE_FILE_NAME);
    mServiceIntent = new Intent(this, SensorsService.class);


}



public void onCollectClicked(View view) {

    if (mState == State.IDLE) {
        mState = State.COLLECTING;
        ((Button) view).setText(R.string.ui_collector_button_stop_title);
        btnDelete.setEnabled(false);
        radioBtns[0].setEnabled(false);
        radioBtns[1].setEnabled(false);
        radioBtns[2].setEnabled(false);
        radioBtns[3].setEnabled(false);

        int acvitivtyId = radioGroup.indexOfChild(findViewById(radioGroup
                .getCheckedRadioButtonId()));
        String label = mLabels[acvitivtyId];

        Bundle extras = new Bundle();
        extras.putString(Globals.CLASS_LABEL_KEY, label);
        mServiceIntent.putExtras(extras);

        startService(mServiceIntent);

    } else if (mState == State.COLLECTING) {
        mState = State.IDLE;
        ((Button) view).setText(R.string.ui_collector_button_start_title);
        btnDelete.setEnabled(true);
        radioBtns[0].setEnabled(true);
        radioBtns[1].setEnabled(true);
        radioBtns[2].setEnabled(true);
        radioBtns[3].setEnabled(true);

        stopService(mServiceIntent);
        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancelAll();
    }
}

public void onDeleteDataClicked(View view) {

    if (Environment.MEDIA_MOUNTED.equals(Environment
            .getExternalStorageState())) {
        if (mFeatureFile.exists()) {
            mFeatureFile.delete();
        }

        Toast.makeText(getApplicationContext(),
                R.string.ui_collector_toast_file_deleted,
                Toast.LENGTH_SHORT).show();
    }
}

@Override
public void onBackPressed() {

    if (mState == State.TRAINING) {
        return;
    } else if (mState == State.COLLECTING || mState == State.CLASSIFYING) {
        stopService(mServiceIntent);
        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
                .cancel(Globals.NOTIFICATION_ID);
    }
    super.onBackPressed();
}

@Override
public void onDestroy() {
    // Stop the service and the notification.
    // Need to check whether the mSensorService is null or not.
    if (mState == State.TRAINING) {
        return;
    } else if (mState == State.COLLECTING || mState == State.CLASSIFYING) {
        stopService(mServiceIntent);
        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
                .cancelAll();
    }
    finish();
    super.onDestroy();
}

这是我的服务类中的“ doInBackground”方法。行“ CollectorActivity.mCurrentLabel.setText(classification);”是问题。我希望它不断更新textView。

 public class OnSensorChangedTask extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... arg0) {



        Instance inst = new DenseInstance(mFeatLen);
        inst.setDataset(mDataset);
        Instance inst2 = new DenseInstance(65);
        int blockSize = 0;
        FFT fft = new FFT(Globals.ACCELEROMETER_BLOCK_CAPACITY);
        double[] accBlock = new double[Globals.ACCELEROMETER_BLOCK_CAPACITY];
        double[] re = accBlock;
        double[] im = new double[Globals.ACCELEROMETER_BLOCK_CAPACITY];

        double max = Double.MIN_VALUE;

        while (true) {
            try {
                // need to check if the AsyncTask is cancelled or not in the while loop
                if (isCancelled () == true)
                {
                    return null;
                }

                // Dumping buffer
                accBlock[blockSize++] = mAccBuffer.take().doubleValue();


                if (blockSize == Globals.ACCELEROMETER_BLOCK_CAPACITY) {
                    blockSize = 0;
                    testList = new ArrayList<Double>();

                    // time = System.currentTimeMillis();
                    max = .0;
                    for (double val : accBlock) {
                        if (max < val) {
                            max = val;
                        }
                    }

                    fft.fft(re, im);

                    for (int i = 0; i < re.length; i++) {
                        double mag = Math.sqrt(re[i] * re[i] + im[i]
                                * im[i]);
                        inst.setValue(i, mag);
                        testList.add(i,mag);
                        im[i] = .0; // Clear the field
                    }

                    // Append max after frequency component
                    inst.setValue(Globals.ACCELEROMETER_BLOCK_CAPACITY, max);
                    inst2.setValue(Globals.ACCELEROMETER_BLOCK_CAPACITY, max);
                    testList.add(max);


                     classificationIndex = WekaClassifier.classify(testList.toArray());
                     classification = testLabel.get((int) classificationIndex);
                     CollectorActivity.mCurrentLabel.setText(classification);

                    inst.setValue(mClassAttribute, mLabel);
                    mDataset.add(inst);
                    Log.i("new instance", mDataset.size() + "");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

1 个答案:

答案 0 :(得分:0)

doInBackground(Void... arg0)中将CollectorActivity.mCurrentLabel.setText(classification);更改为publishProgress(classification);,然后将第二个参数从Void更改为Stringpublic class OnSensorChangedTask extends AsyncTask<Void, Srting, Void>并添加onProgressUpdate()

最后,您的代码应如下所示:

public class OnSensorChangedTask extends AsyncTask<Void, Srting, Void> {

@Override
protected Void doInBackground(Void... arg0) {
    //...
    publishProgress(classification);
    //...
}

@Override
protected Void onProgressUpdate(String... classification) {
     CollectorActivity.mCurrentLabel.setText(classification[0]);
}