图片模块封装

news2025/1/20 16:20:53

图片模块封装

  • 一.如何更换图片框架
  • 二.Glide配置
    • 1.依赖:
  • 三.策略模式+构建者模式图片框架搭建
    • 1.ImageOptions图片参数设置
    • 2.IImageLoader接口以及实现子类
    • 3.图片加载策略
    • 4.ImageLoader
    • 5.ImageLoaderManager
    • 6.使用:
    • 四.Bitmap三级缓存二次采样
    • 五.长图大图处理

一.如何更换图片框架

框架设计过程中对于对于架构要求高内聚低耦合,图片加载框架中引
入三方框架提示开发效率,对于技术选型后的方案可能后面需求的变更原三方
sdk无法满足当前业务需求,故而需要更换原有sdk,为了将更改降到最低,所
有前面设计图片加载框架时要考虑当前这个风险点

使用设计模式来进一步解耦代码耦合度,来解决隔离风险点的目的,
即定义接口层业务依赖抽象即当前接口,具体实现有不同三方sdk完成。
因为业务依赖的是接口层对应后期代码维护更改量会控制在最小,对于原软件
稳定性影响也会极小达到更换图片加载框架的目的。

二.Glide配置

1.依赖:

config.gradle配置:

 //Glide
    // Glide集成OkHttp时需要使用的库,库已经将需要适配Okhhtp的大部分代码封装,注意如果之前已经使用了okhttp依赖注释掉
    libIntegration =  'com.github.bumptech.glide:okhttp3-integration:4.13.0'
    libGlide = 'com.github.bumptech.glide:glide:4.13.0'
    libGlideCompiler = 'com.github.bumptech.glide:compiler:4.13.0'//Glide注解处理器的依赖

library-base封装网络

   //glide图片框架
    api libGlide
    api libIntegration
    kapt libGlideCompiler

项目结构:
在这里插入图片描述
缓存配置:

/**
 * @Author : yaotianxue
 * @Time : On 2023/5/22 17:03
 * @Description : MyGlideModule 配置glide缓存
 */
@GlideModule
class CacheGlideModule:AppGlideModule() {
    override fun applyOptions(context: Context, builder: GlideBuilder) {
        //super.applyOptions(context, builder)
        //设置内存缓存大小:根据机器自动计算
//        var  memorySizeCalculator = MemorySizeCalculator.Builder(context).build()
//        builder.setMemoryCache(LruResourceCache(memorySizeCalculator.memoryCacheSize.toLong()))
        //设置内存缓存大小:10M
        builder.setMemoryCache(LruResourceCache(10*1024*1024))
        //设置磁盘缓存大小:500M 默认250M 设置磁盘缓存文件夹名称 "my_image" 默认 "image_manager_disk_cache"
        builder.setDiskCache(InternalCacheDiskCacheFactory(context,"my_image",500*1024*1024))//修改磁盘缓存的文件夹和磁盘大小
    }
}

网络配置:glide默认使用httpUrlConnection完成网络请求,可以改成okhttp

/**
 * @Author : yaotianxue
 * @Time : On 2023/5/22 17:07
 * @Description : OkhttpGlideModule:配置okhttp认证所有证书,可以认证自定义ca证书
 */
@GlideModule
class OkhttpGlideModule:LibraryGlideModule() {
    override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
        //        super.registerComponents(context, glide, registry)
        var client = OkHttpClient.Builder()
            .sslSocketFactory(sSLSocketFactory,trustManager)
            .build()
        registry.replace(GlideUrl::class.java, InputStream::class.java, OkHttpUrlLoader.Factory(client))
    }

    /** 获取一个SSLSocketFactory */
    val sSLSocketFactory: SSLSocketFactory
        get() = try {
            val sslContext = SSLContext.getInstance("SSL")
            sslContext.init(null, arrayOf(trustManager), SecureRandom())
            sslContext.socketFactory
        } catch (e: Exception) {
            throw RuntimeException(e)
        }

    /** 获取一个忽略证书的X509TrustManager */
    val trustManager: X509TrustManager
        get() = object : X509TrustManager {
            override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) { }
            override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) { }
            override fun getAcceptedIssuers(): Array<X509Certificate> { return arrayOf() }
        }
}

三.策略模式+构建者模式图片框架搭建

1.ImageOptions图片参数设置

/**
 * @Author : yaotianxue
 * @Time : On 2023/5/22 15:04
 * @Description : ImageOptions图片设置
 */
class ImageOptions( var placeImage:Int,//占位符
                    var errorImage:Int,//错误图
                    var isStaticImage:Boolean,//是否为静态图片
                    var isGif:Boolean,//是否为动图
                    var imageSize:Array<Int>,//图片大小
                    var skipMemoryCache:Boolean,//关闭内存缓存
                    var skipDiskCache:Boolean//关闭磁盘缓存
){
    constructor(builder: Builder):this(
        builder.placeImage,
        builder.errorImage,
        builder.isStaticImage,
        builder.isGif,
        builder.imageSize,
        builder.skipMemoryCache,
        builder.skipDiskCache
    )

    class Builder{
         var placeImage:Int = 0//占位符
         var errorImage:Int = 0 //错误图
         var isStaticImage:Boolean = true//是否为静态图片
         var isGif:Boolean = false//是否为动图
         var imageSize:Array<Int> = arrayOf(0,0)//图片大小
         var skipMemoryCache:Boolean = false//关闭内存缓存
         var skipDiskCache:Boolean = false//关闭磁盘缓存
        fun  setPlaceImage(placeImage:Int):Builder{
            this.placeImage = placeImage
            return this
        }
        fun  setErrorImage(errorImage:Int):Builder{
            this.errorImage = errorImage
            return this
        }
        fun build():ImageOptions{
            return ImageOptions(this)
        }
    }
   
}

2.IImageLoader接口以及实现子类

/**
 * @Author : yaotianxue
 * @Time : On 2023/5/22 15:03
 * @Description : IImageLoader
 */
interface IImageLoader {
    /**
     * 加载本地图片到指定图片控件
     */
    fun loadFileIntoImageView(context: Context,file: File,target: ImageView,config: ImageOptions)
    /**
     * 加载网络图片到指定图片控件
     */
    fun loadUrlIntoImageView(context: Context,url: String,target: ImageView,config: ImageOptions)
    /**
     * 加载资源图片到指定图片控件
     */
    fun loadResourceIntoImageView(context: Context,source: Int,target: ImageView,config: ImageOptions)
    /**
     * 加载Uri图片到指定图片控件
     */
    fun loadUriIntoImageView(context: Context, uri: Uri, target: ImageView, config: ImageOptions)
    /**
     * 加载二进制数组到指定图片控件
     */
    fun loadByteArrayIntoImageView(context: Context,bytes: Array<Byte>,target: ImageView,config: ImageOptions)
}

GlideImageLoader/FrscoImageLoader/PicassoImageLoader

/**
 * @Author : yaotianxue
 * @Time : On 2023/5/22 16:50
 * @Description : GlideImageLoader
 */
class GlideImageLoader:IImageLoader {
    override fun loadFileIntoImageView(
        context: Context,
        file: File,
        target: ImageView,
        config: ImageOptions,
    ) {
        loadImageView(context,file,target,config)
    }

    override fun loadUrlIntoImageView(
        context: Context,
        url: String,
        target: ImageView,
        config: ImageOptions,
    ) {
        loadImageView(context,url,target,config)
    }

    override fun loadResourceIntoImageView(
        context: Context,
        source: Int,
        target: ImageView,
        config: ImageOptions,
    ) {
        loadImageView(context,source,target,config)
    }

    override fun loadUriIntoImageView(
        context: Context,
        uri: Uri,
        target: ImageView,
        config: ImageOptions,
    ) {
        loadImageView(context,uri,target,config)
    }

    override fun loadByteArrayIntoImageView(
        context: Context,
        bytes: Array<Byte>,
        target: ImageView,
        config: ImageOptions,
    ) {
        loadImageView(context,bytes,target,config)
    }


    /**
     * 加载
     */
    private fun loadImageView(
        context: Context,
        source: Any,
        target: ImageView,
        config: ImageOptions,
    ) {
        var builder = GlideApp.with(context).load(source)
        setBuilderOptions(builder,config)
        builder.into(target)

    }

    /**
     * 设置图片参数
     */
    private fun setBuilderOptions(builder: GlideRequest<Drawable>, config: ImageOptions) {
        config.let {
            var options = RequestOptions()
            if(config.placeImage != 0){
                options.placeholder(config.placeImage)
            }
            if(config.errorImage != 0){
                options.error(config.errorImage)
            }
            config.imageSize.let {
                if(config.imageSize.size != 2){
                    throw IllegalArgumentException("please set imageSize length size is 2")
                }
                options.override(config.imageSize[0],config.imageSize[1])
            }
            if(config.skipDiskCache)  options.diskCacheStrategy(DiskCacheStrategy.NONE)
            if(config.skipMemoryCache) options.skipMemoryCache(true)
            builder.apply(options)
        }
    }
}

3.图片加载策略

/**
 * @Author : yaotianxue
 * @Time : On 2023/5/22 18:51
 * @Description : ImageStrategy
 */
enum class ImageStrategy {
    Glide,Picasso,Fresco
}

4.ImageLoader

/**
 * @Author : yaotianxue
 * @Time : On 2023/5/22 18:49
 * @Description : ImageLoader
 */
class ImageLoaderManager(var imageStrategy: ImageStrategy):IImageLoader{
    private var imageLoader:IImageLoader = when(imageStrategy){
        ImageStrategy.Glide -> GlideImageLoader()
        ImageStrategy.Fresco -> FrescoImageLoader()
        ImageStrategy.Picasso -> PicassoImageLoader()
    }

    override fun loadFileIntoImageView(
        context: Context,
        file: File,
        target: ImageView,
        config: ImageOptions,
    ) {
        imageLoader.loadFileIntoImageView(context,file,target,config)
    }

    override fun loadUrlIntoImageView(
        context: Context,
        url: String,
        target: ImageView,
        config: ImageOptions,
    ) {
        imageLoader.loadUrlIntoImageView(context,url,target,config)
    }

    override fun loadResourceIntoImageView(
        context: Context,
        source: Int,
        target: ImageView,
        config: ImageOptions,
    ) {
        imageLoader.loadResourceIntoImageView(context,source,target,config)
    }
    
}

5.ImageLoaderManager

/**
 * @Author : yaotianxue
 * @Time : On 2023/5/22 18:49
 * @Description : ImageLoader
 */
class ImageLoaderManager(var imageStrategy: ImageStrategy):IImageLoader{
    private var imageLoader:IImageLoader = when(imageStrategy){
        ImageStrategy.Glide -> GlideImageLoader()
        ImageStrategy.Fresco -> FrescoImageLoader()
        ImageStrategy.Picasso -> PicassoImageLoader()
    }

    override fun loadFileIntoImageView(
        context: Context,
        file: File,
        target: ImageView,
        config: ImageOptions,
    ) {
        imageLoader.loadFileIntoImageView(context,file,target,config)
    }

    override fun loadUrlIntoImageView(
        context: Context,
        url: String,
        target: ImageView,
        config: ImageOptions,
    ) {
        imageLoader.loadUrlIntoImageView(context,url,target,config)
    }

    override fun loadResourceIntoImageView(
        context: Context,
        source: Int,
        target: ImageView,
        config: ImageOptions,
    ) {
        imageLoader.loadResourceIntoImageView(context,source,target,config)
    }

    override fun loadUriIntoImageView(
        context: Context,
        uri: Uri,
        target: ImageView,
        config: ImageOptions,
    ) {
        imageLoader.loadUriIntoImageView(context,uri,target,config)
    }

    override fun loadByteArrayIntoImageView(
        context: Context,
        bytes: Array<Byte>,
        target: ImageView,
        config: ImageOptions,
    ) {
        imageLoader.loadByteArrayIntoImageView(context,bytes, target, config)
    }
}

6.使用:

   		val manager = ImageLoaderManager(ImageStrategy.Glide)
        val options: ImageOptions = ImageOptions.Builder()
            .setPlaceImage(R.mipmap.ic_launcher)
            .setErrorImage(R.mipmap.ic_launcher)
            .skipDiskCache(true)
            .skipDiskCache(true)
            .build()
        val imgUrl =
           "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic13.nipic.com%2F20110324%2F6999402_050849259122_2.jpg&refer=http%3A%2F%2Fpic13.nipic.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1634607623&t=be4a718762c5f4aadb0e640961437e41"
        manager.loadUrlIntoImageView(this, imgUrl, imageView, options)

在使用的时候可以进一步封装

四.Bitmap三级缓存二次采样

传送门走你!!

五.长图大图处理

https://www.jianshu.com/p/5ec13b295dd0


import android.app.appsearch.GetByDocumentIdRequest;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;

/**
 * @Author : yaotianxue
 * @Time : On 2023/5/22 19:47
 * @Description : LargeImageView
 */
public class LargeImageView extends View implements GestureDetector.OnGestureListener {
    private BitmapRegionDecoder mDecoder;
    //绘制的区域
    private volatile Rect mRect = new Rect();
    private int mScaledTouchSlop;
    //分别记录上次的滑动的坐标
    private int mLastX = 0;
    private int mLastY = 0;
    //图片的宽度和高度
    private int mImageWidth,mImageHeight;
    //手势控制器
    private GestureDetector mGestureDetector;
    //Bitmap工厂参数配置
    private BitmapFactory.Options mOptions;

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public LargeImageView(Context context) {
        super(context);
        init(context,null);
    }

    public LargeImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context,attrs);
    }



    public LargeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context,attrs);
    }

    public LargeImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context,attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        //设置图片参数,如果对图片要求高采用ARGB_8888
        mOptions = new BitmapFactory.Options();
        mOptions.inPreferredConfig = Bitmap.Config.RGB_565;

        mScaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
        Log.d("ytx", "init: "+mScaledTouchSlop);
        //初始化手势控制器
        mGestureDetector = new GestureDetector(context,this);
        InputStream inputStream = null;
        try {
            inputStream = context.getResources().getAssets().open("demo.jpg");
            //初始化BitmapRegionDecoder,并用他显示图片
            mDecoder = BitmapRegionDecoder.newInstance(inputStream,false);
            //设置为true只采取图片的宽度和高度,不加载进内存
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(inputStream,null,options);
            mImageHeight = options.outHeight;
            mImageWidth = options.outWidth;

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
    //把触摸事件交给手势控制器处理
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }

    @Override
    public boolean onDown(MotionEvent e) {
        mLastX = (int) e.getRawX();
        mLastY = (int) e.getRawY();
        return true;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        int x = (int) e2.getRawX();
        int y = (int) e2.getY();
        move(x,y);
        return true;
    }
    //移动的时候更新图片的显示的区域
    private void move(int x, int y) {
        int deltaX = x - mLastX;
        int deltaY = y - mLastY;
        if(mImageWidth > getWidth()){
            mRect.offset(-deltaX,0);
            if(mRect.right < mImageWidth){
                mRect.right = mImageWidth;
                mRect.left = mImageWidth - getWidth();
            }
            if(mRect.left < 0){
                mRect.left = 0;
                mRect.right = getRight();
            }
            invalidate();
        }

        if(mImageHeight > getHeight()){
            mRect.offset(0,-deltaY);
            if(mRect.bottom > mImageHeight){
                mRect.bottom = mImageHeight;
                mRect.top = mImageHeight - getHeight();
            }
            if(mRect.top < 0){
                mRect.top = 0;
                mRect.bottom = getHeight();
            }
            invalidate();
        }
        mLastX = x;
        mLastY = y;

    }

    @Override
    public void onLongPress(MotionEvent e) {
        mLastX = (int) e.getRawX();
        mLastY = (int) e.getRawY();
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        int x = (int)e2.getRawX();
        int y = (int) e2.getRawY();
        move(x,y);
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Bitmap bitmap = mDecoder.decodeRegion(mRect,mOptions);
        canvas.drawBitmap(bitmap,0,0,null);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        int imageWidth = mImageWidth;
        int imageHeight = mImageHeight;
        mRect.left = imageWidth/2 - width/2;
        mRect.top = imageHeight/2 - height/2;
        mRect.right = mRect.left +width;
        mRect.bottom = mRect.top + height;

    }
}
  

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

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

相关文章

华为OD机试真题 Java 实现【任务混部】【2023Q1 200分】

一、题目描述 公司创新实验室正在研究如何最小化资源成本&#xff0c;最大化资源利用率&#xff0c;请你帮他们解决一个任务混部问题&#xff1a; 有taskNum项任务&#xff0c;每个任务有开始时间&#xff08;startTime &#xff09;&#xff0c;结束时间&#xff08;endTime…

Linux系统之cut命令的基本使用

Linux系统之cut命令的基本使用 一、cut命令介绍1. cut命令简介2.cut命令的由来 二、在Linux中命令帮助1. cut的help帮助信息2. cut的选项 三、cut的基本使用1. 指定字段的内容2. 使用分隔符打印文本内容3. 显示行中指定范围的字符 四、cut命令的日常使用1. 提取IP地址2. 提取本…

position:sticky-粘性吸附布局

一、描述 就是在一个滚动的容器里,将一个子元素设置为postion:sticky 在元素显示在可视区域内,显示的效果与position:relative 一致&#xff0c;当元素被滑动出可视区域外是,显示效果与position:fixed一致 二、注意事项 1、父元素需要存在滚动&#xff08;overflow:auto&…

快速入门Springboot整合Datagpa操作数据库

简介SpringDatagpa Spring Data JPA是Spring Data家族的一部分&#xff0c;可以轻松实现基于JPA的存储库。 . JPA是ORM规范&#xff0c;Hibernate是JPA规范的具体实现&#xff0c;这样的好处是开发者可以面向JPA规范进行持久层的开发&#xff0c;而底层的实现则是可以切换的。S…

day5 套接字属性设置

选项的级别 SOL_SOCKET 该级别的选项只作用于套接字本身 SOL_LRLMP 该级别的选项作用于IrDA协议 IPPROTO_IP 该级别的选项作用于IPv4协议 IPPROTO_IPV6 该级别的选项作用于IPv6协议 IPPROTO_RM 该级别的选项作用于可靠的多播传输 IPPROTO_TCP 该级别的选项适用于流式…

信道通信基础 - 传输介质(双绞线、光纤)

文章目录 1 概述2 传输介质2.1 双绞线2.2 光纤 3 扩展3.1 网工软考真题 1 概述 2 传输介质 2.1 双绞线 双绞线&#xff1a;8 根铜导线每 2 根扭在一起&#xff08;百兆用 4 根&#xff0c;千兆必须用 8 根&#xff09;分类 2.2 光纤 光纤&#xff1a;利用光在 玻璃或塑料纤…

很长一段时间没有用Ubuntu,无法获得锁**,锁正由进程***持有

问题分析&#xff1a;意思就是有另一个进程占用了apt-get&#xff0c;因为Ubuntu锁的访问机制是互斥的&#xff0c;即同一时间只能允许一个进程占用&#xff0c;只需要将那个占用的进程强制删除掉就行了。 使用如下两条命令即可&#xff1a; sudo rm /var/lib/dpkg/lock-fron…

藏在大神们收藏夹里的实用工具类网站!

今天来给大家分享几个大神们推荐的&#xff0c;藏在收藏夹里的宝藏工具类网站 Toolfk https://www.toolfk.com/ 一款程序员的工具箱&#xff0c;里面包含非常多实用工具&#xff0c;不仅有各种程序相关功能&#xff0c;还有很多不懂程序人也能用的简易功能。PHP在线加密工具、…

docker-compose 搭建maven私服 nexus与配置

目录 创建文件目录 docker-compose.yml文件 登录 配置 创建阿里云代理仓库 配置仓库顺序 maven配置文件setting.xml配置 本地jar包部署 在linux上搭建 创建文件目录 mkdir -p /apps/minio/{config,data,logs} 赋权限 chmod -R 777 data docker-compose.yml文件 version…

按键中断实验和串口中断实验

目录 【1】按键中断实验 【2】串口中断实验 【1】按键中断实验 实验要求&#xff1a;STM32上电LED&#xff08;PB0&#xff09;灯灭 &#xff0c;当检测到按键&#xff08;PA8&#xff09;按下时处理中断事件&#xff0c;变量i 扩展&#xff1a;知识点 响应优先级-》在两个中断…

Camtasia2023简体中文版屏幕录像 支持MP4/AVI/WMV等多种格式

在现在的网络互联网时代&#xff0c;越来越多的人走上了自媒体的道路。有些自媒体人会自己在网络上录制精彩视频&#xff0c;也有一些人会将精彩、热门的电影剪辑出来再加上自己给它的配音&#xff0c;做成大家喜欢看的电影剪辑片段。相信不管大家是自己平时有独特的爱好也好、…

TOGAF架构开发方法—ADM 架构需求管理

一、目标 需求管理阶段的目标是&#xff1a; 确保需求管理流程持续运行&#xff0c;并在所有相关的 ADM 阶段运行管理在 ADM 周期或阶段的任何执行期间确定的架构要求确保在执行阶段时&#xff0c;每个阶段都可以使用相关的体系结构要求 二、输入 需求管理阶段的输入包括&am…

Bean作用域、生命周期

bean作用域如何设置行为模式Bean的生命周期 bean作用域 Bean 的作用域指bean在spring框架的某种行为模式&#xff1b;bean的6种作用域分别是以下&#xff1a; 1&#xff1a;单例&#xff08;Singleton&#xff09;作用域 2&#xff1a;原型&#xff08;Prototype&#xff09;作…

chatgpt赋能Python-python_chardet

Python Chardet: 自动识别文件编码的利器 Python Chardet 是一个用于自动识别文件编码的工具&#xff0c;它基于最新的编码库&#xff0c;可以自动检测多种编码类型。在今天的多语言互联网时代&#xff0c;我们经常需要处理各种编码类型的文件&#xff0c;例如&#xff1a;爬虫…

chatgpt赋能Python-python_calc

介绍 Python Calc 是一款基于 Python 编程语言开发的计算器应用程序。它具备简单易用、功能强大、可扩展性强等特点&#xff0c;广泛应用于数据科学、机器学习、人工智能等领域。 Python Calc 提供了基本算术运算、三角函数、指数函数、对数函数等常用数学运算&#xff0c;同…

chatgpt赋能Python-python_cancel

Python的Cancel&#xff1a;如何有效管理异步操作&#xff1f; 在编写Python应用程序时&#xff0c;异步编程是提高性能和响应能力的重要方式。然而&#xff0c;异步编程会带来一些挑战&#xff0c;如复杂性和不可预测的代码执行顺序。幸运的是&#xff0c;Python提供了一个名…

设计模式-简单Demo掌握责任链模式

文章目录 1、要点2、Demo3、进阶掌握 参考文章&#xff1a; 基本原理&#xff1a;责任链模式 | 菜鸟教程 (runoob.com) 简单例子&#xff1a;五分钟学设计模式.12.责任链模式_哔哩哔哩_bilibili 阿里巴巴的应用&#xff1a;责任链模式在复杂数据处理场景中的实战 责任链模式&am…

chatgpt赋能Python-python_6_0_

Python——一门强大的编程语言 Python是现今最流行的编程语言之一&#xff0c;广泛应用于Web开发、数据分析、人工智能等领域&#xff0c;优雅简洁的语法和强大的库使得Python成为很多开发者的首选语言。 Python的优点 易学易用 作为一门动态类型的语言&#xff0c;Python的…

由浅入深Dubbo核心源码剖析SpringBoot整合使用

目录 1 Dubbo与SpringBoot的整合2 公用RPC接口工程3. 服务端工程4. 消费端工程5. 工程调用验证 1 Dubbo与SpringBoot的整合 基于Zookeeper实现Dubbo与Spring Boot的集成整合,依赖导入 <properties><dubbo-version>2.7.8</dubbo-version><spring-boot.vers…