2013-03-01 94 views
0

我一直在寻找如何在一段时间内实现Android的AsyncTask类。基本上,我希望它能够实现经典的场景:在我进行网络通话时简单地创建一个无限期的装载轮。但是,在实践中,我遇到了一些问题,使其按我想要的方式工作。Android的AsyncTask:多个参数,返回值,等待

我的代码看起来像这样目前:(我期望的AsyncTask实施前)

String result = timeConsumingNetworkCall(String someData, ArrayList stuff1); 
doStuff(result); 

String result = timeConsumingNetworkCall(String otherData, ArrayList stuff2); 
doOtherStuff(result); 

String result = timeConsumingNetworkCall(String dataAgain, ArrayList stuff3); 
doYetEvenMore(result); 

我希望能够重用我的AsyncTask通话将数据传递给它,它使网络通话,然后返回我可以随意处理的数据,就像我上面所做的那样。

现在 - 这个工程是完美的,当然应用程序似乎没有加载“挂起”。在来的AsyncTask。也许我还没有完全“得到它” - 但是如何将数据返回到AsyncTask的外部,以便doStuffToUI()等可以使用它?

最后,我想,如果我可以使用的AsyncTask与此类似:

String result = new PostToFile("function_name", keysAndValues).execute().getResult(); 
doStuff(result); // this shouldn't execute until the AsyncTask is done 

我要对这个权利?这是应该/可以完成的吗?下面是我的AsyncTask类,缩写为简洁。

private class PostToFile extends AsyncTask<PostToFile, Void, Void>{ 
    private String functionName; 
    private ArrayList<NameValuePair> postKeyValuePairs; 
    private String result = ""; 

    public PostToFile(String function, ArrayList<NameValuePair> keyValuePairs){ 
     functionName= function; 
     postKeyValuePairs = keyValuePairs; 
    } 

    @Override 
    protected void onPreExecute() { 
     progressDialog = ProgressDialog.show(BaseActivity.getInstance(), "Loading", "Please wait...", true, false); 
    } 

    @Override 
    protected Void doInBackground(PostToFile... params) {      
     ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); 
     nameValuePairs.add(new BasicNameValuePair(FUNCTION_KEYWORD, functionName)); 
     for (int i = 0; i < postKeyValuePairs.size(); i++)   { 
      nameValuePairs.add(postKeyValuePairs.get(i)); 
     } 

     try{ 
      // ***do the POST magic.*** 
      result = response.toString(); 
     } 
     catch (Exception e){ 
      // clean up my mess 
     } 

     return null; 
    } 

    private String getResult(){ 
     return result; // can I use this somehow??? 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     progressDialog.dismiss(); 
    } 
} 

任何帮助表示赞赏,多谢提前。如果需要,我很乐意澄清。

+0

你可以写doStuff(result);在onPostExtecute()方法 – 2013-03-01 09:11:55

+0

嗯,我真的宁愿不这样做。因为那样我就必须在每次想要PostToFile时都有多个AsyncTask对象,这只是基于我如何接收数据。这听起来很混乱,代码太多。我只是想把数据放进去,然后解析它。 – 2013-03-01 09:20:46

+0

@ unexpected62我有同样的问题,如果你已经解决了这个问题,请帮助我如何实现这个 – CoronaPintu 2013-05-27 05:47:46

回答

1

doStuff(result);这不应该执行,直到的AsyncTask完成

,那么你将需要使用AsyncTask.get()如果有必要,这使得等待计算完成,然后获取其结果。

因为调用AsyncTask.get()冻结主UI线程,直到doInBackground执行没有完成,那么您将需要使用线程来避免冻结UI,runOnUiThread用于在AsyncTask执行完成后更新UI元素。

例子: -

public void ThreaddoStuff(){ 

Thread th=new Thread(){ 
    @Override 
    public void run(){ 
     // start AsyncTask exection here 
     String result = new PostToFile("function_name", 
         keysAndValues).execute().get().getResult(); 

    // now call doStuff by passing result 
    doStuff(result); 
    } 
    }; 
th.start(); 
} 
+0

我害怕这个......有一个更好的办法......你告诉我,当我做'新AsynTaskObject(params).execute()'会开始,然后在完成之前立即执行下一行?我想要做的就是制作该死的装载轮,而不是继续运行我的程序!我不能继续,除非我有用于填充下一个屏幕的UI的数据!必须有一些基本的东西我失踪/不理解。 – 2013-03-01 09:57:46

+0

'你告诉我,当我做新的AsynTaskObject(params).execute()时,它会启动,然后在完成上一行之前立即执行下一行?' - 是的,如果你有这种AsynTask行为在不调用get()方法的情况下调用它,在这种情况下,您需要在onPostExecute方法内调用doStuff(result);因为在doInBackground执行完成时调用此方法。 '我所要做的就是动画这个该死的加载轮':: ---为此,您将需要使用runOnUiThread更新线程 – 2013-03-01 10:08:35

1

请使用默认onPostExecute实现可重复使用的异步任务,然后覆盖默认实现为每个电话:

public static class PostToFile extends AsyncTask<Void, Void, String> { 
     private String functionName; 
     private ArrayList<NameValuePair> postKeyValuePairs; 
     private String result = ""; 

     public PostToFile(String function, ArrayList<NameValuePair> keyValuePairs){ 
      functionName= function; 
      postKeyValuePairs = keyValuePairs; 
     } 

     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 
      // show progress bar 
     } 

     @Override 
     protected String doInBackground(Void... arg0) { 
      // make request and get the result 
      return null; // return result 
     } 

     @Override 
     protected void onCancelled(String result) { 
      super.onCancelled(result); 
      // hide progress bar 
     } 

     @Override 
     protected void onPostExecute(String result) { 
      super.onPostExecute(result); 
      // hide progress bar 
     } 
    } 

执行你的异步任务:

new PostToFile(function, keyValuePairs) { 

     @Override 
     protected void onPostExecute(String result) { 
      super.onPostExecute(result); // this will hide a progress bar 

      doStuff(result); 
     } 
}.execute(); 

new PostToFile(otherFunction, otherKeyValuePairs) { 

     @Override 
     protected void onPostExecute(String result) { 
      super.onPostExecute(result); // this will hide a progress bar 

      doOtherStuff(result); 
     } 
}.execute(); 
+0

的加载轮,我明白了,而且我确实已经开始实施了。然而,问题仍然是,当我执行新的'AsynTaskObject(params).execute()'时,会启动,然后在'execute()'必须完成之前立即执行下一行。把所有东西放在'onPostExecute()'里是不可行的,因为它基本上是我程序的其余部分,哈哈。在我处理完这些数据之前,我无法继续前进,我只想在发生这种情况时展示一个装载轮。也许AsyncTask实际上并不是我需要的?也许只是一个新的线程ProgressDialog? – 2013-03-01 17:57:32

+0

然后在一个doInBackground方法中完成所有工作(多个请求和结果解析)。或者将进度条移动到活动并在执行异步任务之前启动它,并将其隐藏在最后一次异步任务的onPostExecute中(或者更好地说,当所有任务完成时) – vokilam 2013-03-01 20:08:40