Java接口回调

来源:互联网 发布:wow淘宝刷坐骑会封号吗 编辑:程序博客网 时间:2024/06/17 14:16

一、接口回调概述

对于大多数刚刚接触或者没有实际项目的Java学习者来说,并不知道什么是接口回调,接口回调有什么好处,能给开发带来什么好处。下面我将告诉你我所知道的。在我刚刚接触Java时,并不知道什么是接口回调,该怎么用,那时我做了一个小小的项目,在底层处理好数据后,怎么传递给视图进行展示,当时我的做法是开了一个线程,不断的去获取新的值,很显然,这样做的代价是很大的;后面我又用了另外一个方法,就是将数据保存到集合里,每次都取最新的那个值,这样的做法代价也是很大的,需要足够的内存。并且,在一些项目开发中,比如桌面应用或者Android App,当视图层改变,底层的某些引用又得改变,增加了维护成本。有没有这样的方法,不管你的视图如何变化,我底层都不需要变,答案是有的,那就是接口回调。

二、接口回调的使用

首先我编写了一个底层服务类,来模拟底层服务。底层服务实现的功能是一个时间倒数器,时间的变化需要实时的通知给试图,这个时候接口回调就派上大用场了。具体实现见如下代码:

package com.yaohong.callback;/** * 后台数据服务,计数器,单位秒 * @author Yaohong * */public class BackgroundService {    public static final long SLEEP_TIME = 1000;    private int count = 0;    private int time;    private boolean isStart = true;    private CalCount calCountThread;    // 记录使用者注册的接口    private CalCallbackInterface callback;    public BackgroundService(int time){        this.time = time;        calCountThread = new CalCount();    }    /**     * 开始倒数     */    public void start(){        calCountThread.start();    }    /**     * 强制暂停倒数器     */    public void stop(){        isStart = false;    }    /**     * 注册数据回调接口     * @param callback     */    public void addTimeListener(CalCallbackInterface callback){        this.callback = callback;    }    /**     * 定义数据回调接口     * @author Yaohong     *     */    public interface CalCallbackInterface{        public void currentTime(int currentTime);    }    /**     * 计数器倒数线程     * @author ASUS     *     */    private class CalCount extends Thread{        @Override        public void run() {            // 验证time是否正确            if(time <= 0 || time >= Integer.MAX_VALUE){                throw new IllegalArgumentException(time+" is not valid!");            }            while(isStart){                // ① 使用数据回调接口                if(callback != null){                    callback.currentTime(time);                }                // ②                --time;                if(time < 0 ){                    isStart = false;                    break;                }                try {                    Thread.sleep(SLEEP_TIME);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }}

代码中定义了接口CalCallbackInterface,用于对数据变化时进行回调(如果有需要,可以提取出来,分配到独立的包下)。如果学习过Java图形界面编程的人可能知道,这样的做法如何注册鼠标监听事件一样,那么在使用的时候,只需注册这个接口即可得到实时刷新的数据。

接口的使用:

package com.yaohong.callback;import com.yaohong.callback.BackgroundService.CalCallbackInterface;/** * 接口回调测试 *  * @author Yaohong *  */public class CallbackTestMain {    public static void main(String[] args) {        int time = 10;        BackgroundService service = new BackgroundService(time);        service.start();        service.addTimeListener(new CalCallbackInterface() {            // ③            @Override            public void currentTime(int currentTime) {                // ④                System.out.println("Surplus time: " + currentTime);            }        });    }}

使用的方法很简单,只需注册这个接口即可。详情见上述代码

三、接口回调原理

阐述接口回调原理,我将根据上诉所讲的demo进行讲解。

要行成完整的调用过程的前提必须是使用者要注册这个接口,如果使用者没有调用addTimeListener(…)进行接口注册,那么将不产生调用过程。因此,在底层服务的线程中,一定要对callback变量判断是否为空指针,否则,当用户不注册,那么代码会包空指针异常。

如果用户注册接口后,callback将不在是控制针,程序运行到①代码处时,会先判断callback变量是否为null,如果不为null,那么,程序会跳转到③这行代码,然后执行代码④,当执行完这行代码后,程序会跳转回②处继续执行,从而完成一个回调过程。

在某些应用环境下,回调过程将会复杂些,例如在Android应用开发时,由于API严格限制子线程不能够更新主线程UI,因此,直接在代码④处更新UI是会导致程序崩溃的。为了实现接口回调,Android提供了Handler类来进行辅助更新。Handler本身是一个消息队列,子线程的一些操作都会被加入到这个队列中,然后主线程会从这个队列中取出消息进行执行。

四、总结

这里,我仅仅演示了接口回调的简单使用,并没有讲解过多的东西,希望的是快速学会使用接口回调,这样你可以高效编程,某种程度上也可以减轻代码之间的耦合度。

学习过C/C++的人,应该也知道C/C++的主函数也是通过接口回调的方式进行调用的。可见,接口回调是多么的利于编程,同时实现也比较简单,灵活性也高。