Java 异步任务';s get()方法:是否有任何情况下它实际上是最好的选择?

Java 异步任务';s get()方法:是否有任何情况下它实际上是最好的选择?,java,android,android-asynctask,Java,Android,Android Asynctask,在回答了这个问题之后,我对使用Android的AsyncTask类的get()方法的意义/有用性产生了怀疑 public final Result get () Waits if necessary for the computation to complete, and then retrieves its result. 基本上是AsyncTask类的同步解决方案,在后台操作完成之前阻止(冻结)UI 除了测试目的,甚至在那些情况下,我真的不能认为在任何情况下它实际上是一个好的解决方案,

在回答了这个问题之后,我对使用Android的AsyncTask类的get()方法的意义/有用性产生了怀疑

public final Result get ()

Waits if necessary for the computation to complete, and then retrieves its result. 
基本上是AsyncTask类的同步解决方案,在后台操作完成之前阻止(冻结)UI

除了测试目的,甚至在那些情况下,我真的不能认为在任何情况下它实际上是一个好的解决方案,但我可能错了,所以我感到好奇


如果需要用户实际等待AsyncTask完成,则可以显示对话框或ProgressDialog,随时控制UI。我知道这并不完全相同,但我认为这是一种比使用
get()
方法好得多的方法。

在UI线程中永远不应该使用
get
方法,因为它会(正如您所注意的)冻结您的UI。应该在后台线程中使用它来等待任务结束,但一般来说,尽量避免
AsyncTask


我建议使用回调或eventbus作为替换。

如果并行运行多个异步任务,您可能希望某些任务等待其他任务的结果


但是,我认为您应该避免并行运行太多异步任务,因为这会降低设备的速度。

我通常使用handler类来完成这项任务(异步加载媒体)。 比如:


我发布了我自己的答案,因为这是我此刻的想法,没有人给出

我的好奇心仍然存在,所以我不会把这个标记为正确的。如果有人出色地回答了这个问题,我会认为他/她的回答是正确的

我的答案是,实际上没有使用AsyncTask的
get()
方法是最佳解决方案的场景

嗯,使用这种方法是没有意义的。我的意思是,似乎总有更好的解决办法


同样地,我会说这在语义上是令人震惊的,因为调用它会将您的AsyncTask更改为有效的“SyncTask”。

如文档所示:

如有必要,等待计算完成,然后 检索其结果。“

因此,您必须避免在UI线程上调用它,否则将得到
NetworkOnMainThreadException
。我会在涉及网络操作的测试环境中使用它,或者等待另一个任务完成


编辑:关于
networkMainThreadException
AsyncTask
不是执行后台操作的唯一方法,我错了。事实上,文档中说,
AsyncTask
应该只用于最多需要几秒钟的操作。所以,如果您有需要更长时间的任务,那么应该通过实现这些任务的类对它们进行编码。其他(非AsyncTask)线程中的此类任务可能需要等待
AsyncTask
完成,因此在我看来,没有人希望使用
AsyncTask.get()
的情况是错误的

更新:针对一条评论,为了强调这可能是对
AsyncTask.get()
的有效使用,以下情况是可能的:
  • 可能存在从UI线程启动的
    AsyncTask
    ,这可能涉及通过internet进行通信,例如加载网页或与服务器通信。无论
    AsyncTask
    的结果是什么,都需要部分(或全部)结果来更新屏幕。因此,一个
    AsyncTask
    及其
    doInBackground
    在UI线程上后跟
    onPostExecute
    是有意义的。
  • 每当UI线程启动一个
    AsyncTask
    时,它都会将
    AsyncTask
    对象放入队列中,用于在结果可用后由单独的后台线程进行附加处理。
  • 对于队列中的每个
    异步任务
    ,后台线程依次使用
    AsyncTask.get()
    等待任务完成,然后再执行附加处理。附加处理的一个明显例子就是将所有此类
    AsyncTask
    活动记录到internet上的服务器上,因此在后台这样做是有意义的。
下面的代码说明了我的意思。当应用程序想要执行异步任务时,它会调用KickOffAsynctask(…),并且有一个后台线程,一旦任务完成,它会自动拾取任务进行后期处理

public class MyActivity extends Activity {

    static class MyAsyncTaskParameters { }
    static class MyAsyncTaskResults { }

    Queue<MyAsyncTask> queue;   // task queue for post-processing of AsyncTasks in the background
    BackgroundThread b_thread;  // class related to the background thread that does the post-processing of AsyncTasks

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);     
        queue = new  ConcurrentLinkedQueue<MyAsyncTask>();
        b_thread = new BackgroundThread(queue);
        b_thread.Start();       
    }

    void KickOffAsynctask(MyAsyncTaskParameters params) {
        MyAsyncTask newtask = new MyAsyncTask();
        newtask.execute(params);
        synchronized(queue) {
            queue.add(newtask);
        }
    }

    static class MyAsyncTask extends AsyncTask<MyAsyncTaskParameters, Void, MyAsyncTaskResults> {

        @Override
        protected MyAsyncTaskResults doInBackground(MyAsyncTaskParameters... params) {
            MyAsyncTaskResults results = new MyAsyncTaskResults();
            // do AsyncTask in background
            return results;
        }

        @Override
        protected void onPostExecute(MyAsyncTaskResults res){
            // take required results from MyAsyncResults for use in the user interface
        }

    }

    static class BackgroundThread implements Runnable {
        // class that controls the post processing of AsyncTask results in background

        private Queue<MyAsyncTask> queue;
        private Thread thisthread;
        public boolean continue_running;

        public BackgroundThread(Queue<MyAsyncTask> queue) {
            this.queue=queue; thisthread = null; continue_running = true;
        }

        public void Start() {
            thisthread = new Thread(this);
            thisthread.start();
        }

        @Override
        public void run() {
            try {
                do {
                    MyAsyncTask task;
                    synchronized(queue) {
                        task = queue.poll();
                    }
                    if (task == null) {
                        Thread.sleep(100);
                    } else {
                        MyAsyncTaskResults results = task.get();
                        // post processing of AsyncTask results in background, e.g. log to a server somewhere
                    }
                } while (continue_running);     
            } catch(Throwable e) {
                e.printStackTrace();
            }           
        }

    }

}
公共类MyActivity扩展活动{
静态类MyAsyncTaskParameters{}
静态类MyAsyncTaskResults{}
Queue Queue;//用于后台异步任务后处理的任务队列
BackgroundThread b_thread;//与执行异步任务后处理的后台线程相关的类
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
队列=新的ConcurrentLinkedQueue();
b_线程=新的背景线程(队列);
b_thread.Start();
}
无效KickOffAsynctask(MyAsyncTaskParameters参数){
MyAsyncTask newtask=新建MyAsyncTask();
newtask.execute(params);
已同步(队列){
queue.add(newtask);
}
}
静态类MyAsyncTask扩展了AsyncTask{
@凌驾
受保护的MyAsyncTaskResults doInBackground(MyAsyncTaskParameters…params){
MyAsyncTaskResults=新建MyAsyncTaskResults();
//在后台执行异步任务
返回结果;
}
@凌驾
受保护的void onPostExecute(MyAsyncTaskResults res){
//从MyAsyncResults中获取所需结果,以便在用户界面中使用
}
}
静态类BackgroundThread实现Runnable{
//类,该类控制后台异步任务结果的后处理
专用队列;
专用线程
public class MyActivity extends Activity {

    static class MyAsyncTaskParameters { }
    static class MyAsyncTaskResults { }

    Queue<MyAsyncTask> queue;   // task queue for post-processing of AsyncTasks in the background
    BackgroundThread b_thread;  // class related to the background thread that does the post-processing of AsyncTasks

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);     
        queue = new  ConcurrentLinkedQueue<MyAsyncTask>();
        b_thread = new BackgroundThread(queue);
        b_thread.Start();       
    }

    void KickOffAsynctask(MyAsyncTaskParameters params) {
        MyAsyncTask newtask = new MyAsyncTask();
        newtask.execute(params);
        synchronized(queue) {
            queue.add(newtask);
        }
    }

    static class MyAsyncTask extends AsyncTask<MyAsyncTaskParameters, Void, MyAsyncTaskResults> {

        @Override
        protected MyAsyncTaskResults doInBackground(MyAsyncTaskParameters... params) {
            MyAsyncTaskResults results = new MyAsyncTaskResults();
            // do AsyncTask in background
            return results;
        }

        @Override
        protected void onPostExecute(MyAsyncTaskResults res){
            // take required results from MyAsyncResults for use in the user interface
        }

    }

    static class BackgroundThread implements Runnable {
        // class that controls the post processing of AsyncTask results in background

        private Queue<MyAsyncTask> queue;
        private Thread thisthread;
        public boolean continue_running;

        public BackgroundThread(Queue<MyAsyncTask> queue) {
            this.queue=queue; thisthread = null; continue_running = true;
        }

        public void Start() {
            thisthread = new Thread(this);
            thisthread.start();
        }

        @Override
        public void run() {
            try {
                do {
                    MyAsyncTask task;
                    synchronized(queue) {
                        task = queue.poll();
                    }
                    if (task == null) {
                        Thread.sleep(100);
                    } else {
                        MyAsyncTaskResults results = task.get();
                        // post processing of AsyncTask results in background, e.g. log to a server somewhere
                    }
                } while (continue_running);     
            } catch(Throwable e) {
                e.printStackTrace();
            }           
        }

    }

}
    private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
    }

new DownloadFilesTask().get(5000, TimeUnit.MILLISECONDS);
private class Adapter extends BaseAdapter implements Filterable{
    getFilter(){
        return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            List<String> suggestions = MyApiSuggestionsApi(constraint).get();
            return packageAsFilterResults(suggestions);
        }
    }
}