Messages: Replace (Safe)AsyncTask
* AsyncTask is deprecated * Executors and Handlers can achieve the same thing and are not deprecated Change-Id: I5271bb73b848ce885eeaf5632c1da27853c56c4a
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
* Copyright (C) 2024-2025 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,8 @@ import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.Editable;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextWatcher;
|
||||
@@ -49,6 +50,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
@@ -147,66 +149,81 @@ public class ContactRecipientAutoCompleteView extends RecipientEditTextView {
|
||||
}
|
||||
|
||||
/**
|
||||
* An AsyncTask that cleans up contact chips on every chips commit (i.e. get or create a new
|
||||
* A class that cleans up contact chips on every chips commit (i.e. get or create a new
|
||||
* conversation with the given chips).
|
||||
*/
|
||||
private class AsyncContactChipSanitizeTask extends
|
||||
AsyncTask<Void, ChipReplacementTuple, Integer> {
|
||||
private class AsyncContactChipSanitizeTask {
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground(final Void... params) {
|
||||
final DrawableRecipientChip[] recips = getText()
|
||||
.getSpans(0, getText().length(), DrawableRecipientChip.class);
|
||||
int invalidChipsRemoved = 0;
|
||||
for (final DrawableRecipientChip recipient : recips) {
|
||||
final RecipientEntry entry = recipient.getEntry();
|
||||
if (entry != null) {
|
||||
if (entry.isValid()) {
|
||||
if (RecipientEntry.isCreatedRecipient(entry.getContactId()) ||
|
||||
ContactRecipientEntryUtils.isSendToDestinationContact(entry)) {
|
||||
// This is a generated/send-to contact chip, try to look it up and
|
||||
// display a chip for the corresponding local contact.
|
||||
try (final Cursor lookupResult =
|
||||
ContactUtil.lookupDestination(
|
||||
getContext(), entry.getDestination())
|
||||
.performSynchronousQuery()) {
|
||||
if (lookupResult != null && lookupResult.moveToNext()) {
|
||||
// Found a match, remove the generated entry and replace with a
|
||||
// better local entry.
|
||||
publishProgress(
|
||||
new ChipReplacementTuple(
|
||||
recipient,
|
||||
ContactUtil.createRecipientEntryForPhoneQuery(
|
||||
lookupResult, true)));
|
||||
} else if (PhoneUtils.isValidSmsMmsDestination(
|
||||
entry.getDestination())) {
|
||||
// No match was found, but we have a valid destination so let's
|
||||
// at least create an entry that shows an avatar.
|
||||
publishProgress(
|
||||
new ChipReplacementTuple(
|
||||
recipient,
|
||||
ContactRecipientEntryUtils
|
||||
.constructNumberWithAvatarEntry(
|
||||
entry.getDestination())));
|
||||
} else {
|
||||
// Not a valid contact. Remove and show an error.
|
||||
publishProgress(new ChipReplacementTuple(recipient, null));
|
||||
invalidChipsRemoved++;
|
||||
private ExecutorService mExecutor = Executors.newSingleThreadExecutor();
|
||||
private Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private boolean mIsCancelled;
|
||||
|
||||
protected void execute() {
|
||||
mExecutor.execute(() -> {
|
||||
final DrawableRecipientChip[] recips = getText()
|
||||
.getSpans(0, getText().length(), DrawableRecipientChip.class);
|
||||
int invalidChipsRemoved = 0;
|
||||
for (final DrawableRecipientChip recipient : recips) {
|
||||
if (mIsCancelled) {
|
||||
break;
|
||||
}
|
||||
final RecipientEntry entry = recipient.getEntry();
|
||||
if (entry != null) {
|
||||
if (entry.isValid()) {
|
||||
if (RecipientEntry.isCreatedRecipient(entry.getContactId()) ||
|
||||
ContactRecipientEntryUtils.isSendToDestinationContact(entry)) {
|
||||
// This is a generated/send-to contact chip, try to look it up and
|
||||
// display a chip for the corresponding local contact.
|
||||
try (final Cursor lookupResult = ContactUtil.lookupDestination(
|
||||
getContext(), entry.getDestination())
|
||||
.performSynchronousQuery()) {
|
||||
if (mIsCancelled) {
|
||||
break;
|
||||
}
|
||||
if (lookupResult != null && lookupResult.moveToNext()) {
|
||||
// Found a match, remove the generated entry and replace
|
||||
// with abetter local entry.
|
||||
publishProgress(
|
||||
new ChipReplacementTuple(recipient,
|
||||
ContactUtil.
|
||||
createRecipientEntryForPhoneQuery(
|
||||
lookupResult, true)));
|
||||
} else if (PhoneUtils.isValidSmsMmsDestination(
|
||||
entry.getDestination())) {
|
||||
// No match was found, but we have a valid destination so
|
||||
// let's at least create an entry that shows an avatar.
|
||||
publishProgress(
|
||||
new ChipReplacementTuple(
|
||||
recipient,
|
||||
ContactRecipientEntryUtils
|
||||
.constructNumberWithAvatarEntry(
|
||||
entry.getDestination())));
|
||||
} else {
|
||||
// Not a valid contact. Remove and show an error.
|
||||
publishProgress(new ChipReplacementTuple(recipient, null));
|
||||
invalidChipsRemoved++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
publishProgress(new ChipReplacementTuple(recipient, null));
|
||||
invalidChipsRemoved++;
|
||||
}
|
||||
} else {
|
||||
publishProgress(new ChipReplacementTuple(recipient, null));
|
||||
invalidChipsRemoved++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return invalidChipsRemoved;
|
||||
|
||||
final int finalInvalidChipsRemoved = invalidChipsRemoved;
|
||||
mHandler.post(() -> {
|
||||
mCurrentSanitizeTask = null;
|
||||
if (finalInvalidChipsRemoved > 0) {
|
||||
mChipsChangeListener.onInvalidContactChipsPruned(finalInvalidChipsRemoved);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(final ChipReplacementTuple... values) {
|
||||
for (final ChipReplacementTuple tuple : values) {
|
||||
private void publishProgress(final ChipReplacementTuple tuple) {
|
||||
mHandler.post(() -> {
|
||||
if (tuple.removedChip != null) {
|
||||
final Editable text = getText();
|
||||
final int chipStart = text.getSpanStart(tuple.removedChip);
|
||||
@@ -219,24 +236,18 @@ public class ContactRecipientAutoCompleteView extends RecipientEditTextView {
|
||||
appendRecipientEntry(tuple.replacedChipEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Integer invalidChipsRemoved) {
|
||||
mCurrentSanitizeTask = null;
|
||||
if (invalidChipsRemoved > 0) {
|
||||
mChipsChangeListener.onInvalidContactChipsPruned(invalidChipsRemoved);
|
||||
}
|
||||
public void cancel() {
|
||||
mIsCancelled = true;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return mIsCancelled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We don't use SafeAsyncTask but instead use a single threaded executor to ensure that
|
||||
* all sanitization tasks are serially executed so as not to interfere with each other.
|
||||
*/
|
||||
private static final Executor SANITIZE_EXECUTOR = Executors.newSingleThreadExecutor();
|
||||
|
||||
private AsyncContactChipSanitizeTask mCurrentSanitizeTask;
|
||||
|
||||
/**
|
||||
@@ -251,11 +262,11 @@ public class ContactRecipientAutoCompleteView extends RecipientEditTextView {
|
||||
*/
|
||||
private void sanitizeContactChips() {
|
||||
if (mCurrentSanitizeTask != null && !mCurrentSanitizeTask.isCancelled()) {
|
||||
mCurrentSanitizeTask.cancel(false);
|
||||
mCurrentSanitizeTask.cancel();
|
||||
mCurrentSanitizeTask = null;
|
||||
}
|
||||
mCurrentSanitizeTask = new AsyncContactChipSanitizeTask();
|
||||
mCurrentSanitizeTask.executeOnExecutor(SANITIZE_EXECUTOR);
|
||||
mCurrentSanitizeTask.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user