Android中的接口回调机制

news2024/10/6 0:35:29

文章目录

      • 1.回调的含义和用途
      • 2.java实现接口回调
      • 3.Android中接口回调的体现
      • 4.接口回调在异步任务中的体现

1.回调的含义和用途

一般来说,模块之间都存在一定的调用关系,从调用方式上看,可以分为三类同步调用、异步调用和回调。同步调用是一种阻塞式调用,即在函数A的函数体里通过书写函数B的函数名来调用之,使内存中对应函数B的代码得以执行。异步调用是一种类似消息或事件的机制解决了同步阻塞的问题,例如A通知B后,他们各走各的路,互不影响,不用像同步调用那样,A通知B后,非得等到B走完后,A才继续走。回调是一种双向的调用模式,也就是说,被调用的接口被调用时也会调用对方的接口,例如A要调用B,B在执行完又要调用A。
回调的思想是:
类A的a()方法调用类B的b()方法
类B的b()方法执行完毕主动调用类A的callback()方法

通俗而言: 就是A类中调用B类中的某个方法C, 然后B类中反过来调用A类中的方法D, D这个方法就叫回调方法, 这样子说你是不是有点晕晕的, 其实我刚开始也是这样不理解, 看了人家说比较经典的回调方式:
1.class A实现接口CallBack callback——背景1
2.class A中包含一个class B的引用b ——背景2
3.class B有一个参数为callback的方法f(CallBack callback) ——背景3
4.A的对象a调用B的方法 f(CallBack callback) ——A类调用B类的某个方法 C
5.然后b就可以在f(CallBack callback)方法中调用A的方法 ——B类调用A类的某个方法D

2.java实现接口回调

在C/C++中,要实现回调函数,被调用函数要告诉调用者自己的指针地址。但是Java没有指针地址,不能传递方法的地址,一般采用接口回调的方法来实现:把实现某一接口的类创建的对象的引用赋给该接口声明的接口变量,那么该接口变量就可以调用被调用类实现的接口的方法。
 原理:首先创建一个回调对象,然后再创建一个控制器对象,将回调对象需要被调用的方法告诉控制器对象,控制器对象负责检查某个场景是否出现或某个条件是否满足,当满足时,自动调用回调对象的方法。

package Demon;

//创建回调接口实现类
public class Boss implements AcceptListener{
    public void acceptEvent(String result){
        if(result.equals("ok")){
            System.out.println("接受到了工作结果,老板很满意");
        }else {
            System.out.println("接受到了工作结果,老板很生气!");
        }
    }
}
class Manager implements AcceptListener{
    public void acceptEvent(String result){
        if(result.equals("ok")){
            System.out.println("接受到了工作结果,经理很满意");
        }else {
            System.out.println("接受到了工作结果,经理很生气!");
        }
    }
}
class Tester implements AcceptListener{
    public void acceptEvent(String result){
        if(result.equals("ok")){
            System.out.println("接受到了工作结果,测试很满意");
        }else {
            System.out.println("接受到了工作结果,测试很生气!");
        }
    }
}

//创建回调接口
interface AcceptListener {
    public void acceptEvent(String result);
}

//创建控制类,要持有回调接口
class Employee{
    AcceptListener listener;

    public void setListener(AcceptListener listener) {
        this.listener = listener;
    }

    public void doWork(){
        System.out.println("玩命工作中...");
        if(listener!=null){
            listener.acceptEvent("ok");
        }
    }
    public void haveRest(){
        System.out.println("工作太累了,需要休息一天");

        if(listener!=null){
            listener.acceptEvent("休息");
        }
    }
}

//测试类
class TestMain{
    public static void main(String[] args) {
        Employee employee = new Employee();
        //创建控制器对象,将提供给他的回调对象传入
        employee.setListener(new Boss());
        //启动控制器对象运行
        employee.doWork();
    }
}

在这里插入图片描述
设置接口就相对于设置一个用途,相当于可以将这个用途抽取出来供多个人可以使用,比较灵活

3.Android中接口回调的体现

package com.example.intenttest;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.NonNull;

public class MyDialog extends Dialog implements View.OnClickListener{

    Button btn1,btn2;
    EditText et;
    TextView waimainTv;

    interface OnEnsureListener{
        public void onEnsure(String msg);
    }
    OnEnsureListener onEnsureListener;

    public void setListener(OnEnsureListener listener) {
        this.onEnsureListener = listener;
    }

    public MyDialog(@NonNull Context context) {
        super(context);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mydialog);
        //只要是调用的本类的方法或变量加不加this都一样。因为findViewById是MyDialog继承的方法
        btn1=findViewById(R.id.dg_btn1);
        btn2=findViewById(R.id.dg_btn2);
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
        et=findViewById(R.id.dg_et);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.dg_btn1:
                String msg = et.getText().toString();
                if(!TextUtils.isEmpty(msg)){
                    if(onEnsureListener !=null){
                        onEnsureListener.onEnsure(msg);
                    }
                }
                break;
            case R.id.dg_btn2:
                cancel();
                break;
        }
    }

    public void setTextView(TextView tv) {
         waimainTv=tv;
    }
}

OnEnsureListener就是android系统所约好的接口,然后在我们写的应用程序中传入回调对象,这样就可以达到接口统一,实现不同的效果。

package com.example.intenttest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class MainActivity2 extends AppCompatActivity {
    TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        tv=findViewById(R.id.tv);
    }
  public void onClick(View view){
     switch (view.getId()){
         case R.id.tv:
             MyDialog dialog = new MyDialog(this);
             dialog.show();
             dialog.setListener(new MyDialog.OnEnsureListener() {
                 @Override
                 public void onEnsure(String msg) {
                     Log.i("=====", "onEnsure: "+msg);
                     tv.setText(msg);
                 }
             });
             break;
     }
  }
}

在这里插入图片描述
点击确定后,点一下会变成你输入的内容

4.接口回调在异步任务中的体现

package com.example.intenttest;

import android.os.AsyncTask;


public class MyTask extends AsyncTask<String,Void,byte[]> {

    public interface CallBack{
        public void onSuccess(byte[] bytes);
        public void onError();
    }
    CallBack mCallBack;

    public void setCallBack(CallBack callBack) {
        mCallBack = callBack;
    }

    @Override
    protected byte[] doInBackground(String... params) {
        //进行子线程操作的函数
        byte[] content = HttpUtils.getByteContent(params[0]);

        return content;
    }

    @Override
    protected void onPostExecute(byte[] bytes) {
        super.onPostExecute(bytes);
        //将字节数组转换为位图
        if(bytes!=null&&bytes.length!=0){
           mCallBack.onSuccess(bytes);
        }else {
            mCallBack.onError();
        }
    }
}

package com.example.intenttest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpUtils {
    public static byte[] getByteContent(String path){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        try {
            try {
                HttpURLConnection conn=(HttpURLConnection) new URL(path).openConnection();
                InputStream is = conn.getInputStream();
                int hasRead=0;
                byte[] buf = new byte[1024];
                while (true){
                    hasRead=is.read(buf);
                    if(hasRead==-1){
                        //读完了,跳出循环,不读了
                        break;
                    }else {
                        baos.write(buf,0,hasRead);
                    }
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
       return baos.toByteArray();
    }

}

package com.example.intenttest;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;

public class MainActivity2 extends AppCompatActivity {
    TextView tv,tv2;
    ImageView iv;
    String url="https://img1.baidu.com/it/u=378860652&size=w500&n=0&g=0n&f=jpeg?sec=1646658692&t=cbeca35343cf07495a91f56c444974ff";
    String url2="https://www.163.com/news/article/GVE6NVOQ0001899N.html?clickfrom=w_lb_1_big";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        tv=findViewById(R.id.tv);
        tv2=findViewById(R.id.tv2);
        iv=findViewById(R.id.iv);
    }
  public void onClick(View view){
     switch (view.getId()){
         case R.id.tv:
             showDialog();
             break;
         case R.id.tv2:
             MyTask myTask = new MyTask();
             myTask.setCallBack(new MyTask.CallBack() {
                 @Override
                 public void onSuccess(byte[] bytes) {
                     try {
                         String s = new String(bytes, 0, bytes.length, "UTF-8");
                         tv2.setText(s);

                     } catch (UnsupportedEncodingException e) {
                         e.printStackTrace();
                     }
                 }

                 @Override
                 public void onError() {
                     tv2.setText("加载不到啊");
                 }
             });
             myTask.execute(url2);
             break;
         case R.id.iv:
             showImage();
             break;
     }
  }

    private void showImage() {
        MyTask task = new MyTask();
        task.setCallBack(new MyTask.CallBack() {
            @Override
            public void onSuccess(byte[] bytes) {
                Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                iv.setImageBitmap(bitmap);
            }

            @Override
            public void onError() {
                iv.setImageResource(R.drawable.pc1);
            }
        });
        task.execute(url);
    }

    private void showDialog() {
        MyDialog dialog = new MyDialog(this);
        dialog.show();
        dialog.setListener(new MyDialog.OnEnsureListener() {
            @Override
            public void onEnsure(String msg) {
                Log.i("=====", "onEnsure: "+msg);
                tv.setText(msg);
            }
        });
    }
}

上面通过接口回调很灵活,不仅通过该接口可以实现图片的加载也可以实现网页数据的加载。
在这里插入图片描述
因为在到点击事件的时候设置接口(是new的),当传入到Mytask类里的时候,通过传过来的对象给当前的接口赋值,然后通过当前接口调用的方法( mCallBack.onSuccess(bytes); mCallBack.onError();),从而去执行实现了的接口方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/416482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVAWeb04-DOM

1. DOM 1.1 概述 1.1.1 官方文档 地址: https://www.w3school.com.cn/js/js_htmldom.asp 1.1.2 DOM 介绍 DOM 全称是 Document Object Model 文档对象模型就是把文档中的标签&#xff0c;属性&#xff0c;文本&#xff0c;转换成为对象来管理 1.2 HTML DOM&#xff08;文档…

为什么现代企业都在使用ERP系统 它有哪些优势

随着科技的不断发展&#xff0c;企业管理方式也在不断地发生改变。在这个信息化的时代&#xff0c;企业要想取得成功&#xff0c;必须要善于利用先进的信息化技术工具。其中&#xff0c;ERP系统是企业管理中不可或缺的重要工具。本文将探讨现代企业为什么会使用ERP系统&#xf…

CPU占用率高怎么办?正确解决方法在这里!

案例&#xff1a;CPU占用率高怎么解决 【各位朋友&#xff0c;我的电脑现在运行太慢了&#xff0c;同事说可能是CPU占用率太高了&#xff0c;但对本电脑小白来说&#xff0c;完全不知道怎么处理&#xff0c;大家有什么好的方法可以解决这个问题吗&#xff1f;】 在计算机中&a…

快看这些wireshark 命令,必须得会!

wireshark捕获命令 捕获器表达式语法&#xff1a; 限定词三类 Type&#xff1a;host、net、prot 指出其后数字或名字的意义&#xff08;主机&#xff0c;网段&#xff0c;端口&#xff09; Direction&#xff1a;src、dst 指出传输方向 &#xff08;源 、目的&#xff09; …

GcExcel Java Edition 6.0.6 Crack

概述 GrapeCity Documents for Excel&#xff0c;Java 版&#xff0c;是一个编程接口&#xff0c;允许 Java 开发人员以编程方式大规模创建和操作 Excel 文档。GrapeCity Documents for Excel 是一种解决方案&#xff0c;允许开发人员跨 Java 应用程序导入/导出、创建报告和模板…

论文阅读《GlueStick: Robust Image Matching by Sticking Points and Lines Together》

论文地址&#xff1a;https://arxiv.org/abs/2304.02008 源码地址&#xff1a;https://github.com/cvg/GlueStick 概述 针对视角变化时在闭塞、无纹理、重复纹理区域的线段匹配难的问题&#xff0c;本文提出一种新的匹配范式&#xff08;GlueStick&#xff09;&#xff0c;该方…

MySQL性能优化(三)事务与锁详解

文章目录什么是数据库事务&#xff1f;事务的四大特性&#xff1a;ACID事务的开启与结束案例表结构与数据案例事务并发的三大问题&#xff1a;脏读&#xff08;一个事务读取到了其他事务未提交的数据&#xff09;不可重复读&#xff08;一个事务读取到其他事务已提交的数据造成…

Qt在安卓手机输出‘hello,world‘

我也想实现这样的功能。 最开始的参考文章&#xff1a; (2条消息) Qt android 开发环境搭建_逝水流年丶轻染尘的博客-CSDN博客 方案1&#xff1a;(失败) 我之前已经下载过 Qt5.14.2了&#xff0c;所以我想直接添加组件 中间过程参考&#xff1a; (2条消息) Qt更新组件出现&…

敏捷开发模式下如何用 PingCode 这类工具迭代管理

迭代&#xff08;Sprint&#xff09;是 Scrum 敏捷开发框架的核心&#xff0c;正确的迭代可以帮助敏捷团队提高工作交付速度。Scrum 团队以完成迭代待办列表为工作目标&#xff0c;并在迭代结束时交付一定的产品增量。PingCode 以产品待办列表作为迭代管理的核心&#xff0c;因…

java并发编程之美第二章读书笔记

并发编程的其他基础知识 什么是多线程的并发编程 并发: 同一时间段内多个任务同时都在执行,且执行都没有执行结束,强调的是在一个时间段内同时执行,而一个时间段由多个时间积累而成的,所以并发的多个任务在单位时间内并不一定同时执行 并行: 单位时间内多个任务同时在执行…

基于GPT-4免费生成代码的工具!小游戏,管理系统都能生成!

Cursor支持Python、Java、C、JavaScript、C#等等&#xff0c;可AI生成代码&#xff0c;功能非常强大&#xff01;这篇教程将教你如何下载安装&#xff0c;带你玩转Cursor 目录 话不多说&#xff0c;先看能力&#xff1a; 只需要三步&#xff0c;就可以AI出你想要的代码&#x…

测试基础知识

开发模型和测试模型 软件的生命周期 软件的生命周期指的是产品从设想开始到软件不再使用的时间。 软件的生命周期可以分为6个阶段&#xff1a;需求分析&#xff0c;计划&#xff0c;设计&#xff0c;编码&#xff0c;测试&#xff0c;运行维护。 瀑布模型 适用项目&#xf…

[考研数据结构]第3章之栈的基本知识与操作

文章目录 栈的基本概念 栈的实现 顺序栈 共享栈 链栈 栈的基本概念 栈的定义 栈&#xff08;Stack&#xff09;是只允许在一端进行插入或删除操作的线性表 相关术语 栈顶&#xff08;Top&#xff09;线性表允许进行插入或删除的那一端称之为栈顶栈底&#xff08;Bottom&…

JAVASE基础(二)

这里写目录标题JAVASE基础11.科学计数法12.编码和字符集12.编译格式问题13.类型转换类型级别自动类型转换强制类型转换特殊情况14.final修饰符a.修饰变量b.修饰方法c.修饰类15.scanner使用16.两个数交换引入中间变量位运算数学数方法一数学计数方法二17.扩展赋值运算符&#xf…

递归算法_字符串反转_20230412

递归算法-字符串反转 前言 递归算法对解决重复的子问题非常有效&#xff0c;字符串反转也可以用递归算法加以解决&#xff0c;递归算法设计的关键是建立子问题和原问题之间的相关性&#xff0c;同时需要确立递归退出的条件&#xff1b;如果递归退出的条件无法确定&#xff0c…

【LeetCode: 面试题 17.13. 恢复空格 | 暴力递归=>记忆化搜索=>动态规划】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Redis安装和配置

目录本章重点Redis安装Redis启动和停止配置后台启动连接前的配置本章重点 主要掌握安装和启动了解redis的配置文件进行配置掌握Redis几种启动方式 Redis安装 下载 Redis官网 点击下载 解压 然后将下载好的压缩包上传到服务器,进行解压! tar zxvf 进行解压 编译 我们要进行编…

4.12每日一练

题目&#xff1a;给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外&#xff0c;这两个数…

学生信息管理系统【GUI/Swing+MySQL】(Java课设)

系统类型 Swing窗口类型Mysql数据库存储数据 使用范围 适合作为Java课设&#xff01;&#xff01;&#xff01; 部署环境 jdk1.8Mysql8.0Idea或eclipsejdbc 运行效果 本系统源码地址&#xff1a;https://download.csdn.net/download/qq_50954361/87673902 更多系统资源库…

安全运营场景下的机器学习算法应用

观测到一个有意思的现象&#xff1a; 假设把安全划分为 基础安全 和 业务安全&#xff0c;PR类的议题中&#xff0c;会出现分级&#xff1a;基础安全领域&#xff0c;喜欢讲纵深防御&#xff0c;给出一个炫酷的架构图&#xff0c;然后各种技术关键字往上标&#xff1b;业务安全…