我正在计算需要一些时间的东西。为此,我创建了一个子类AsyncTask的内部类:
private class AsyncAllPlayAll extends AsyncTask<String, Void, CharSequence>
{
StournamentDbAdapter mDbHelper;
public AsyncAllPlayAll(Context context, StournamentDbAdapter dbHelper)
{
this.mContext = context;
this.mDbHelper = dbHelper;
}
@Override
protected CharSequence doInBackground(String... tournamentRowIds)
{
Long tournamentRowId = Long.valueOf(tournamentRowIds[0]);
Tournament tournament = new Tournament(mDbHelper, tournamentRowId);
tournament.setupTournament();
Boolean tournamentHasWinner = mDbHelper.winningTournamentParticipantsExists(tournamentRowId);
// tournament already run: delete score
if(tournamentHasWinner)
{
mDbHelper.resetTournamentsStocksScore(tournamentRowId);
mDbHelper.resetTournamentWinnerStockId(tournamentRowId);
}
//run tournament!
tournament.allPlayAll();
TournamentParticipant tournamentParticipant = mDbHelper.insertWinningParticipant(tournamentRowId);
populateCompetitorsListView();
final CharSequence winner = "Winner is: " + tournamentParticipant.getStock().getName() + "(" + tournamentParticipant.getScore() + ")";
return winner;
}
@Override //the winner
protected void onPostExecute(final CharSequence result) {
super.onPostExecute(result);
final int duration = Toast.LENGTH_LONG;
TournamentEdit.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(mContext, "Hello", duration).show();
}
});
}
}
但我得到一个错误,我不会放弃理解:“无法在未调用Looper.prepare()的线程内创建处理程序”
我在stackoverflow上读了几个线程,但实现写在其中的内容并没有改变我的情况。
我确定错误来自我在onPostExecute中运行的Toast,但这不是问题。该错误始于尝试初始化锦标赛。
Tournament tournament = new Tournament(mDbHelper, tournamentRowId);
这是我的堆栈:
Thread [<11> AsyncTask #1] (Suspended)
FragmentManagerImpl$1.<init>(FragmentManagerImpl) line: 423
FragmentManagerImpl.<init>() line: 423
Tournament(Activity).<init>() line: 702
Tournament.<init>(StournamentDbAdapter, Long) line: 48
TournamentEdit$AsyncAllPlayAll.doInBackground(String...) line: 346
TournamentEdit$AsyncAllPlayAll.doInBackground(Object...) line: 1
AsyncTask$2.call() line: 264
FutureTask$Sync.innerRun() line: 305
AsyncTask$3(FutureTask).run() line: 137
AsyncTask$SerialExecutor$1.run() line: 208
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1076
ThreadPoolExecutor$Worker.run() line: 569
Thread.run() line: 856
我觉得这可能是db线程的一些问题?当我从主线程传递给AsyncAllPlayAll时。
所以我尝试在内部类(不同的实例)中打开db线程并将其构造函数更改为:
public AsyncAllPlayAll(Context context, StournamentDbAdapter dbHelper)
{
this.mContext = context;
this.mDbHelper = dbHelper;
mDbHelper = new StournamentDbAdapter(context);
mDbHelper.open();
}
这也没有帮助:(
现在我尝试添加一个Looper(如AsyncTask and Looper.prepare() error中所述)
@Override
protected CharSequence doInBackground(String... tournamentRowIds)
{
Looper.prepare();
Long tournamentRowId = Long.valueOf(tournamentRowIds[0]);
Tournament tournament = new Tournament(mDbHelper, tournamentRowId);
tournament.setupTournament();
Boolean tournamentHasWinner = mDbHelper.winningTournamentParticipantsExists(tournamentRowId);
// tournament already run: delete score
if(tournamentHasWinner)
{
mDbHelper.resetTournamentsStocksScore(tournamentRowId);
mDbHelper.resetTournamentWinnerStockId(tournamentRowId);
}
//run tournament!
tournament.allPlayAll();
TournamentParticipant tournamentParticipant = mDbHelper.insertWinningParticipant(tournamentRowId);
populateCompetitorsListView();
final CharSequence winner = "Winner is: " + tournamentParticipant.getStock().getName() + "(" + tournamentParticipant.getScore() + ")";
Looper.loop();
return winner;
}
代码更进一步,但我收到以下错误:
引起:android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图。
现在populateCompetitorsListView()导致崩溃,也很清楚原因:查看populateCompetitorsListView()的最后一行,这是
setListAdapter(tournamentStocks);
试图改变主线程。我将它移动到主类,它似乎修复了它:计算运行。
@SuppressWarnings("deprecation")
private void populateCompetitorsListView()
{
// Get all of the notes from the database and create the item list
Cursor tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
startManagingCursor(tournamentStocksCursor);
// Create an array to specify the fields we want to display in the list (only name)
String[] from = new String[] {StournamentConstants.TblStocks.COLUMN_NAME, StournamentConstants.TblTournamentsStocks.TBL_COLUMN_TOURNAMENTS_STOCKS_STOCK_SCORE};
// and an array of the fields we want to bind those fields to (in this case just name)
int[] to = new int[]{R.id.competitor_name, R.id.competitor_score};
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter tournamentStocks = new SimpleCursorAdapter(this, R.layout.competitor_row, tournamentStocksCursor, from, to);
//tournamentStocks.convertToString(tournamentStocksCursor);
setListAdapter(tournamentStocks);
}
但现在的问题是我似乎陷入了 doInBackground(),因为 Looper.loop(); 的实现,这是猜测运行无限循环?
还有其他想法吗?
谢谢!
答案 0 :(得分:0)
经过大量研究后我发现了我的问题:我在doInBackground()&amp;中使用了太多代码。在我拿出大部分代码并将其放回我的Activity后,我的ListView有奇怪的行为:sonetimes它显示了一个空的结果。有时它只显示一行(23个中的一行),结果显示不同的行。当我运行应用程序时 - 我大多没有或只有一行结果。当我使用调试器时 - 我得到了所有结果就好了!怎么会??? - 好吧 - 我错误地在主线程上更新我的ListView,然后第二个线程设法用结果更新数据库。所以主线程抓住了db的空结果。我也摆脱了循环。
我的异步类现在看起来像这样:
private class AsyncAllPlayAll extends AsyncTask<String, Void, Long>
{
Tournament mTournament = null;
public AsyncAllPlayAll(Tournament tournament)
{
this.mTournament = tournament;
}
@Override
protected Long doInBackground(String... string)
{
Long ml = null;
//run tournament!
mTournament.allPlayAll();
return ml = (long) 0;
}
@Override
protected void onPostExecute(Long result)
{
TournamentEdit.this.runOnUiThread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
populateCompetitorsListView();
}
});
}
}
我现在使用runOnUiThread()在我的主线程上调用populate方法。我仍然需要更新我的Toast消息,但明天我会这样做: - )
感谢您阅读这篇超长的传奇......