2010-12-02 4 views
9

URL에 연결하고, JSON을 파싱하고, 파싱하는 동안 불확실한 ProgressDialog를 표시하고 결과를 키 - 값으로 반환하기 위해 AsyncTask 확장 클래스를 사용하려고합니다. 쌍을 HashMap에서 주 활동으로 보냅니다. 그런 다음 HashMap의 결과가 주 활동에 의해 읽혀 양식 필드에 입력됩니다. 그러나, AsyncTask (println 문으로 입증 됨)에서 HashMap을 채우더라도 HashMap을 반환하는 주 Activity에서 메서드를 호출하면 빈 결과가 나타납니다. 이것이 내가 잘못하고있는 것인지 아니면 AsyncTask의 기능을 오해하고 있는지 알 수는 없습니다.안드로이드 - AsyncTask의 결과가 메인 액티비티로 리턴되지 않습니다.

AsyncTask를 활동으로 확장하는 클래스를 변환하는 것에 대해 토론하고 있습니다. 본질적으로 사용자는이 데이터 검색/구문 분석 중에 다른 작업을 할 수 없어야하며 ProgressDialog가 사라져야 응용 프로그램과 다시 상호 작용할 수 있습니다 (또는 뒤로 단추를 눌러서). 또한, 내 응용 프로그램은 예외가 잡힌 (URL에 연결할 수 없으며, 잘못된 JSON, 검색 할 제품 ID를 찾을 수없는) AsyncTask의 특정 케이스를 처리 할 수 ​​있어야하며 이러한 예외에 대한 맞춤 오류 대화 상자가 필요합니다. 예외가 잡히는 지에 따라 finish()를 호출 할 때 다른 결과 코드를 보낼 수 있으므로이 클래스가 Activity 인 경우 쉽게이 작업을 수행 할 수 있습니다.

정보가 모아지고 파싱되는 동안 사용자가 다른 작업을 수행하지 않으므로 AsyncTask가 최상의 솔루션인지 여부에 대해 다시 한 번 확실하지 않습니다. 새로운 액티비티가 의미가 있는지 아니면 내가 백그라운드 스레드의 구현을 망가 뜨리고 있는지 알려주세요.

MainActivity.java

public class ProductLookup extends AsyncTask<Object, Void, HashMap<String, String>> { 
    private String mProductID; 
    private Context mContext; 
    HashMap<String, String> mProductInfo; 
    ProgressDialog mDialog; 

    public ProductLookup(String id, Context applicationContext) { 
     mProductID = id; 
     mContext = applicationContext; 
     mProductInfo = new HashMap<String, String>(); 
    } 

    @Override 
    protected void onPreExecute() { 
     mDialog = new ProgressDialog(mContext); 
     mDialog.setMessage("Loading product info. Please wait..."); 
     mDialog.setIndeterminate(true); 
     mDialog.setCancelable(false); 
     mDialog.show(); 
    } 

    @Override 
    protected void onPostExecute(HashMap<String, String> result){ 
     super.onPostExecute(result); 
     mDialog.dismiss(); 
     mProductInfo = result; 
    } 


    @Override 
    protected HashMap<String, String> doInBackground(Object... params) { 
     try { 
      // Connect to URL, parse JSON, and add key-value pairs to mProductInfo... 

     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 
     finally { 
      try { 
       // Close input/output reader variables 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     return mProductInfo; 

    } 

    public HashMap<String, String> getProductInfo(){ 
     return this.mProductInfo; 
    } 

} 

답변

5

이 같은 스레드 실행하고 결과를 기다리지 않고 .execute()를 발행

mInitiateProductLookupButton.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View v) { 
       ProductLookup pl = new ProductLookup(id, MainActivity.this); 
       pl.execute(); 

       // The below variable is always empty! 
       HashMap<String, String> productInfo = pl.getProductInfo(); 
       applyProductInfoToFormFields(productInfo); 
      } 
     }); 

ProductLookup.java.

데이터를 아직로드하지 않았으므로이 데이터를 나중에 호출하면 아무 것도 표시되지 않습니다.

당신은 세터 MainActivity.this.setProductInfo(result)

+1

, 나는 나를 컴파일 못하게 오류가 발생 : 아이 private 클래스로 MainActivity의 내부 AsyncTask를 작성 – Keeb13r

+2

"유형의 MainActivity의 어떤 둘러싸는 인스턴스 범위에 액세스 할 수 없습니다" . – Pentium10

+0

하위 개인 클래스는 정확히 어떻게 만듭니 까? – Keeb13r

3

당신을 위해 몇 가지 미스 개념이 있습니다 통해 활동에 직접 PostExecuted에 결과를 설정해야합니다. AsyncTask.execute() 이후의 명령문은 호출 직후에 실행됩니다. doInBackground가 다른 스레드에서 수행하는 동안. 여기서 productInfo 맵을 사용할 때 doInBackground가 완료되지 않으므로 결과가 채워지지 않습니다.

쉬운 솔루션은 onPostExecute 메소 드에서 결과를 사용하는 것입니다. 나는 그렇게하려고하면

protected void onPostExecute(HashMap<String, String> result){ 
     mDialog.dismiss(); 
     mProductInfo = result; 
applyProductInfoToFormFields(productInfo); 

    } 
+0

applyProductInfoToFormFields() 메소드는 MainActivity에 있지만 양식 필드를 나타내는 해당 클래스의 데이터 멤버가 새 값 (예 : JSON에서 파싱 된 값)을 갖도록 설정합니다. . ProductLookup에서 해당 메서드를 호출 할 수 있다고 생각하지 않았습니다. 또한 GUI를 수정/상호 작용할 예정이라면 MainActivity에서 계속해야한다고 생각했습니다. ProductInfo는 새 인스턴스를 저장하지 않고 필드의 데이터 멤버를 어떻게 알 수 있습니까? – Keeb13r

+0

나는 당신을 올바르게 얻지 못한다. 나는 당신에게 GUI 컨트롤 폼 applyProductInfoToFormFields()에 접근 할 필요가 있다고 생각한다. 그렇다면 가장 좋은 방법은 모든 GUI 구성 요소를 전역으로 선언하여 어디서나 액세스 할 수 있도록하는 것입니다. –

+0

그리고 ProductLookup에서 MainActivity의 데이터 멤버를 어떻게 참조 할 수 있습니까? 글로벌화하기 위해서는 무엇을 바꾸어야합니까? – Keeb13r

관련 문제