Android Asynctask и runOnUiThread

63
8

Недавно я попытался реализовать проект openalpr, и он отлично работал в своем исходном коде. Но когда я попытался изменить его и добавить некоторые функции, я столкнулся с некоторыми проблемами. Это его частичный код:

AsyncTask.execute(new Runnable() {
@Override
public void run() {
String result = OpenALPR.Factory.create(MainActivity.this, ANDROID_DATA_DIR).recognizeWithCountryRegionNConfig("us", "", destination.getAbsolutePath(), openAlprConfFile, 10);

Log.d("OPEN ALPR", result);

try {
final Results results = new Gson().fromJson(result, Results.class);
runOnUiThread(new Runnable() {
@Override
public void run() {
if (results == null || results.getResults() == null || results.getResults().size() == 0) {
Toast.makeText(MainActivity.this, "It was not possible to detect the licence plate.", Toast.LENGTH_LONG).show();
resultTextView.setText("It was not possible to detect the licence plate.");
} else {
resultTextView.setText("Plate: " + results.getResults().get(0).getPlate()
// Trim confidence to two decimal places
+ " Confidence: " + String.format("%.2f", results.getResults().get(0).getConfidence()) + "%"
// Convert processing time to seconds and trim to two decimal places
+ " Processing time: " + String.format("%.2f", ((results.getProcessingTimeMs() / 1000.0) % 60)) + " seconds");
}
}

Это отлично работает. Но когда я попытался получить "результаты" перед runOnUiThread, он не смог правильно определить. Ниже мой модифицированный код:

AsyncTask.execute(new Runnable() {
@Override
public void run() {
String result = OpenALPR.Factory.create(MainActivity.this, ANDROID_DATA_DIR).recognizeWithCountryRegionNConfig("us", "", destination.getAbsolutePath(), openAlprConfFile, 10);

Log.d("OPEN ALPR", result);

try {
final Results results = new Gson().fromJson(result, Results.class);
if(results!=null) Log.d("ShowTheResults",results.getResults().get(0).getPlate());
runOnUiThread(new Runnable() {
@Override
public void run() {
if (results == null || results.getResults() == null || results.getResults().size() == 0) {
Toast.makeText(MainActivity.this, "It was not possible to detect the licence plate.", Toast.LENGTH_LONG).show();
resultTextView.setText("It was not possible to detect the licence plate.");
} else {
resultTextView.setText("Plate: " + results.getResults().get(0).getPlate()
// Trim confidence to two decimal places
+ " Confidence: " + String.format("%.2f", results.getResults().get(0).getConfidence()) + "%"
// Convert processing time to seconds and trim to two decimal places
+ " Processing time: " + String.format("%.2f", ((results.getProcessingTimeMs() / 1000.0) % 60)) + " seconds");
}
}

Я просто не могу понять, почему вывод будет отличаться от потока пользовательского интерфейса. Может ли кто-нибудь сказать мне, как правильно использовать "результаты" в фоновом режиме, прежде чем я покажу его в пользовательском интерфейсе?

спросил(а) 2021-01-28T00:57:18+03:00 4 месяца, 3 недели назад
1
Решение
88

Я думаю, вы используете AsyncTask очень плохо. Вы хотите выполнить Runnable в асинхронном потоке, а затем вы вызываете runOnUiThread внутри него для обработки результата в потоке пользовательского интерфейса. Почему бы не использовать AsyncTask так, как они предназначены для использования?

Создайте новую задачу и используйте ее общие методы: doInBackground, onProgressUpdate, onPostExecute. Если AsyncTask выполняется в основном потоке, эти последние два уже вызываются в потоке пользовательского интерфейса.

new AsyncTask<Void, Void, Results>() {
@Override
protected Results doInBackground(Void... params) {
String result = OpenALPR.Factory.create(MainActivity.this, ANDROID_DATA_DIR).recognizeWithCountryRegionNConfig("us", "", destination.getAbsolutePath(), openAlprConfFile, 10);

Log.d("OPEN ALPR", result);

Results results = new Gson().fromJson(result, Results.class);
if (results != null || results.getResults() != null || results.getResults().size() > 0)
Log.d("ShowTheResults", results.getResults().get(0).getPlate());

return results;
}

@Override
protected void onPostExecute(Results result) {
if (results == null || results.getResults() == null || results.getResults().size() == 0) {
Toast.makeText(MainActivity.this, "It was not possible to detect the licence plate.", Toast.LENGTH_LONG).show();
resultTextView.setText("It was not possible to detect the licence plate.");
} else {
resultTextView.setText("Plate: " + results.getResults().get(0).getPlate()
// Trim confidence to two decimal places
+ " Confidence: " + String.format("%.2f", results.getResults().get(0).getConfidence()) + "%"
// Convert processing time to seconds and trim to two decimal places
+ " Processing time: " + String.format("%.2f", ((results.getProcessingTimeMs() / 1000.0) % 60)) + " seconds");
}
}
}.execute();

ответил(а) 2021-01-28T00:57:18+03:00 4 месяца, 3 недели назад
45

Прежде всего, я не уверен в вашей реализации Async Task, но я вижу, в чем проблема. Пожалуйста, проверьте приведенный ниже код.


AsyncTask.execute(new Runnable() {
@Override
public void run() {
String result = OpenALPR.Factory.create(MainActivity.this, ANDROID_DATA_DIR).recognizeWithCountryRegionNConfig("us", "", destination.getAbsolutePath(), openAlprConfFile, 10);

Log.d("OPEN ALPR", result);

try {
final Results results = new Gson().fromJson(result, Results.class);
if(results!=null || results.getResults() != null || results.getResults().size() > 0) Log.d("ShowTheResults",results.getResults().get(0).getPlate());
runOnUiThread(new Runnable() {
@Override
public void run() {
if (results == null || results.getResults() == null || results.getResults().size() == 0) {
Toast.makeText(MainActivity.this, "It was not possible to detect the licence plate.", Toast.LENGTH_LONG).show();
resultTextView.setText("It was not possible to detect the licence plate.");
} else {
resultTextView.setText("Plate: " + results.getResults().get(0).getPlate()
// Trim confidence to two decimal places
+ " Confidence: " + String.format("%.2f", results.getResults().get(0).getConfidence()) + "%"
// Convert processing time to seconds and trim to two decimal places
+ " Processing time: " + String.format("%.2f", ((results.getProcessingTimeMs() / 1000.0) % 60)) + " seconds");
}
}

ответил(а) 2021-01-28T00:57:18+03:00 4 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема