2012-10-09 45 views
0

我有一个应用程序调用web服务,它返回一个xml字符串。以下类处理String并将所需数据放入ArrayList中。 ArrayList是TwoDimentionalArrayList类型。我发布了下面这两个类。他们都很好。AsyncTask没有填充ArrayList

public class RetrieveExtraDetails { 

    private static final String TAG = RetrieveExtraDetails.class.getSimpleName(); 
    DocumentBuilderFactory builderFactory; 
    DocumentBuilder builder; 
    Document document; 
    TwoDimentionalArrayList<String> arrayList; 


    public RetrieveExtraDetails() { 
     super(); 
     arrayList = new TwoDimentionalArrayList<String>(); 
     builderFactory = DocumentBuilderFactory.newInstance(); 
     document = null; 
     try { 
      builder = builderFactory.newDocumentBuilder(); 
      Log.e(TAG, "built the dom factory"); 
     } catch (ParserConfigurationException e) { 
      e.printStackTrace(); 
     } 

    }// end of constructor 


public TwoDimentionalArrayList<String> getExtraDetails(String xmlStr){ 

    ArrayList<String> array = null; 

     try { 

      document = builder.parse(new InputSource(new StringReader(xmlStr))); 
      Log.e(TAG, "document = " + document); 

     } catch (SAXException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     Element rootElement = document.getDocumentElement(); 
     NodeList nodes = rootElement.getChildNodes(); 

     Node rota = nodes.item(0); 
     NodeList callList = rota.getChildNodes(); 

     for(int i = 0; i < callList.getLength(); i++){ 

      Node call = callList.item(i); 
      NodeList callChildrenList = call.getChildNodes(); 
      array = new ArrayList<String>(); 

     for(int j = 0; j < callChildrenList.getLength(); j++){ 

       Node callChild = callChildrenList.item(j); 

       if(callChild.getNodeName().equalsIgnoreCase("RecTypeID")){ 
         String nodeData = callChild.getTextContent(); 
         Log.e(TAG, "RecTypeID = " + nodeData); 
         array.add(nodeData); 

       }else if (callChild.getNodeName().equalsIgnoreCase("RecType")){ 

        String nodeData = callChild.getTextContent(); 
         Log.e(TAG, "RecType = " + nodeData); 
         array.add(nodeData); 
       }else if (callChild.getNodeName().equalsIgnoreCase("Name")){ 

        String nodeData = callChild.getTextContent(); 
         Log.e(TAG, "Name = " + nodeData); 
         array.add(nodeData); 
       }else if (callChild.getNodeName().equalsIgnoreCase("Relationship")){ 

        String nodeData = callChild.getTextContent(); 
         Log.e(TAG, "Relationship = " + nodeData); 
         array.add(nodeData); 
       }else if (callChild.getNodeName().equalsIgnoreCase("Address")){ 

        String nodeData = callChild.getTextContent(); 
         Log.e(TAG, "Address = " + nodeData); 
         array.add(nodeData); 
       }else if (callChild.getNodeName().equalsIgnoreCase("Postcode")){ 

        String nodeData = callChild.getTextContent(); 
         Log.e(TAG, "Postcode = " + nodeData); 
         array.add(nodeData); 
       }else if (callChild.getNodeName().equalsIgnoreCase("TelNo")){ 

        String nodeData = callChild.getTextContent(); 
         Log.e(TAG, "TelNo = " + nodeData); 
         array.add(nodeData); 
       }else if (callChild.getNodeName().equalsIgnoreCase("Keysafe")){ 

        String nodeData = callChild.getTextContent(); 
         Log.e(TAG, "Keysafe = " + nodeData); 
         array.add(nodeData); 
       }else if (callChild.getNodeName().equalsIgnoreCase("Notes")){ 

        String nodeData = callChild.getTextContent(); 
         Log.e(TAG, "Notes = " + nodeData); 
         array.add(nodeData); 
       }else if (callChild.getNodeName().equalsIgnoreCase("Meds")){ 

        String nodeData = callChild.getTextContent(); 
         Log.e(TAG, "Meds = " + nodeData); 
         array.add(nodeData); 
       } 



      }// end of j loop 
     arrayList.add(i, array); 
     }//end of i loop 

     return arrayList; 

    }//end of getExtraDetails 



}//end of class 

public class TwoDimentionalArrayList<T> extends ArrayList<ArrayList<T>> { 

    private static final long serialVersionUID = 1L; 

    public void addToInnerArray(int index, T element) { 
     while (index >= this.size()) { 
      this.add(new ArrayList<T>()); 
     } 
     this.get(index).add(element); 
    } 

    public void addToInnerArray(int index, int index2, T element) { 
     while (index >= this.size()) { 
      this.add(new ArrayList<T>()); 
     } 

     ArrayList<T> inner = this.get(index); 
     while (index2 >= inner.size()) { 
      inner.add(null); 
     } 

     inner.set(index2, element); 
    } 
} 

现在在下面的类中,我有一个ArrayList,它在类范围内设置。以下类应使用AsyncTask的结果填充此数组列表。在onPostExecute中,数组的大小为4,但是当我记录了类作用域数组的值时,在由AsyncTask设置后它为0。我甚至在Async上调用.get()以确保活动在恢复执行之前等待来自Async的结果。

任何想法为什么这个ArrayList没有被填充?我已经提出了一个类似的问题,但在这个问题中,我已经减少了代码,以便更容易理解问题。谢谢。

ArrayList<ArrayList<String>> array; 

public class GetRotaDetails extends NfcBaseActivity{ 



    ArrayList<ArrayList<String>> array; 

    private static final String TAG = GetRotaDetails.class.getSimpleName(); 
    NfcScannerApplication nfcscannerapplication; 
    String callID; 
    ListView listView; 
    Intent intent; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     //set titlebar to carer's name 
     nfcscannerapplication = (NfcScannerApplication) getApplication(); 
     intent = this.getIntent(); 
     Cursor cursorCarerName = nfcscannerapplication.loginValidate.queryAllFromCarer(); 
     cursorCarerName.moveToLast(); 
     String carerTitleName = cursorCarerName.getString(cursorCarerName 
       .getColumnIndex(LoginValidate.C_CARER_NAME)); 
     setTitle(carerTitleName + " is currently logged in"); 


     array = new ArrayList<ArrayList<String>>(); 

     listView = (ListView) findViewById(R.id.getrotadetailslistview); 
     setContentView(R.layout.getrotadetailslayout); 


     callID = intent.getStringExtra("callIDExtra"); 
     String[] params = { callID }; 

     AsyncGetRotaDetails agrd = new AsyncGetRotaDetails(); 
     try { 
      agrd.execute(params).get(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 


     Log.e(TAG, "array size = " + array.size()); 



    }// end of onCreate 



    private class AsyncGetRotaDetails extends AsyncTask<String, Void, String> { 

     ProgressDialog progressDialog; 
     String rotaDetails = null; 

     @Override 
     protected void onPreExecute() { 
      progressDialog = ProgressDialog 
        .show(GetRotaDetails.this, "Connecting to Server", 
          " retrieving rota details...", true); 

     }; 

     @Override 
     protected String doInBackground(String... params) { 

      try { 
       Log.e(TAG, "inside doInBackground"); 

       rotaDetails = nfcscannerapplication.loginWebservice.getRotaDetail(params[0]); 

      } catch (Exception e) { 

       e.printStackTrace(); 

      } 
      return rotaDetails; 

     } 

     @Override 
     protected void onPostExecute(String xmlResult) { 
      super.onPostExecute(xmlResult); 
      if (progressDialog != null) 
       progressDialog.dismiss(); 

       RetrieveExtraDetails red = new RetrieveExtraDetails(); 
       array = red.getExtraDetails(xmlResult); 
       Log.e(TAG, "array from WS = " + array.size()); 


     }// end of postExecute 

    }//end of Async 


} 
+0

我对'get()'方法不熟悉,但是我想知道是否有任何保证它不会在'onPostExecute()'之前返回结果? –

+0

你的AsnycTask很奇怪。而不是检查'progressDialog'是否为空,请检查您的结果数据是否为空。您的进度对话框永远不会为空,除非世界结束并且在对象使用之前不再调用构造函数。此外,'array = red.gotExtraDetails(xmlResult)'应该在后台完成。 – AedonEtLIRA

+0

另外,请检查您的节点名称以确保它们符合预期。 – AedonEtLIRA

回答

2

我的猜测是对的。 AsyncTask.get()方法可能会在doInBackground()方法结束后返回结果,但在方法启动之前。因此,从技术上讲,您的数组在当时可能仍然是空的。

另外,启动后台线程并阻止主线程是非常奇怪的。重点是什么?

+0

我同意@Kzinch。调用'get'没有意义,因为它会阻塞你的主线程。在你的主类中打印数组的大小也没有意义。你想对调用Web服务的结果进行任何操作都应该在'onPostExecute'中完成。 –