2011-07-19 178 views
2

我正在加載一些AsyncTask中的JSON數據,因爲我想在UI中顯示下載進度。下載工作正常,並定期調用publishProgress方法(每100個JSON對象),但onProgressUpdate和onPostExecute不會實際執行,直到完成所有後臺操作(即所有需要doInBackground結果的計算)。AsyncTask的doInBackground方法阻止UI線程

登錄看起來大致是這樣的:

AsyncTaskCaller.downloadWithAsyncTask: executing AsyncTask 

MyAsyncTask.onPreExecute: AsyncTask started 

MyAsyncTask.doInBackground: Download 0% 
MyAsyncTask.doInBackground: Download 10% 
... 
MyAsyncTask.doInBackground: Download 90% 
MyAsyncTask.doInBackground: Download 100% 

AsyncTaskCaller.processResult: Results processed 

// all background calculations finished 

MyAsyncTask.onProgressUpdate: Download 0% 
MyAsyncTask.onProgressUpdate: Download 10% 
... 
MyAsyncTask.onProgressUpdate: Download 90% 
MyAsyncTask.onProgressUpdate: Download 100% 

MyAsyncTask.onPostExecute: AsyncTask ended 

MyActivity.updateUiAfterDownload 

這是我的代碼是如何調用數據:

MyActivity:

final Runnable mSynchroniseContacts = new Runnable() { 
    public void run() { 
     /** get oAuth tokens for synchronisation */ 
     MyApp app = (MyApp) getApplication(); 
     OpenAuthTokens myTokens = app.getAccessTokens(); 

     // mockup code to load contacts 
     MyContact[] contacts = AsyncTaskCaller.loadContacts(myTokens, MyActivity.this); 
    } 
}; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    // TODO Auto-generated method stub 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.synchronisation_activity); 

    statusText = (TextView) findViewById(R.id.synchronisation_status_text); 

    mSynchroniseContacts.run(); 
} 

AsyncTaskCaller:

private static JSONArray records = null; 

public static MyContact[] loadContacts(OpenAuthTokens myTokens, Context context) { 
    MyAsyncTask contactDownloader = new MyAsyncTask(context, myTokens) { 
     @Override 
     protected void onPostExecute(JSONArray result) { 
      super.onPostExecute(result); 

      records = result; // assigning result to static class variable, to avoid calling contactDownloader.get(), which apparently blocks the UI thread according to http://stackoverflow.com/questions/5583137/asynctask-block-ui-threat-and-show-progressbar-with-delay 
     } 
    }; 

    contactDownloader.execute(url); 

    // wait until contacts are downloaded 
    while(!SforceContactDownloadTask2.isFinished()) { 
     try { 
      Thread.sleep(50); 
     } catch (InterruptedException e) { 
      Log.e(TAG, e.getCause() + " - " + e.getMessage()); 
      e.printStackTrace(); 
     } 
    } 

    // some code to convert JSONArray records into MyContact[] myContacts 

    return myContacts; 
} 

MyAsyncTask(代碼如上面記錄中沒有明確粘貼):

@Override 
protected void onPreExecute() { 
    finished = false; 
} 

@Override 
protected void onPreExecute() { 
    finished = false; 
} 

@Override 
protected JSONArray doInBackground(String... url) { 

    StringBuffer dataString = new StringBuffer(); 

    try { 

     boolean isOnline = ConnectivtiyChecker.isInternetAvailable(context); 

     if (isOnline) { 

      /** send as http get request */ 
      URL urlObject = new URL(url[0]); 
      HttpURLConnection conn = (HttpURLConnection) urlObject.openConnection(); 
      conn.addRequestProperty("Authorization", "OAuth " + myTokens.get_access_token()); 

      /** prepare response reader */ 
      JSONArray records = null; 
      byte data[] = new byte[MAX_BUFFER_SIZE]; 
      int currentByteReadCount = 0; 
      InputStream stream = null; 
      BufferedInputStream input = null; 

      try { 
       /** get response input stream */ 
       stream = conn.getInputStream(); 
       input = new BufferedInputStream(stream); 

       /** read response from input stream */ 
       while ((currentByteReadCount = input.read(data)) != -1) { 
        String readData = new String(data, 0, currentByteReadCount); 
        dataString.append(readData); 

        //code to figure progress out 

        // publishing the progress (every 5%)... 
        if (progress % (total/20) == 0) { 
         publishProgress((int)(progress * 100/total)); 
        } 
       } 
      } catch (Exception e) { 
       Log.e(TAG, e.getCause() + " - " + e.getMessage()); 
       e.printStackTrace(); 
      } finally { 
       // close streams 
       if (input != null) { 
        input.close(); 
       } 
       if (stream != null) { 
        stream.close();      
       } 
      } 

      /** transform response into JSONArray */ 
      String result = dataString.toString(); 
      JSONObject object = (JSONObject) new JSONTokener(result).nextValue(); 
      records = object.getJSONArray("records"); 

      return records; 
     } else { 
      return null; 
     } 
    } catch (Exception e) { 
     Log.e(TAG, e.getCause() + " - " + e.getMessage()); 
     e.printStackTrace(); 
     return null; 
    } 
} 

@Override 
protected void onProgressUpdate(Integer... changed) { 
    Log.d(TAG, "Download " + changed[0] + "%"); 
} 

@Override 
protected void onPostExecute(JSONArray result) { 
    finished = true; 
} 

public static boolean isFinished() { 
    return finished; 
} 

任何想法如何去阻止用戶界面?

回答

4

您似乎在主應用程序線程上調用Thread.sleep()。不要這樣做。請編寫您的應用程序以正確異步。

+1

哦,我的上帝,我不敢相信我做了我沒有意識到的事情......謝謝馬克,這顯然解決了這個問題。在嘗試避免調用myAsyncTask.get()時,我只是手動執行了相同的操作 - 如果錯誤代碼可能會導致死機... – benfwirtz

+0

如果錯誤的代碼可能會導致死機。 –