2012-10-09 2 views
0

xml String을 반환하는 webservice를 호출하는 앱이 있습니다. 다음 클래스는 String을 처리하고 필요한 데이터를 ArrayList에 저장합니다. ArrayList는 TwoDimentionalArrayList 유형입니다. 이 2 개의 클래스를 아래에 게시하십시오. 둘 다 잘 작동합니다.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가 있습니다. 다음 클래스는이 arrayList에 AsyncTask의 결과를 채워야합니다. onPostExecute에서 배열의 크기는 4이지만 클래스 범위 배열의 값을 로그 아웃하면 AsyncTask에 의해 설정된 후 0이됩니다. Async에서 .get()을 호출하여 Activity가 실행을 다시 시작하기 전에 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'가 null인지 확인하는 대신 결과 데이터가 null인지 확인하십시오. 세상이 끝나고 생성자가 객체 사용 전에 더 이상 호출되지 않는 한, 진행 대화 상자는 null이 될 수 없습니다. 또한'array = red.gotExtraDetails (xmlResult)'가 백그라운드에서 수행되어야한다. – AedonEtLIRA

+0

또한 노드 이름을 확인하여 예상대로 노드 이름을 확인하십시오. – AedonEtLIRA

답변

2

제 생각에 맞았습니다. AsyncTask.get() 메서드는 doInBackground() 메서드가 끝난 후 결과가 반환 될 수 있지만 onPostExecute() 메서드가 시작되기 전에 결과를 반환 할 수 있습니다. 따라서 기술적으로 배열이 아직 비어있을 수 있습니다.

또한 배경 스레드를 시작하고 주 스레드를 차단하는 것은 매우 이상합니다. 점은 무엇인가?

+0

@Kzinch에 동의하겠습니다. 메인 스레드를 차단할 때'get '을 호출 할 필요가 없습니다. 메인 클래스 내에 배열의 크기를 출력하는 것도 없습니다. 웹 서비스를 호출 한 결과에 대해 수행하고자하는 조작은'onPostExecute'에서 수행되어야합니다. –

관련 문제