从服务更新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
的第二个参数更改为String
:public 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的最简单方法是什么?的主要内容,如果未能解决你的问题,请参考以下文章