Java接口回调

Posted YQS_Love

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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++的主函数也是通过接口回调的方式进行调用的。可见,接口回调是多么的利于编程,同时实现也比较简单,灵活性也高。

以上是关于Java接口回调的主要内容,如果未能解决你的问题,请参考以下文章

Java--回调接口

java基础接口回调的实现

有关接口回调的java题,求解。

java8函数接口处理回调

Java_接口回调与匿名内部类

Java接口回调