A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 xiaoqing 于 2015-11-12 20:08 编辑

         大家好,深圳校区福利来啦。不过不是美女图哦,是技术福利。
         简单的说,就是深圳校区内网有一个便捷的问答平台(跟知乎很像)。就业指导老师不单止辅导就业哦,技术实力也是棒棒的,晚自习会帮助大家解决各种疑难杂症,解决好问题之后呢?就完了吗?当然要惠及大众呀。老师就从里面各种问答中找出一些典型的问答,分享给大家。这些问题是学员平时上课遇到的问题,也可能是去面试时面试官提出的问题。相信这些问题对大家的学习和就业肯定有帮助。
       那么这一期的问题就是关于回调(CallBack)
       好了,不说废话,直接上精彩问答。在问答网里,师生对答是这样的:


      
       看完是不是想说:然并卵?其实我们是有代码的。直接上原问答吧:

-------------------------------------------------------华丽的分割线------------------------------------------------------
        先讲讲怎么去写一个回调,举个例子比较容易解释。
        这是一个真实的应用场景,就是类似微信的表情模块,点击选中某个表情,就可以显示在edittext上:
  1. FaceRelativeLayout类 :怎么写一个回调接口
  2. /**
  3. * 表情控件
  4. * @author JIM
  5. *
  6. */
  7. public class FaceRelativeLayout extends RelativeLayout implements
  8.   OnItemClickListener {
  9. /** 表情页的监听事件 */
  10. private OnCorpusSelectedListener listener;
  11.   public void setOnCorpusSelectedListener(OnCorpusSelectedListener listener) {
  12.   this.listener = listener;
  13. }
  14. /**
  15.   * 表情选择监听
  16.   *
  17.   * @author naibo-liao
  18.   * @时间: 2013-1-15下午04:32:54
  19.   */
  20. public interface OnCorpusSelectedListener {
  21.   void onCorpusSelected(ChatEmoji emoji);
  22.   void onCorpusDeleted();
  23. }

  24. private void Init_viewPager() {
  25. ...
  26. ...
  27. ...省略
  28.    view.setOnItemClickListener(new OnItemClickListener(){
  29.     @Override
  30.     public void onItemClick(AdapterView<?> arg0, View arg1,
  31.       int arg2, long arg3) {
  32.      ChatEmoji emoji = (ChatEmoji) faceAdapters.get(current).getItem(arg2);
  33.      //System.out.println("mListener: "+listener);
  34.      listener.onCorpusSelected(emoji);
  35.     }
  36.      
  37.    });
  38.   }  
  39. }
  40. }
复制代码
  1. ChatActivity类:写好了回调接口,怎么取去用


  2. private void callBack() {
  3.   mListener = new OnCorpusSelectedListener() {
  4.    @Override
  5.    public void onCorpusSelected(ChatEmoji emoji) {
  6.      
  7.     //if (emoji.getFaceName() != "face_del.png")
  8.     if (TextUtils.isEmpty(emoji.getFaceName())&&emoji.getId()==R.drawable.del_face_btn) {
  9.      int selection = mContent.getSelectionStart();
  10.      String text = mContent.getText().toString();
  11.      if (selection > 0) {
  12.       String text2 = text.substring(selection - 1);
  13.       if ("]".equals(text2)) {
  14.        int start = text.lastIndexOf("[");
  15.        int end = selection;
  16.        mContent.getText().delete(start, end);
  17.        return;
  18.       }
  19.       mContent.getText().delete(selection - 1, selection);
  20.      }
  21.     }else {
  22.      if(emoji.getCharacter() == null){
  23.       return ;
  24.      }
  25.      SpannableString spannableString = FaceConversionUtil
  26.        .getInstace().addFace(getApplicationContext(),
  27.          emoji.getPath(), emoji.getCharacter());
  28.      mContent.append(spannableString);
  29.     }
  30.      
  31.    }
  32.    @Override
  33.    public void onCorpusDeleted() {
  34.     // TODO Auto-generated method stub
  35.    }
  36.   };
  37.   mFaceRelativeLayout.setOnCorpusSelectedListener(mListener);
  38. }
复制代码
以上述代码为例子,总结一下:
写一个回调接口的步骤为
(1)定义一个接口:
  1. public interface OnCorpusSelectedListener {

  2.   void onCorpusSelected(ChatEmoji emoji);

  3.   void onCorpusDeleted();

  4. }
复制代码
(2)声明该接口的成员变量
  1. private OnCorpusSelectedListener listener;
复制代码
(3)创建一个public权限的方法供外界设置改回调
  1. public void setOnCorpusSelectedListener(OnCorpusSelectedListener listener) {

  2.   this.listener = listener;

  3. }
复制代码
(4)使用该接口方法里的方法
  1. listener.onCorpusSelected(emoji);
复制代码
总结一下,怎么在别的类中使用该回调
步骤为:
(1)声明该回调类的变量
  1. /** 表情页的监听事件 */

  2. private OnCorpusSelectedListener mListener;
复制代码
(2)调用该回调类中,对外暴露的设置该回调的方法
  1. mFaceRelativeLayout.setOnCorpusSelectedListener(new OnCorpusSelectedListener() {
  2.    @Override
  3.    public void onCorpusSelected(ChatEmoji emoji) {
  4.      
  5.     //if (emoji.getFaceName() != "face_del.png")
  6.     if (TextUtils.isEmpty(emoji.getFaceName())&&emoji.getId()==R.drawable.del_face_btn) {
  7.      int selection = mContent.getSelectionStart();
  8.      String text = mContent.getText().toString();
  9.      if (selection > 0) {
  10.       String text2 = text.substring(selection - 1);
  11.       if ("]".equals(text2)) {
  12.        int start = text.lastIndexOf("[");
  13.        int end = selection;
  14.        mContent.getText().delete(start, end);
  15.        return;
  16.       }
  17.       mContent.getText().delete(selection - 1, selection);
  18.      }
  19.     }else {
  20.      if(emoji.getCharacter() == null){
  21.       return ;
  22.      }
  23.      SpannableString spannableString = FaceConversionUtil
  24.        .getInstace().addFace(getApplicationContext(),
  25.          emoji.getPath(), emoji.getCharacter());
  26.      mContent.append(spannableString);
  27.     }
  28.      
  29.    }
  30.    @Override
  31.    public void onCorpusDeleted() {
  32.     // TODO Auto-generated method stub
  33.    }
  34.   };);
复制代码
完毕
       其实对于这个表情模块,是可以不用回调实现的,我们把两个类合并,把功能都写到一个类中,那么同样可以实现功能,但是呢,会导致什么问题?这样会出现不能复用,并且带来一个很有严重的问题,耦合度太高,一个类中几千行代码。分开来写的话,这个模块就能够被复用,并且解耦合。把具体的实现留到给以后去实现。形象的形容一下方法回调,其实就是传递一个代码块。类比一下方法的调用,传递的是一个参数,方法的回调,传递的是一个代码块

-------------------------------------------------------
华丽的分割线------------------------------------------------------      

        感谢梁剑老师细致的回答,这是一个很接地气的技术问题。并且,回调经常被用于在封装模块时进行解耦,比如观察者模式就是用回调实现的哦,妈妈再也不用担心面试官问我观察者了。下回再见!



2 个回复

倒序浏览
  1. 接口回调4个步骤

  2. 定义接口以及接口方法;

  3. // 接口方法如果没有参数-->通知效果
  4. // 接口方法,如果定义了参数-->通知传值的效果
  5. /**
  6.   * Interface definition for a callback to be invoked when the checked state
  7.   * of a compound button changed.
  8.   */
  9. public  interface OnCheckedChangeListener {
  10.      /**
  11.       * Called when the checked state of a compound button has changed.
  12.       *
  13.       * @param buttonView The compound button view whose state has changed.
  14.       * @param isChecked  The new checked state of buttonView.
  15.       */
  16.      void onCheckedChanged(CompoundButton buttonView, boolean isChecked);
  17. }
  18. 声明一个接口对象;

  19. private OnCheckedChangeListener mOnCheckedChangeListener;
  20. 在某一个时候(需要回调的时候,或者叫做需要触发的时候,比如上面的老师想到问题的答案、老师来了的时候),接口对象调用接口方法;

  21.    if (mOnCheckedChangeListener != null) {
  22.          mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
  23.      }
  24. 暴露公共方法,通过setter或者构造方法

  25.   /**
  26.   * Register a callback to be invoked when the checked state of this button
  27.   * changes.
  28.   *
  29.   * @param listener the callback to call on checked state change
  30.   */
  31. public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
  32.      mOnCheckedChangeListener = listener;
  33. }
复制代码
回复 使用道具 举报
kungege 来自手机 中级黑马 2015-11-4 20:30:29
藤椅
给力,谢谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马