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, вы должны остановить выполнение.

Другие вопросы по тегам