Java接口回调

一、接口回调概述

对于大多数刚刚接触或者没有实际项目的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++的主函数也是通过接口回调的方式进行调用的。可见,接口回调是多么的利于编程,同时实现也比较简单,灵活性也高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值