У меня есть TableLayout с несколькими сотнями строк таблиц.
Я заполняю его потоком, который уведомляет обработчик, когда создается строка, и обработчик добавляет строку в поток пользовательского интерфейса. Но проблема в том, что в некоторых случаях некоторые пользователи сообщают ARN из-за:
Истекло время диспетчеризации ввода (ожидание отправки ключевого события, потому что сфокусированное окно не завершило обработку всех входных событий, которые были ранее доставлен на него. Длина исходящей очереди: 0. Длина очереди ожидания: 1.)
ОС Android обрабатывает создание ANR, когда обнаруживает, что поток пользовательского интерфейса / основной поток блокируется в течение 5 секунд .
Я думал об использовании AsyncTask, но он будет устаревшим в Android 11.
Это мой поток:
private class PopulateTableThread extends Thread {
private Context context;
private ArrayList<Player> players;
public PopulateTableThread(Context context, ArrayList<Player> players) {
super();
this.context = context;
this.players = players;
}
public void run() {
for (int i=0; i<players.size(); i++) {
TableRow row = new TableRow(context);
row.setLayoutParams(rowParams);
row.setBackgroundResource(R.drawable.table_row_not_selected);
String strings[] = {players.get(i).getName(),
"" + players.get(i).getTeam().getName(),
"" + players.get(i).getPositionInString(context),
"" + players.get(i).getYearsOfContractFormatted(),
"" + players.get(i).getValue() + " M€",
"" + players.get(i).getSalary() + " M€",
"" + players.get(i).getAge(),
"" + players.get(i).getBaseLevel()};
for (int j = 0; j < strings.length; j++) {
TextView text = new TextView(context);
text.setBackgroundResource(R.drawable.table_cell_background);
if (j == 0) {
text.setLayoutParams(nameParams);
text.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
text.setPadding((int) getResources().getDimension(R.dimen.spacing_small), 0, (int) getResources().getDimension(R.dimen.spacing_small), 0);
text.setMaxLines(1);
text.setEllipsize(TextUtils.TruncateAt.END);
}else if (j == 1) {
text.setLayoutParams(teamNameParams);
text.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
text.setPadding((int) getResources().getDimension(R.dimen.spacing_small), 0, (int) getResources().getDimension(R.dimen.spacing_small), 0);
text.setMaxLines(1);
text.setEllipsize(TextUtils.TruncateAt.END);
} else if (j == 2 || j == 3) {
text.setLayoutParams(positionAndContractParams);
text.setGravity(Gravity.CENTER);
} else if (j == 4) {
text.setLayoutParams(valueParams);
text.setGravity(Gravity.CENTER);
} else if (j == 5) {
text.setLayoutParams(salaryParams);
text.setGravity(Gravity.CENTER);
} else if (j == 6 || j == 7) {
text.setLayoutParams(ageAndLevelParams);
text.setGravity(Gravity.CENTER);
}
if (j == 3 && strings[3].split("/")[0].equals("1")) {
text.setBackgroundResource(R.drawable.table_cell_background_danger);
}
text.setMinHeight((int) getResources().getDimension(R.dimen.cell_height));
text.setText(strings[j]);
row.addView(text);
}
ProgressBar levelProgress = new ProgressBar(new ContextThemeWrapper(context, R.style.ProgressBar), null, 0);
levelProgress.setBackgroundResource(R.drawable.table_cell_background);
levelProgress.setLayoutParams(levelBarParams);
levelProgress.setMinimumHeight((int) getResources().getDimension(R.dimen.cell_height));
levelProgress.setProgress(players.get(i).getBaseLevel());
levelProgress.setPadding((int) getResources().getDimension(R.dimen.spacing_small), 0, (int) getResources().getDimension(R.dimen.spacing_small), 0);
row.addView(levelProgress);
final int finalIndex = i;
row.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (searchProgressBar.getVisibility() == View.VISIBLE) {
return;
}
SoundEffectsManager.getInstance().play(context, SoundEffectsManager.button);
displaySignDialog(players.get(finalIndex));
}
});
Message message = new Message();
message.what = HANDLER_ROW_CREATED;
message.obj = row;
updateTableHandler.sendMessage(message);
}
Message message = new Message();
message.what = HANDLER_TABLE_FILLED;
updateTableHandler.sendMessage(message);
}
}
И это обработчик, который обновление потока пользовательского интерфейса, когда поток создал новую строку TableRow:
updateTableHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case HANDLER_ROW_CREATED:
TableRow row = (TableRow) msg.obj;
tableLayout.addView(row);
break;
case HANDLER_TABLE_FILLED:
tableLayout.setAlpha(1f);
searchProgressBar.setVisibility(View.GONE);
break;
}
}
};
Как я могу избежать этих отчетов ARN?
Попытка выполнить решение Дэвида Вассера, но с той же проблемой:
private class PopulateTableThread extends Thread {
private Context context;
private ArrayList<Player> players;
public PopulateTableThread(Context context, ArrayList<Player> players) {
super();
this.context = context;
this.players = players;
}
public void run() {
Log.d("XXX_SeekerActivity","filling table with "+players.size()+" players");
for (int i=0; i<players.size(); i++) {
final String strings[] = {players.get(i).getName(),
"" + players.get(i).getTeam().getName(),
"" + players.get(i).getPositionInString(context),
"" + players.get(i).getYearsOfContractFormatted(),
"" + players.get(i).getValue() + " M€",
"" + players.get(i).getSalary() + " M€",
"" + players.get(i).getAge(),
"" + players.get(i).getBaseLevel()};
final int finalI = i;
runOnUiThread(new Runnable() {
@Override
public void run() {
TableRow row = new TableRow(context);
row.setLayoutParams(rowParams);
row.setBackgroundResource(R.drawable.table_row_not_selected);
for (int j = 0; j < strings.length; j++) {
TextView text = new TextView(context);
text.setBackgroundResource(R.drawable.table_cell_background);
if (j == 0) {
text.setLayoutParams(nameParams);
text.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
text.setPadding((int) getResources().getDimension(R.dimen.spacing_small), 0, (int) getResources().getDimension(R.dimen.spacing_small), 0);
text.setMaxLines(1);
text.setEllipsize(TextUtils.TruncateAt.END);
}else if (j == 1) {
text.setLayoutParams(teamNameParams);
text.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
text.setPadding((int) getResources().getDimension(R.dimen.spacing_small), 0, (int) getResources().getDimension(R.dimen.spacing_small), 0);
text.setMaxLines(1);
text.setEllipsize(TextUtils.TruncateAt.END);
} else if (j == 2 || j == 3) {
text.setLayoutParams(positionAndContractParams);
text.setGravity(Gravity.CENTER);
} else if (j == 4) {
text.setLayoutParams(valueParams);
text.setGravity(Gravity.CENTER);
} else if (j == 5) {
text.setLayoutParams(salaryParams);
text.setGravity(Gravity.CENTER);
} else if (j == 6 || j == 7) {
text.setLayoutParams(ageAndLevelParams);
text.setGravity(Gravity.CENTER);
}
if (j == 2) {
switch (players.get(finalI).getPosition()) {
case Player.PLAYER_POSITION_GOALKEEPER:
text.setBackgroundResource(R.drawable.table_cell_background_position_gk);
break;
case Player.PLAYER_POSITION_DEFENDER:
text.setBackgroundResource(R.drawable.table_cell_background_position_def);
break;
case Player.PLAYER_POSITION_MIDFIELDER:
text.setBackgroundResource(R.drawable.table_cell_background_position_mid);
break;
case Player.PLAYER_POSITION_FORWARD:
text.setBackgroundResource(R.drawable.table_cell_background_position_fw);
break;
}
}
if (j == 3 && strings[3].split("/")[0].equals("1")) {
text.setBackgroundResource(R.drawable.table_cell_background_danger);
}
text.setMinHeight((int) getResources().getDimension(R.dimen.cell_height));
text.setText(strings[j]);
row.addView(text);
}
ProgressBar levelProgress = new ProgressBar(new ContextThemeWrapper(context, R.style.ProgressBar), null, 0);
levelProgress.setBackgroundResource(R.drawable.table_cell_background);
levelProgress.setLayoutParams(levelBarParams);
levelProgress.setMinimumHeight((int) getResources().getDimension(R.dimen.cell_height));
levelProgress.setProgress(players.get(finalI).getBaseLevel());
levelProgress.setPadding((int) getResources().getDimension(R.dimen.spacing_small), 0, (int) getResources().getDimension(R.dimen.spacing_small), 0);
row.addView(levelProgress);
final int finalIndex = finalI;
row.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (searchProgressBar.getVisibility() == View.VISIBLE) {
return;
}
SoundEffectsManager.getInstance().play(context, SoundEffectsManager.button);
displaySignDialog(players.get(finalIndex));
}
});
row.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(final View view, MotionEvent motionEvent) {
if (searchProgressBar.getVisibility() == View.VISIBLE) {
return true;
}
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
delayColorizeHandler.postDelayed(new Runnable() {
@Override
public void run() {
Util.getInstance().colorizeBackgroundCheckingApiLevel(view);
}
}, Util.WAIT_TIME_BEFORE_TOUCH_COLORIZE);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
delayColorizeHandler.removeCallbacksAndMessages(null);
Util.getInstance().clearBackgroundColorFilter(view);
break;
}
return false;
}
});
tableLayout.addView(row);
}
});
}
runOnUiThread(new Runnable() {
@Override
public void run() {
tableLayout.setAlpha(1f);
searchProgressBar.setVisibility(View.GONE);
}
});
}
}