API.AI: Как остановить AsyncTask по нажатию кнопки AIB?
Я использую AIButton
в моем приложении, и у меня есть AsyncTask
который выполняется после нажатия кнопки AIButton и получения какой-либо команды, а AsyncTask иногда занимает слишком много времени для выполнения.
Вот мой код:
final AIConfiguration config = new AIConfiguration("xxx",
AIConfiguration.SupportedLanguages.English,
AIConfiguration.RecognitionEngine.System);
listenButton = (AIButton) findViewById(R.id.micButton);
config.setRecognizerStartSound(getResources().openRawResourceFd(R.raw.test_start));
config.setRecognizerStopSound(getResources().openRawResourceFd(R.raw.test_stop));
config.setRecognizerCancelSound(getResources().openRawResourceFd(R.raw.test_cancel));
listenButton.initialize(config);
listenButton.setResultsListener(this);
Вот AsnycTask
:
class translate extends AsyncTask<String, Void, String> {
String translatedText = "";
@Override
protected void onPreExecute() {
super.onPreExecute();
loading.setMessage("Loading");
loading.show();
}
@Override
protected String doInBackground(String... params) {
String text = params[0];
String toBeConvertedIn = params[1];
Log.d("TEXT", text);
Log.d("TBCI", toBeConvertedIn);
try {
String encodedText = URLEncoder.encode(text, "UTF-8");
HttpHandler httpHandler = new HttpHandler();
String url = "https://translate.yandex.net/api/v1.5/tr.json/translate?key=xxxxxxx&text=" + encodedText + "&lang=" + toBeConvertedIn;
String jsonStr = httpHandler.makeServiceCall(url);
if (jsonStr != null) {
Log.e(TAG, "Response from url: " + jsonStr);
try {
JSONObject jsonObj = new JSONObject(jsonStr);
Log.d("jsonObj", String.valueOf(jsonObj));
JSONArray translatedTextObj = jsonObj.getJSONArray("text");
for (int i=0; i<translatedTextObj.length(); i++) {
translatedText = translatedTextObj.getString(i);
Log.d("translatedText", translatedText);
}
} catch (JSONException e) {
Log.d(TAG, e.getMessage());
}
} else {
Log.e(TAG, "Couldn't get json from server.");
}
} catch (UnsupportedEncodingException e) {
Log.d(TAG, e.getMessage());
}
return translatedText;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
hTV.setText(s);
if (loading.isShowing()) {
loading.dismiss();
}
}
}
Я звоню выше дано AsyncTask
в onResult()
метод как это:
public void onResult(final AIResponse response) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "onResult");
Log.i(TAG, "Received success response");
// this is example how to get different parts of result object
final Status status = response.getStatus();
Log.i(TAG, "Status code: " + status.getCode());
Log.i(TAG, "Status type: " + status.getErrorType());
final Result result = response.getResult();
Log.i(TAG, "Resolved query: " + result.getResolvedQuery());
Log.i(TAG, "Action: " + result.getAction());
final String speech = result.getFulfillment().getSpeech();
final Metadata metadata = result.getMetadata();
if (metadata != null) {
Log.i(TAG, "Intent id: " + metadata.getIntentId());
Log.i(TAG, "Intent name: " + metadata.getIntentName());
}
final HashMap<String, JsonElement> params = result.getParameters();
if (params != null && !params.isEmpty()) {
Log.i(TAG, "Parameters: ");
for (final Map.Entry<String, JsonElement> entry : params.entrySet()) {
switch (response.getResult().getMetadata().getIntentName()) {
case "Translate":
if (entry.getValue() != null) {
if (entry.getKey().equals("translate")) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MainActivity.this);
LayoutInflater inflater = MainActivity.this.getLayoutInflater();
final View dialogView = inflater.inflate(R.layout.translate_alertdialog, null);
dialogBuilder.setView(dialogView);
final EditText textToTranslate = (EditText) dialogView.findViewById(R.id.text_to_translate);
final AutoCompleteTextView chooseLanguage = (AutoCompleteTextView) dialogView.findViewById(R.id.choose_language);
ArrayAdapter adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_spinner_item, languages);
chooseLanguage.setAdapter(adapter);
dialogBuilder.setTitle("What should I translate?");
dialogBuilder.setPositiveButton("Translate", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
if (!textToTranslate.getText().toString().isEmpty()) {
if (!chooseLanguage.getText().toString().isEmpty()) {
switch (chooseLanguage.getText().toString().toLowerCase()) {
case "french":
new translate().execute(textToTranslate.getText().toString(), "az");
break;
}
}
}
}
});
dialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//pass
}
});
AlertDialog b = dialogBuilder.create();
b.show();
} else {
Log.d("null", "No translate parameter");
}
} else {
Log.d("null", "No translate entry value");
}
break;
}
}
}
}
});
}
Итак, я хочу остановить все запущенные AsyncTask при нажатии кнопки AIB, чтобы предыдущие задачи были остановлены для выполнения новой задачи. Как это сделать?
Проблема в том, что вы не можете сделать что-то вроде: listenButton.onClickListener()
Вот.
4 ответа
Используйте логическое отмена (boolean mayInterruptIfRunning).
Сделайте asyncTask переменной класса.
AsyncTask translate_ = new translate();
Тогда назовите это так на месте.
translate_.execute(textToTranslate.getText().toString(), "az");
В пределах кнопки onclick отмените asyncTask.
translate_.cancel(true);
Затем проверьте в цикле, что задача была отменена, и установите перерыв.
for (int i=0; i<translatedTextObj.length(); i++) {
translatedText = translatedTextObj.getString(i);
Log.d("translatedText", translatedText);
if(isCancelled())
break;
}
Эти вопросы также дают больше разнообразия в том, как сделать это:
Android - принудительно отмените AsyncTask
Как остановить нить asynctask в Android?
Было бы целесообразно также управлять заданием на backpress. Возможно, отмените задачу в активности на паузу.
public void listenButtonOnClick(final View view) {
// aiService.startListening();
// add more details in here
if (aiService != null) {
switch (currentState) {
case normal:
aiService.startListening();
break;
case busy:
aiService.cancel();
translate_.cancel(true);
break;
default:
aiService.stopListening();
translate_.cancel(true);
break;
}
Или отмените задачу, когда aiservice
отменен или остановлен.
@Override
public void onListeningStarted() {}
@Override
public void onListeningCanceled() {
translate_.cancel(true);
}
@Override
public void onListeningFinished() {
translate_.cancel(true);
}
Есть и другие способы управления этим, изучите ваши варианты. Внимательно посмотрите на это и на вопросы SO, связанные выше.
Если вы посмотрите на документы.
Апиаи-андроид-клиент / ailib / SRC / Основной / Java / AI / API / щ / AIButton.java
@Override
protected void onClick(final View v) {
super.onClick(v);
if (aiService != null) {
switch (currentState) {
case normal:
aiService.startListening();
break;
case busy:
aiService.cancel();
break;
default:
aiService.stopListening();
break;
}
}
}
Из нашего обсуждения ясно, что вы боретесь с тем, как это реализовать.
Пожалуйста, изучите этот apiai-android-клиент / Android SDK для api.ai/ Учебное пособие
Вернитесь к основам. Забудь о ai.api
некоторое время и выучить основы. Просматривайте, читайте документы Входные события, читайте вопросы и применяйте принципы программирования. Например:
Переопределение клика по кнопке Android
Помимо этого, я не могу помочь вам дальше.
Вы должны сделать одну следующую вещь при отмене AsyncTask. на ваш метод нажатия кнопки.
public void AIButtonClick(View view){
asyncTask.cancel(false);
}
и проверьте в doInBackground, если он отменен, затем вернитесь из него.
@Override
protected String doInBackground(String... params) {
if(asyncTask.isCanceled()) return;
}
Также в вашем методе onPause вы отменили это было хорошо.
@Override
public void onPause() {
super.onPause();
if(asyncTask!=null){
asyncTask.cancel(false);
}
}
Если вы хотите отменить класс AsyncTask translate.cancel()
если вы хотите отменить запрос к серверу, я рекомендую использовать OKHTTP имеет функцию отмены запроса
Попробуйте установить resultListener для вашего AIButton и реализовать метод onCancelled(), отменяющий ваши AsyncTasks оттуда.
Чтобы пометить AsyncTask как необходимый для остановки, вы должны позвонить
asyncTask.cancel(false);
И в вашей AsyncTask вы должны периодически проверять, была ли она отменена или нет, позвонив isCancelled()
, Если этот метод возвращает true, вы должны остановить выполнение.