Android(安卓)回调机制举例及个人理解
先举1个Java的例子用来引入
小王去向小李请教数学题,小李在判断完小王的问题后将结果返回给小王:
//这个是回调接口,在小李返回结果给小王时要用到public interface CallBack { void solve(String result);}
//这个是小王,重写了solve方法public class Wang implements CallBack { private Li li; public Wang(Li li) { this.li = li; } public void ask(String question){ li.answer(Wang.this , question); }//此处的solve()便是回调方法,可以在其他类中调用 @Override public void solve(String result) { System.out.println("答案是:" + result); }}
//这个是小李,判断完问题之后将答案通过callBack.solve返回给小王public class Li { public void answer(CallBack callBack, String question){ String result = "不知道"; System.out.println("问题是:" + question); if(question.equals("1+1=?")) result = "2"; else if(question.equals("1+2=?")) result = "3"; callBack.solve(result); }}
测试类public class Test { public static void main(String[]args){ Li li = new Li(); Wang wang = new Wang(li); wang.ask("1+1=?" ); }}
此例如果能看懂就不必再深究了,这里只是为了引入
直接看下面的Android的实际例子
简单需求:点击Fragment的Button,改变MainActivity中TextView的显示
//定义接口public interface CallBackListener { void onCallBack();}
public class MainActivity extends AppCompatActivity implements CallBackListener { int i = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }//根据自定义需求重写方法 @Override public void onCallBack() { TextView textView = findViewById(R.id.textView); textView.setText("点击了" + i + "次"); i++; }}
public class CallBackFragment extends Fragment { private CallBackListener callBackListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment, container, false); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (getActivity() instanceof CallBackListener) callBackListener = (CallBackListener) getActivity(); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); Button btn = (Button) view.findViewById(R.id.button); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(callBackListener != null) callBackListener.onCallBack(); } }); }}
onCreateView和onViewCreated的区别:日常使用没区别:)
onCreateView可能会(极少)在绘制子View(TextView、Button等除了主Layout的其他控件)的时候崩溃,这时可以尝试在onCreateView中初始化主Layout,而在onViewCreated中使用findViewById初始化其他控件。
调用顺序:onViewCreated()会在onCreateView()之后立马被调用
来源:stackoverflow
综上2个例子,以下是我个人的理解和想法
-
首先创建一个接口L(如上例的CallBack或CallBackListener),并在其中添加你想要的效果( solve() 或 onCallBack() )。这个接口可以创建在外面,也可以创建在某个类中
-
哪个类想要实现这个效果,这个效果最终体现在哪个类上面,就让这个类继承前面定义好的那个接口(如果这个接口是单独新建的情况1),或者在这个类中new出接口并重写方法(如果这个接口是新建在其他类中的情况2)
情况1: 你想让小王去输出结果(因为如果是小王输出的话就说明小王拿到了结果),就让Wang继承CallBack;你想让MainActivity中的Textview显示点击次数,那就让MainActivity继承CallBackListener。
情况2: 假设CallBack接口是定义在类A中的,而你想要B类去实现你要的效果。public class A {public void add(MyCallBack myCallBack){ myCallBack.complete();}public interface MyCallBack{ void complete();};}
public class B {A a = new A();public void test(){ a.add(new A.MyCallBack(){ @Override public void complete() { //自定义效果 } });};}
-
第二步中你想要的那个效果,是谁导致的,是谁触发的,就在谁中引用
比如:小王拿到结果是由于小李将答案传给了小王,所以小李就需要通过answer()中的callback获取到小王的引用,通过callBack.solve把resul传给小王;MainActivity中TextView变化是由于Fragment中Button的点击,所以在Fragment中,首先通过getActivity()获取到MainActivity,然后在Button的点击事件中调用onCallBack()方法达到效果;自定义效果是在调用a.add时触发的,所以就在类A中引用,即myCallBack.complete()(情况二这种情况,一般引用的类和接口定义的类是同一个类)
这时候就要考虑为什么需要有Callback的存在,它的意义是什么
在Java学习中我们就知道了,接口的作用是「我想要一个XX效果,但是我目前实现不出来,或者说实现的不完全,那就把它定义成一个接口,让下面会用到这个效果的类去继承,然后再根据自己的情况去重调代码」
我们这时候举例,假如这个我们想要的效果就是点击事件
Button原生的点击事件
package android.view;public interface OnClickListener {void onClick(View v);//省去了其他代码}
//MainActivity类public class MainActivity extends Activity implements OnClickListener{ private Button button; @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button)findViewById(R.id.button1); button.setOnClickListener(this); } @Override public void onClick(View v) {//这里写你想要效果} }
//参见‘个人的理解和想法’第三点//因为这个效果的直接来由是「我点击了View」 (Button隶属View),所以需要在View类中获取MainActivity并去调用MainActivity的onClick()方法public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource {public OnClickListener mOnClickListener; public void setOnClickListener(@Nullable OnClickListener l) { if (!isClickable()) { setClickable(true); } //获取到了MainActivity,类似于例2中的getActivity() getListenerInfo().mOnClickListener = l; } public boolean performClick() {if (li != null && li.mOnClickListener != null) {playSoundEffect(SoundEffectConstants.CLICK);//点击事件,这里即是「回调」li.mOnClickListener.onClick(this);result = true;} } //省去了其他代码}
具体分析可以看简书
由上总结,回调其实就是:
A调用B的方法b,需要传入A自身引用,或通过其他方式( getActivity() )拿到A的引用,在方法b执行完毕之后,再利用拿到的A的引用,来调用A中的方法
以上为个人理解,如果有哪里各位dalao觉得不对或者可以改进的希望可以提出,如果有疑惑想要一起交流的也同样欢迎
更多相关文章
- 网页标签
- Android(安卓)翻书效果
- Android下利用Fragment+RadioGroup和TabHost实现底部选项卡的效
- 最简便实现Android(安卓)ListView选中item高亮显示
- Android(安卓)框架层为IMountService 增加新接口
- Android(安卓)开发艺术探索学习笔记(二)
- cocos2d怎么设置屏幕朝向?横屏 or 竖屏设置
- [置顶] 【Android】 给我一个Path,还你一个酷炫动画
- Android(安卓)搜索结果关键字动态匹配筛选变色效果且高亮显示