【问题标题】:AsyncTask return valueAsyncTask 返回值
【发布时间】:2011-03-28 10:13:50
【问题描述】:

我的 android 应用程序连接到我的网站以检索和上传信息,因此我使用 AsyncTask 线程。

在一个实例中,我需要我的线程向我的主线程返回一个真值或假值。

有没有办法从 AsyncTask 执行函数中获取这个返回值?

当我执行以下操作时:

Toast.makeText(Locate.this, "Testing : "+locationUpdate.execute(location), Toast.LENGTH_LONG).show();

我只是得到了很多胡言乱语。

我认为我需要一种暂停主线程直到第二个线程完成的方法。第二个线程调用主线程中的一个函数来设置我的返回值。 所以当第二个线程完成时,主线程可以取消暂停并访问第二个线程设置的返回值 如果这个逻辑是合理的,请提供建议...谢谢!

【问题讨论】:

    标签: android return-value android-asynctask


    【解决方案1】:

    您可以为此使用 AsyncTask get() 方法。如果需要,它会等待计算完成,然后检索其结果:

    Toast.makeText(Locate.this, "Testing : " + locationUpdate.execute(location).get(), Toast.LENGTH_LONG).show();
    

    但请务必不要长时间阻塞主线程,因为这会导致 UI 无响应和ANR

    更新
    我错过了关于异步 web 下载/上传的问题。 Web/网络操作应该被认为是一个漫长的过程,因此“暂停 UI 线程并等待下载完成” 的方法总是错误的。使用通常的结果发布方法(例如:AsyncTask.onPostExecute、Service + sendBroadcast、Volley、RoboSpice、DataDroid 等库)。

    【讨论】:

    • 不要使用get!!!它冻结了用户界面。 stackoverflow.com/questions/9019249/…(这发生在我身上,所以我把这个贴在我最初找到建议的地方)
    • @aldo.roman.nurena 阅读我回答的最后一句话:be sure to not block the main thread for a long period of time, as this will lead to unresponsive UI and ANR。如果 AsyncTask 执行时间超过 200 毫秒,则此方法肯定不是最佳选择,而应使用通常的结果发布(AsyncTask.onPostExecute)。顺便说一句,还有更灵活的 AsyncTask.get() 方法版本,它允许您指定等待 AsyncTask 的最长时间。
    • 在这个问题的情况下,它连接到一个网站并下载数据。这总是一个很长的时间,至少足以让用户注意到,这是一个不好的模式。如果执行需要下载的数据,则提供超时参数可能会导致应用崩溃。
    • @aldo.roman.nurena 你是对的关于网络下载,这是一项长期任务(我想我错过了 OP 询问异步 web 操作) - 通常的结果应该使用发布方法(使用 AsyncTask.onPostExecute、Service 或 Volley 等库)。我已经更新了答案。但只是为了澄清(在问题范围之外) - 我看不出timeout parameter may crush the app。在超时的情况下会抛出一个TimeoutException,因为它已经被检查过了,你必须抓住它并提供一些“发生超时”的逻辑。
    • 在我的应用程序(类似 Dropbox 的应用程序)中,我需要下载文件夹中包含的文件,以便用户打开它们。如果“点击”但现在已下载,则应用程序崩溃,因为视图没有收到任何数据。你是对的,例外是一个很好的解决方案。
    【解决方案2】:

    Handler 是最好的方法 在onPostExcecute() 方法中简单地做

    @Override
        protected void onPostExecute(Boolean bool) {
            super.onPostExecute(bool);
               Message msg=new Message();
                msg.obj=bool;
                mHandler.sendMessage(msg);
            }
        }
    

    您的消息处理程序将是

    mHandler = new Handler() { 
        @Override 
        public void handleMessage(Message msg) { 
            bool i=(String)msg.obj;
        }
     };
    

    【讨论】:

    • 在这种情况下使用处理程序是完全没有必要的。您将带有处理程序的返回值发送到(可能)UI,但您可以通过简单地调用使用布尔值并更新 UI 的方法(主要是关闭对话框并更新视图内容)来访问 onPostExecute() 中的 UI。你做的更复杂,它应该是......
    • 我尝试了你的方法,但我的布尔值在我的 asyncTash 完成之前不会改变。同时,当我实际需要它等待正确的返回值时,主线程继续执行。
    【解决方案3】:
    public class RunWebScript {
    String mString;
    public RunWebScript(String url){
        try {   
            URL updateURL = new URL(url);  
            URLConnection conn = updateURL.openConnection(); 
            // now read the items returned...
            InputStream is = conn.getInputStream();  
            BufferedInputStream bis = new BufferedInputStream(is);  
            ByteArrayBuffer baf = new ByteArrayBuffer(50);  
            int current = 0;  
            while((current = bis.read()) != -1){  
                baf.append((byte)current);  
            }   
            String s = new String(baf.toByteArray());
             mString = s;
        } catch (Exception e) {  
            Log.e("ANDRO_ASYNC", "exception in callWebPage",e); 
            mString = "error";
        }
    }
    public String getVal(){
        return mString;
    }   
    

    }

    这被执行为...(显示调用类中方法的结尾

            asyncWebCall (url1,CONSTANT);
    }
    private void asyncWebCall(String url,int actionPostExecute){
        new WebCall().execute(url,String.format("%d",actionPostExecute));
    }   
    

    业务的异步部分是......注意 onPostExecute 中的 case 语句,这是再次将返回值返回到程序的关键。注意调用 new WebCall().execute(url,String.format("%d",actionPostExecute));是线程中完成的最后一件事,不能执行更多语句,控制通过 onPostExecute 返回。

    class WebCall extends AsyncTask<String, String, String>{
        int chooser = -1;
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        @Override   
        protected String doInBackground(String... params) {
            try {
                chooser = Integer.parseInt(params[1]);
            } catch(NumberFormatException nfe) {
                Log.d("ANDRO_ASYNC",String.format("asyncReturn() mString numberformatexception = %s",params[1]));
                chooser = 0;
            }
            return(new RunWebScript(params[0])).getVal();           
        }
        protected void onProgressUpdate(String... progress) {       
        }
        @Override
        protected void onPostExecute(String gotFromDoInBkgnd) {
            Log.d("ANDRO_ASYNC",String.format("chooser = %s",chooser));
            switch (chooser){
            case CONSTANT:
                printStringx(gotFromDoInBkgnd);
                asyncWebCall(url2,5); 
                break;
            case 0:
                Log.d("ANDRO_ASYNC",String.format("case 0 = %s",gotFromDoInBkgnd));
                break;
            case 5:
                Log.d("ANDRO_ASYNC",String.format("case 5 = %s",gotFromDoInBkgnd));
                asyncWebCall(url3,7);
    
                break;
    
            default:
                Log.d("ANDRO_ASYNC",String.format("man we got problems = %s",gotFromDoInBkgnd));
                break;
            }
        }
    

    } // 课程结束

    【讨论】:

      【解决方案4】:

      这是一个从异步任务返回值问题的完整示例。可能会出现很多任务一个接一个地异步完成。

      基础知识。 1. 从类中获取返回值。

      public class Snippet {
      int computVal;
      public Snippet(){
          computVal = 17*32; 
      }
      public int getVal(){
          return computVal;
      }   
      

      }

      这被称为...

      int hooray = (new Snippet()).getVal();
      

      【讨论】:

        猜你喜欢
        • 2019-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-21
        相关资源
        最近更新 更多