当前位置 博文首页 > 高远的博客:易生活(一)-APP---回调函数在异步操作中的应用

    高远的博客:易生活(一)-APP---回调函数在异步操作中的应用

    作者:[db:作者] 时间:2021-09-06 22:46

    易生活(一)-APP—回调函数在异步操作中的应用

    背景

    1. 在项目开发过程中遇到这样一个问题:在使用科大讯飞语音识别功能的时候,想要把语音识别这个功能封装成一个工具类,无论哪一个界面使用直接调用就可以使用语音识别功能了,比较方便。
    2. 最开始想法是靠最原始的方式,直接封装一个工具类,带一个返回值,直接拿去识别的返回结果就行了。但是出现异常了,返回结果为空,郁闷了好久,后来通过查看科大讯飞的文档才知道,语音识别是一个异步操作,直接获取返回结果是不可以的。[google:什么是异步操作]
    3. 前面学习的过程中老师有提到回调函数这个概念,在安卓中应用广泛,例如各个按钮的点击事件、各个生命周期函数等。
    4. 现尝试使用回调函数解决这个问题。[已解决]

    思路及实现

    1. 首先定义一个接口,该接口有一个方法,这个接口将来要被实现,实现的类中的这个方法就是所谓回调函数,内容如下

      /**
       * 该接口是为了获取语音识别结果。
       * 参数为一个List<String>,共两个值,用strList.get(0)和strList.get(1)获取。
       * 第一个是识别的完整的语句,如;“今天你吃饭了吗?”;第二个是识别的分词结果,以“,”隔开,如“今天,你,吃饭,了,吗,?,”
       */
      public interface MscInterface {
          public  void voice2List(List<String> strList);
      }
      
    2. 需要获取语音识别结果的类,如activity继承该接口,会实现上述接口的 public void voice2List(List<String> strList);方法,在在该方法中获取list结果,进行相关数据处理。同时,在该类中调用封装好的语音识别工具类MSCUtils的 public static void getVoiceReslut(final SearchActivity searchActivity),注意,要把该activity当作一个参数传递给工具类。内容如下

      //开始调用工具类
      private void showMSC() {
      MSCUtils mMSCUtils=new MSCUtils();
      mMSCUtils.getVoiceReslut(this);
      }
      //这个是回调函数,用来获取语音的识别结果;返回值为一个List,共两个值,第一个是识别的完整的语句;第二个是识别的分词结果,以“,”隔开,如“今天,你,吃饭,了,吗,?,”
      @Override
      public void voice2List(List strList) {
      Toast.makeText(SearchActivity.this, “回调成功!”, Toast.LENGTH_SHORT).show();
      processMSC(strList);
      }

    3. 工具类的封装,请特别注意mMscInterface.voice2List(chineseWordList);这一句话,这一句话是实现回调的核心。我们传递过来了activity这个对象,并且activity这个类还实现了MscInterface这个接口,所以就有这个方法可以实现回调。大致如下

              /**
       * 该工具类可以实现快速调用科大讯飞的语音识别,获取识别结果。【采用回调的方式实现】
       * 使用方式:1.在你的类实例化该类,然后调用该工具类的getVoiceReslut方法,参数:"你的类.this"(说法不规范,好理解=_+)。
       * 2.让你的类实现MscInterface接口,在实现的接口中获取参数即可;
       * 参数说明:参数为一个List<String>,共两个值,用strList.get(0)和strList.get(1)获取。
       * 第一个是识别的完整的语句,如;“今天你吃饭了吗?”;
       * 第二个是识别的分词结果,以“,”隔开,如“今天,你,吃饭,了,吗,?,”
       */
      public class MSCUtils {
          private final String TAG = "MSCUtils+++++";
          private MscInterface mMscInterface;
          private List<String> chineseWordList = new ArrayList<String>();//分词结果集
          private String Str = "";//最终形成的句子
          private String str2 = "";//要做的分词效果
      
          public void getVoiceReslut(final MscInterface mMscInterface) {
             this.mMscInterface = mMscInterface;
              //1.创建RecognizerDialog对象
              RecognizerDialog mDialog = new RecognizerDialog((Context) mMscInterface, new InitListener() {
                  @Override
                  public void onInit(int i) {
      
                  }
              });
              //2.设置accent、 language等参数
              mDialog.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
              mDialog.setParameter(SpeechConstant.ACCENT, "mandarin");
              //若要将UI控件用于语义理解,必须添加以下参数设置,设置之后onResult回调返回将是语义理解
              //结果
              // mDialog.setParameter("asr_sch", "1");
              // mDialog.setParameter("nlp_version", "2.0");
              //3.设置回调接口
              mDialog.setListener(new RecognizerDialogListener() {
                  //特别注意该方法会回调多次,不要让数据覆盖了
                  @Override
                  public void onResult(RecognizerResult recognizerResult, boolean b) {
                      String jsonObg = recognizerResult.getResultString();
                      Gson gson = new Gson();
                      Sentence sentence = gson.fromJson(jsonObg, new Sentence().getClass());
                      List<Ws> wsList = sentence.getWs();
                      for (Ws w : wsList) {
                          List<Cw> cwList = w.getCw();
                          for (Cw c : cwList) {
                              String chineseWord = c.getW();
                              Str += chineseWord;
                              str2 += chineseWord + ",";
                              Log.e(TAG, Str);
                              Log.e(TAG, str2);
                          }
                      }
                      if (b) processVoice();//b然后true,表示识别结束,当时别结束,我们再回调
      
                  }
      
                  @Override
                  public void onError(SpeechError speechError) {
      
                  }
              });
              //4.显示dialog,接收语音输入
              mDialog.show();
          }
      
          private void processVoice() {
              chineseWordList.clear();
              //最后再填充数据,防止数据被覆盖
              chineseWordList.add(Str);
              chineseWordList.add(str2);
              mMscInterface.voice2List(chineseWordList);//开始回调
          }
      
      }
      
    cs