我正在处理Android UI,我正面临着这里看起来很常见的问题。 通过使用AsyncTask,我想:
1-展示ProgressDialog同时准备一些东西
2-显示倒计时以让用户为实际操作做好准备
3-倒计时后播放声音以通知样品
4-显示另一个代表10s样本的ProgressDialog
5-取样后再播放声音
嗯,这是我的结果:
1-正常工作
2 - MISSING,UI没有更新但后台进程正在运行
3-工作正常
4-工作正常
5-工作正常
最有趣的是,当我删除代码来处理处理第一个进度对话框的第一部分时,其他部分按预期执行/显示。我知道有些东西在某些时候阻止了用户界面,但我很熟悉用android来实现阻止它的东西。
提前感谢您的帮助。
public class SnapshotActivity extends AppCompatActivity {
private int COUNTDOWN_TIME = 5;
private Button startStop;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_snapshot);
startStop = (Button) findViewById(R.id.btnStartStop);
startStop.setText("START");
}
public void startSnapshot(View view) {
startStop.setClickable(false);
new Async(SnapshotActivity.this).execute();
}
class Async extends AsyncTask<Void, Void, Void>{
TextView tv = (TextView) findViewById(R.id.tvCountDown);
ProgressDialog progressDialog ;
ProgressDialog preparing;
Context context;
int flag = 0;
int counter = COUNTDOWN_TIME;
public Async(Context context) {
this.context = context;
progressDialog = new ProgressDialog(context);
preparing = new ProgressDialog(context);
}
@Override
protected void onPreExecute(){
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params) {
//PROGRESS DIALOG
flag = 4;
publishProgress();
try {
//SIMULATE SOME WORKLOAD
Thread.sleep(2000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
flag = 5;
publishProgress();
//HANDLE THE COUNTDOWN
for(counter = COUNTDOWN_TIME; counter>=1; counter--){
publishProgress();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
//PLAY THE SOUND
new Thread(new Runnable() {
@Override
public void run() {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
}
}).start();
//PROGRESS DIALOG
flag = 1;
publishProgress();
//10s SAMPLE
flag = 2;
for(int j = 0; j <= 10; j++ ){
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
publishProgress();
}
//PLAY THE SOUND
new Thread(new Runnable() {
@Override
public void run() {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
}
}).start();
flag = 3;
publishProgress();
return null;
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
switch (flag) {
case 0:
tv.setText(String.valueOf(counter));
break;
case 1:
tv.setText("");
progressDialog.setTitle("TAIKING SAMPLE");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMax(10);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
break;
case 2:
progressDialog.incrementProgressBy(1);
break;
case 3:
progressDialog.dismiss();
break;
case 4:
preparing.setMessage("Starting the device...");
preparing.setCanceledOnTouchOutside(false);
preparing.show();
break;
case 5:
preparing.dismiss();
break;
default:
break;
}
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
startStop.setClickable(true);
}
}
}
答案 0 :(得分:0)
有两个问题:
onProgressUpdate()
倒计时值 doInBackground()
和onProgressUpdate()
方法在两个不同的线程中执行,并且两个方法/线程都以不安全的方式访问flag
字段。您可以直接在flag
调用中通知此值,而不是在doInBackground()
中的onProgressUpdate()
中设置要在publishProgress()
中读取的值。所以我建议你做以下事情:
public class SnapshotActivity extends AppCompatActivity {
// ...
// Change the Progress generic type to Integer.
class Async extends AsyncTask<Void, Integer, Void> {
// Remove the flag field.
// int flag = 0;
@Override
protected Void doInBackground(Void... params) {
//PROGRESS DIALOG
// Pass the flag argument in publishProgress() instead.
// flag = 4;
publishProgress(4);
// ...
// flag = 5;
publishProgress(5);
//HANDLE THE COUNTDOWN
for (counter = COUNTDOWN_TIME; counter>=1; counter--){
// The countdown progress has two parameters:
// a flag indicating countdown and
// the countdown value.
publishProgress(6, counter);
// ...
}
//PLAY THE SOUND
// ...
//PROGRESS DIALOG
// flag = 1;
publishProgress(1);
//10s SAMPLE
// flag = 2;
for(int j = 0; j <= 10; j++ ){
// ...
publishProgress(2);
}
//PLAY THE SOUND
// ...
// flag = 3;
publishProgress(3);
return null;
}
// This signature changes.
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// Redeclare flag here.
int flag = values[0];
switch (flag) {
// ...
case 6:
tv.setText(Integer.toString(values[1]));
break;
// ...
}
}
}
}