我的应用程序在使用AsyncTask时崩溃

3
我是新手,正在学习Android开发,我的简单应用程序出现了问题。我使用了一个非常简单的计数器,使用了AsyncTask。
当我运行应用程序并开始计数时,它计数到10,然后没有打印“完成!”而是崩溃了,我不知道为什么。这是我的代码。(该活动有3个按钮来创建、启动和取消任务)。
public class AsyncTaskActivity extends AppCompatActivity {

    AsyncTask myAsyncTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task);
    }

    public static void startActivity(Context context){

        Intent intent = new Intent(context, AsyncTaskActivity.class);
        context.startActivity(intent);

    }

    public void createNewTask(View view) {

        TextView textView = findViewById(R.id.text_view_id);
        myAsyncTask = new MyAsyncTask(textView);
    }

    public void startTask(View view) {

        myAsyncTask.execute();
    }

    public void cancelTask(View view) {

        myAsyncTask.cancel(true);
    }

    private static class MyAsyncTask extends AsyncTask{

        private TextView textView;

        public MyAsyncTask(TextView textView){

            this.textView = textView;
        }

        @Override
        protected Object doInBackground(Object[] objects) {


            for(int counter = 0; counter <= 10; counter ++){

                if(!isCancelled()) {
                    textView.setText(String.valueOf(counter));
                    SystemClock.sleep(500);
                }
                else
                    break;
            }

            textView.setText("DONE!");
            return null;
        }
    }

2
发布崩溃日志。 - MichaelStoddart
2个回答

4

在后台线程中无法更新UI,这意味着doInBackground中的代码运行在后台线程上。

 @Override
 protected Object doInBackground(Object[] objects) {
     for(int counter = 0; counter <= 10; counter ++){

         if(!isCancelled()) {
             textView.setText(String.valueOf(counter));
             SystemClock.sleep(500);
         }
         else
             break;
        }

        textView.setText("DONE!");
        // ^^^^^ crash , cannot update UI from background thread
        return null;
    }

因此,应使用 onPostExecute 代替。
 protected void onPostExecute(Long result) {
        textView.setText("DONE!");
 }

注意:如果您取消任务,则会发现与textView.setText(String.valueOf(counter));相同的崩溃。


始终使用通用类型,并传递结果计数器值并相应地更新UI。
private static class MyAsyncTask extends AsyncTask<Void,Void,Integer>{

    private TextView textView;

    public MyAsyncTask(TextView textView){

        this.textView = textView;
    }


     protected Long doInBackground(Void... obj) {
        for(int counter = 0; counter <= 10; counter ++){

            if(!isCancelled()) {
                SystemClock.sleep(500);
                return counter;
            }
            else
                break;
        }
         return null;
     }


     protected void onPostExecute(Integer result) {
        if(result != null)
            textView.setText(String.valueOf(result));
        else
            textView.setText(String.valueOf("Done"));
            // your current code will set done no matter the task is cancelled or not
     }
 }

3
您不能在AsyncTask doInBackground中编辑View(只能在主线程中)。所以将setText移动到onPostExecute中。
@Override
protected void onPostExecute(Void result)

    textView.setText("DONE!");

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接