最近在做一个Android的项目,使用了接口回调方法,当我第一次接触这种方法时,我觉得这个设计真的是很棒,参考了别人的源码自己也跟着敲了.当时也不求甚解.
当后来发现有bug不对劲的时候,不知道是那里出了岔子.于是我就把接口回调这部分代码抽出来, 自己写写demo熟悉一下, 抽出关键的部分,自己面对空白独自码了一遍.写Android用的是Android studio,写demo用的是eclipse,换了一种环境,重新把接口回调这部分代码一边查资料一边凭着理解写出来.
终于发现问题了,bug也随之找出来了.这也算是一种经验吧,把不熟悉不确定的地方自己重新再编写一边,这种效率比较高, 花的时间较少(茫目找bug花的时间真的是没法说了),并且自己又真正学到东西了,弄懂了…想想如果我一头再扎进已经编写较为庞大的项目里面,想把bug找出来估计够呛.
好了,就不多发感慨了.还是将实验demo的过程在这里码下.如果有什么不对的地方还请多多指教,目前刚刚接触这部分, 理论部分欠缺.多多包涵.
有关理论上的知识,我目前没法深入,随着以后知识的积累,回过头来再详细总结.这里先贴出自己的Demo代码:
这里我要做的是,先让两个抽象类(UserA\UserC)实现接口CallBack.然后UserB类有一个属性是CallBack callBack. 用它引用由抽象类创建的匿名类.useB类的方法调用: callBack.方法名() 接着匿名类中的方法就得到回调
CallBack接口如下:
public interface CallBack {
public void getData(String result);
public void getBall(String result);
public void getWater(String result);
}
UserA.class
public abstract class UserA implements CallBack {
@Override
public void getData(String result) {
// TODO Auto-generated method stub
}
@Override
public void getBall(String result) {
// TODO Auto-generated method stub
}
@Override
public void getWater(String result) {
// TODO Auto-generated method stub
}
}
UserC.class
public abstract class UserC implements CallBack {
public void getBall(String result) {
// TODO Auto-generated method stub
}
@Override
public void getData(String result) {
// TODO Auto-generated method stub
}
@Override
public void getWater(String result) {
// TODO Auto-generated method stub
}
}
UserB.class
public class UserB {
private static CallBack callback;
private static UserB instance;
private UserB() {
}
public static UserB getInstance(CallBack back) {
if(instance == null) {
instance = new UserB();
callback = back;
}
return instance;
}
public void catchData(String word) {
System.out.println(callback+"主人吩咐"+word);
callback.getData("数据做好了");
}
public void catchWater(String word) {
System.out.println(callback+"主人吩咐"+word);
callback.getWater("水准备好了");
}
public void catchBall(String word) {
System.out.println(callback+"主人吩咐"+word);
callback.getBall("那你要的球准备好了");
}
public static void main(String[] args) {
UserB.getInstance(new UserA() {
public void getData(String res) {
System.out.println(res);
}
}).catchData("我想获取数据");
UserB.getInstance(new UserC() {
@Override
public void getWater(String result) {
System.out.println(result);
}
}).catchWater("我想喝水");
}
}
好了,在写Demo过程中,我慢慢还原项目中关键部分的场景.
我的预期结果是:
“数据准备好了”
“水准备好了”
但是结果却是这样:
可以看到第二次接口并未回调,预期结果是:“水准备好了”,可上图显示为空。
这里问题在哪,我们先看每次的接口CallBack都是同一个(UserB$1@7852e922),这也不奇怪,上面的代码中我们已经把CallBack作为一个单例了:
if(instance == null) {
instance = new UserB();
callback = back;
}
也就是说,我们每次通过getInstance(new UserA(){…….}),匿名类接口回调其实是不起作用的.因为这个CallBack接口只是引用上一个匿名类,当然回调方法就是上一个匿名类的了.可以这么说,跟目前的这个匿名类没有关系.
解决方法:
public static UserB getInstance(CallBack back) {
callback = back;
if(instance == null) {
instance = new UserB();
// callback = back;
}
return instance;
}
把callBack引用赋值放到if判断之上.
没错,项目中也是这个问题,所以bug是找出来了.解决了接口为什么没有回调的问题了.而我项目中的场景是: 通过Bmob后端云验证登录,也是接口回调,可是结果就是没有返回过来.导致登录一直登不上.原来是我把接口引用弄成了单例的缘故.
以此作为纪念
2018/12/10