【问题标题】:Best practices of notifying UI components from AsyncTask or service从 AsyncTask 或服务通知 UI 组件的最佳实践
【发布时间】:2013-05-16 19:01:35
【问题描述】:

我一直在阅读使用 AsyncTask 类来执行较短的后台操作,并使用服务来执行持久的操作。

那么,在 Android 中,使用 AsyncTask 类时通知 UI 后台进程更改的最佳实践是什么?我应该使用经典的 MVC 模型并创建一个侦听器(最好在扩展 Application 类的类中)还是在 Android 中这样做?

我已阅读AsyncTask reference,似乎方法 onProgressUpdate() 仅在例如在任务本身中使用 ProgressDialog 时才有用。

谢谢!

【问题讨论】:

    标签: android android-asynctask android-service


    【解决方案1】:

    如果要更新的组件是启动更新作业的组件(通过 AsyncTask 或 Service),您可能应该使用内部 AsyncTask

    AsyncTask 为您提供了两种更新 UI 的可能性:

    • 要与 doInBackground() 中执行的任务并行更新 UI(例如更新 ProgressBar),您必须在 doInBackground() 方法中调用 publishProgress()。然后你必须在 onProgressUpdate() 方法中更新 UI。
    • 要在任务完成后更新 UI,您必须在 onPostExecute() 方法中进行。

    见:
    doInBackground()
    publishProgress()
    onProgressUpdate()
    onPostExecute()

    编辑:

    public class Home extends Activity implements OnClickListener {
        private Button mButton;
        private TextView mTextView;
    
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.my_layout);
            mButton   = (Button) findViewById(R.id.myButton);
            mTextView = (TextView) findViewById(R.id.myTextView);
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
            case R.id.myButton:
                (new MyAsyncTask()).execute();
                break;
            default:
                break;
            }
        }
    
        private class MyAsyncTask extends AsyncTask<String, int[], Boolean> {
    
            /** This method runs on a background thread (not on the UI thread) */
            @Override
            protected String doInBackground(String... params) {
                for (int progressValue = 0; progressValue  < 100; progressValue++) {
                    publishProgress(progressValue);
                }
            }
    
            /** This method runs on the UI thread */
            @Override
            protected void onProgressUpdate(Integer... progressValue) {
                // TODO Update your ProgressBar here
                mTextView.setText("Updating : " + progressValue + "/100");
            }
    
            /**
             * Called after doInBackground() method
             * This method runs on the UI thread
             */
            @Override
            protected void onPostExecute(Boolean result) {
               // TODO Update the UI thread with the final result
               mTextView.setText("Update complete !");
    
            }
        }
    }
    

    你可以找到另一个例子here

    【讨论】:

    • 我应该在 AsyncTask 中使用 UI 的引用来更新它吗?
    • 我认为一个好的做法是使 AsyncTask 成为您要更新的活动的内部类。通过这种方式,您可以在 onPostExecute() 或 onProgressUpdate() 中调用和更新小部件(按钮、imageViews,...)。我会用一个例子来编辑我的帖子。
    【解决方案2】:

    OnProgressUpdate 是要走的路。当您声明 AsyncTask 的实现时,您可以定义一个要通过 onProgressUpdate 发回的对象,该对象可以被处理以向您的 UI 发送更新。否则,如果您在尝试更改 UI 时实现侦听器,您将遇到线程冲突,因为 AsyncTask 是在应用程序主线程之外的线程中执行的。 onProgessUpdate 中的任何代码都在调用者主线程中执行,因此它可以毫无问题地更新 UI

    【讨论】:

    • 当 onProgressUpdate() 是一个 AsyncTask 方法时我看到它的方式,我需要将当前活动的引用传递给任务以在 onProgressUpdate() 中更新它。这是正确的方法吗?
    【解决方案3】:

    AsyncTask 与服务 - 当结果是本地活动时使用 AsyncTask - 当其他活动不需要您的任务结果时。当他们这样做时使用服务。

    使用 onPorgressUpdate 在 AsyncTask 中提供增量状态通知 - 任务尚未完成时的任何通知。有关任务完成时间的通知,请使用 onPostExecute。监听器也可能是合适的,但前提是您需要通知编译时不一定知道的特定类,而不是发布状态更新的通用方式。

    【讨论】:

      猜你喜欢
      • 2020-11-11
      • 1970-01-01
      • 1970-01-01
      • 2011-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      相关资源
      最近更新 更多