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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从服务更新textView的最简单方法是什么?相关的知识,希望对你有一定的参考价值。

我正在制作一个包含活动和服务的应用程序。通过按下按钮启动服务,它从传感器收集背景中的数据并对其进行分类并输出字符串。我想在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();
            }
        }

    }
答案

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]);
}

以上是关于从服务更新textView的最简单方法是什么?的主要内容,如果未能解决你的问题,请参考以下文章

使用 C# 从 RTMP 服务器获取和播放音频流的最简单方法是啥?

仅使用一次行程更新一批记录的最简单方法是啥?

从其他数据库更新表数据的最有效方法是啥?

定期更新小部件 TextView 的简单方法

更新 mnesia 模式的最简单方法是啥?

从IP地址获取用户纬度和经度的最简单方法是啥[关闭]