Android UI省略了一些更新

时间:2017-01-18 08:45:45

标签: android user-interface android-asynctask

我正在处理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);
            }
        }
}

1 个答案:

答案 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;

                // ...
            }
        }
    }
}