【发布时间】:2011-12-06 21:53:57
【问题描述】:
我的一个活动中的一个按钮调用了一个 AsyncTask,它更新了 ListView 的 SimpleCursorAdapter 的基础游标。每次单击该按钮时,都会为 AsyncTask 添加一个新线程并且任务完成(进入“等待”状态)。如果我单击该按钮 5 次或更多次,则 5 个 AsyncTasks 最终会以“等待”状态坐在那里。这是正常的还是我的某个地方有内存泄漏?
异步任务
private class updateAdapter extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
// Open database connection
if(_db == null || !_db.isOpen()) _db = new DatabaseWrapper(ActivityShowWOD.this).getWritableDatabase();
Cursor WODcursor;
// Check if a wod_id is set
if(_wod_id == -1) {
// Grab filters from preferences and at the same time build SQLselection string
SharedPreferences prefs = getSharedPreferences("Preferences", 0);
String[] filterNames = getResources().getStringArray(R.array.filters_values);
boolean[] filterValues = new boolean[filterNames.length];
String SQLselection = "";
for (int i = 0; i < filterNames.length; i++) {
filterValues[i] = prefs.getBoolean(filterNames[i], false);
// Build SQL query
if(filterValues[i] == true) {
SQLselection += filterNames[i] + " = 1 OR " + filterNames[i] + " = 0";
} else {
SQLselection += filterNames[i] + " = 0";
}
// Add an "AND" if there are more filters
if(i < filterNames.length - 1) SQLselection += " AND ";
}
// Get all WODs matching filter preferences
WODcursor = _db.query(DatabaseConstants.TBL_WORKOUTS,
new String[] { DatabaseConstants.WORKOUTS_ID, DatabaseConstants.WORKOUTS_NAME,
DatabaseConstants.WORKOUTS_NOTES, DatabaseConstants.WORKOUTS_CFID },
SQLselection, null, null, null, null);
// Move the Cursor to a random position
Random rand = new Random();
WODcursor.moveToPosition(rand.nextInt(WODcursor.getCount()));
// Store wod_id
_wod_id = WODcursor.getInt(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_ID));
} else {
// Get the cursor from the wod_id
WODcursor = _db.query(DatabaseConstants.TBL_WORKOUTS,
new String[] { DatabaseConstants.WORKOUTS_ID, DatabaseConstants.WORKOUTS_NAME,
DatabaseConstants.WORKOUTS_NOTES, DatabaseConstants.WORKOUTS_CFID },
DatabaseConstants.WORKOUTS_ID + " = " + _wod_id, null, null, null, null);
WODcursor.moveToFirst();
}
// Store WOD information into class instance variables and close cursor
_wod_cfid = WODcursor.getInt(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_CFID));
_wod_name = WODcursor.getString(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_NAME));
_wod_notes = WODcursor.getString(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_NOTES));
WODcursor.close();
// Return all exercises pertaining to this WOD
_excCursor = _db.query(DatabaseConstants.TBL_EXERCISES,
new String[] { DatabaseConstants.EXERCISES_ID, DatabaseConstants.EXERCISES_EXERCISE,
DatabaseConstants.EXERCISES_REPS, DatabaseConstants.EXERCISES_NOTES },
DatabaseConstants.EXERCISES_WOD_ID + " = " + _wod_id, null, null, null,
DatabaseConstants.EXERCISES_ID + " ASC");
return null;
}
@Override
protected void onPostExecute(Void result) {
_adapter.changeCursor(_excCursor);
_adapter.notifyDataSetChanged();
_WODlist.setOnItemClickListener(new WODlistClickListener());
}
}
我的 onCreate 中调用任务的代码(首次加载活动时):
upAdapter = new updateAdapter().execute();
在按钮上点击监听:
// Reset wod_id
_wod_id = -1;
// Update the underlying SimpleCursorAdapter
upAdapter = new updateAdapter().execute();
其中一个 AsyncTask 的堆栈跟踪(所有这些都相同):
Object.wait(long, int) line: not available [native method]
Thread.parkFor(long) line: 1535
LangAccessImpl.parkFor(long) line: 48
Unsafe.park(boolean, long) line: 317
LockSupport.park() line: 131
AbstractQueuedSynchronizer$ConditionObject.await() line: 1996
LinkedBlockingQueue.take() line: 359
ThreadPoolExecutor.getTask() line: 1001
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1061
ThreadPoolExecutor$Worker.run() line: 561
Thread.run() line: 1096
【问题讨论】:
-
我们可以看看你正在运行的一些代码吗?您是在每个
AsyncTask上调用execute()还是只是创建对象? -
你能为那些正在睡觉的
AsynTask线程发布完整的堆栈跟踪吗?根据我的经验,应该不会有很多人停放。 -
另外,您在哪个 Android 版本上进行测试?
-
@inazaruk Android 2.2。如何获取 AsyncTask 线程的堆栈跟踪?
-
@@soren.qvist,从堆栈跟踪中可以清楚地看出@kabuko 是正确的。
标签: java android android-asynctask