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;
}
任何想法如何去阻止用戶界面?
哦,我的上帝,我不敢相信我做了我沒有意識到的事情......謝謝馬克,這顯然解決了這個問題。在嘗試避免調用myAsyncTask.get()時,我只是手動執行了相同的操作 - 如果錯誤代碼可能會導致死機... – benfwirtz
如果錯誤的代碼可能會導致死機。 –