【问题标题】:API.AI: How to stop AsyncTask on click of the AIButton?API.AI:如何在点击 AIButton 时停止 AsyncTask?
【发布时间】:2017-09-08 01:58:26
【问题描述】:

我在我的应用程序中使用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();
            }
        }
    }

我在上面给定AsyncTaskonResult() 方法中调用,如下所示:

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;
                    }
                }
            }
        }

    });

}

所以,我想要的是在单击 AIButton 时停止所有正在运行的 AsyncTask,以便停止以前的任务以执行新任务。如何做到这一点?

这里的问题是你不能这样做:listenButton.onClickListener() 这里。

【问题讨论】:

  • @YvetteColomb 我不会在任何地方实例化它,而是在我需要的地方调用它就像new translate().execute(param1, param2);
  • translate 类添加一个新的构造函数,传递一个对象,即布尔值,并在单击按钮时保留该对象的实例。您检查doInBackgroundBoolean 对象的值以查看该值是否更改为false 以便退出。当您单击按钮时,您将 Boolean 对象的值更改为 false
  • @EasyJoin.net 问题是在这种情况下无法跟踪按钮的点击。再次阅读问题。
  • @HammadNasir 你在onResult 方法以外的其他地方创建translate 类的实例,特别是在case "french":?
  • @EasyJoin.net 但您已经写了“当您单击按钮时,您将布尔对象的值更改为 false。”如果没有onclick,我应该如何更改此处的值?

标签: android android-asynctask onclicklistener api-ai


【解决方案1】:

使用boolean cancel (boolean mayInterruptIfRunning)

将 asyncTask 设为类变量。

AsyncTask translate_ = new translate();

然后就地这样称呼它。

translate_.execute(textToTranslate.getText().toString(), "az");

在按钮内点击取消异步任务。

translate_.cancel(true);

然后在循环中检查任务是否已被取消并设置中断。

for (int i=0; i<translatedTextObj.length(); i++) {
    translatedText = translatedTextObj.getString(i);
    Log.d("translatedText", translatedText);
    if(isCancelled())
        break;
}

这些问题也为如何选择提供了更多选择:

Android - Cancel AsyncTask Forcefully

How to stop asynctask thread in android?

在后台管理任务也是明智之举。或许取消活动 onpause 中的任务。

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);
}

还有其他管理方式,请探索您的选择。好好看看at this 和上面链接的 SO 问题。

如果你看看the docs

apiai-android-client/ailib/src/main/java/ai/api/ui/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;
        }
    }

}

our discussion 可以清楚地看出,您正在为如何实现这一点而苦苦挣扎。

请研究这个apiai-android-client/ Android SDK for api.ai/ Tutorial

回到基础。暂时忘记ai.api 并学习基础知识。 Browse 左右,阅读文档 Input Events 阅读问题并应用编程原则。 例如:
Android button onclick override

除此之外,我无法再为您提供任何帮助。

【讨论】:

    【解决方案2】:

    取消 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);
    
       }
    }
    

    【讨论】:

      【解决方案3】:

      尝试为您的 AIButton 设置 resultListener 并实现 onCancelled() 方法从那里取消您的 AsyncTasks。

      要将 AsyncTask 标记为需要停止,您应该调用

      asyncTask.cancel(false);
      

      在您的 AsyncTask 中,您必须通过调用 isCancelled() 定期检查它是否被取消。如果此方法返回 true,您应该停止执行。

      【讨论】:

      • 如何设置 AIButton 的 resultListener?
      • @HammadNasir 你已经在设置它了:listenButton.setResultsListener(this);.
      • 好的!所以我只需要把asyncTask.cancel(false);放到AIButton的onCancelled中,然后在AsyncTask中检查它是否被取消?
      【解决方案4】:

      如果你想取消 AsyncTask 类 translate.cancel()

      如果要取消服务器请求我推荐使用OKHTTP有取消请求功能

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多