从AsyncTask返回数据而不阻塞UI

15

我有一个关于 AsyncTask 类的概念性问题。我们使用 AsyncTask 以便主 UI 不被阻塞。 但是假设,我想从设备存储器中检索一些数据,并且我使用 AsyncTask 类来完成此操作。相关的代码行将如下所示(假设返回的数据类型为 String):

  //code
    String data = new ExtendedAsyncTask().execute(param1, param2).get();
  //use this returned value.

那么上述代码行不会阻塞用户界面(UI)吗?这不是违背使用 AsyncTask 的初衷吗?如果是,那么我该如何在不阻塞UI的情况下获取相关数据呢?需要注意的是,下一行代码将需要这些数据来执行某些任务,并因此依赖于返回值。

谢谢


Google解释了AsyncTask:https://developer.android.com/guide/components/processes-and-threads.html#AsyncTask - luc.chante
3个回答

20

get()方法会阻塞UI线程。为了获取相关数据,您需要从doInBackground返回值,并在onPostExecute参数中捕获该值。

通过doInBackground返回的值可以被onPostExecute方法捕获

示例:

public class BackgroundTask extends AsyncTask<String, Integer, String >{
       private ProgressDialog mProgressDialog;
       int progress;
       public BackgroundTask() {
           mProgressDialog = new ProgressDialog(context);
             mProgressDialog.setMax(100);
             mProgressDialog.setProgress(0);
    }

       @Override
    protected void onPreExecute() {
           mProgressDialog =ProgressDialog.show(context, "", "Loading...",true,false);
        super.onPreExecute();
    }
     @Override
     protected void onProgressUpdate(Integer... values) {
     setProgress(values[0]);
  }

    @Override
    protected String doInBackground(String... params) {
            String data=getDatafromMemoryCard();    

        return data;  // return data you want to use here
    }
    @Override
    protected void onPostExecute(String  result) {  // result is data returned by doInBackground
        Toast.makeText(context, result, Toast.LENGTH_LONG).show();
        mProgressDialog.dismiss();
        super.onPostExecute(result);
    }
   }

如果您在单独的类中使用asynctask,则可以使用带有回调接口的AsyncTask,如下所示。
这是我之前提供的有关带有回调的AsyncTask的答案。

我不想显示那些数据,我想使用那些数据。当我在谷歌搜索我的问题时,我得到了和你类似的结果。 - Rajat
好的,我有一些模糊的想法,但我希望将这些数据传递到主UI线程。 - Rajat
@addresseerajat 回调函数将会把数据返回给您的UI线程,只需要使用相同的代码即可。 - Pragnani
问题:ProgressDialog中的context参数是什么? - Alioo
1
@Alioo 如果您将此类作为内部类包含,则可以在onCreate中从父类获取上下文。其次,如果您将其作为单独的类包含,则使用单参数构造函数进行后台任务,并从该参数获取上下文。 - Pragnani
显示剩余2条评论

1
当执行异步任务时,该任务会经历4个步骤:
1.onPreExecute(), invoked on the UI thread before the task is executed. use this to diaply progress dialog.

2.doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. Can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.

3.onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). Used to publish progress.

4.onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.

在您的activity的onCreate()方法中。
    TextView tv;
   @Override
   protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);  
    setContentView(R.layout.activity_main);
    tv= (TextView)findViewById(R.id.textView);
    new TheTask().execute();
      
  }
class TheTask extends AsyncTask<Void, Void,String> {

  protected void onPreExecute() {
  //dispaly progress dialog
 }

 protected String doInBackground(Void... params) {
   //do network operation
     return "hello"; 
 }

 protected void onPostExecute(String result) {  
  //dismiss dialog. //set hello to textview
      //use the returned value here.
     tv.setText(result.toString());
 }
 }

进行异步调用,在UI线程上通知。
更新:AsyncTask已被弃用。请切换到Kotlin协程。https://developer.android.com/kotlin/coroutines

0

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