Android 绘图基础:Canvas画布——自定义View基础(绘制表盘、矩形、圆形、弧、渐变)

news2024/11/25 22:34:46

  Canvas画布,通过它我们可以自定义一个View,设置View的相关效果之类的。感觉用法差不多,重要的是要理解方法中传入的参数的含义,比如float类型的参数,传递的是坐标,已开是没有注意传入的参数时坐标,导致我迷糊了一段时间,希望大家不要犯我的错误,记住是坐标啊!。

一、Canvas画布介绍

The Canvas class holds the “draw” calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, Path, text, Bitmap), and a paint (to describe the colors and styles for the drawing).  

  关于Canvas网上也没有什么好的介绍, 我就直接从API中复制过来的,这里翻译一下。

  Canvas 支持“绘制”调用,想要进行绘制,你需要4个基本组成:一个由像素构成的位图,支持绘制调用的画布(绘制位图),一个图元(如矩形,路径,文本,位图),和油漆(用于绘制图的颜色和样式)。

(上面的四个基本组成会在后面代码部分进行解释)

  API中说的究竟是什么意思呢?我们可以把这个Canvas理解成系统提供给我们的一块内存区域(但实际上它只是一套画图的API,真正的内存是下面的Bitmap),而且它还提供了一整套对这个内存区域进行操作的方法,所有的这些操作都是画图API。这样我们就可以在画布上进行绘制了。

二、使用步骤

  上面说了那么多是不是特别想知道它要怎样使用呢?现在我们就来说说他的使用步骤。

2.1使用步骤

1、写一个class类继承自View

2、在继承的class中写它的两个构造器,以前的版本中我们只需要写它的两个构造器(一个构造器参数为View(Context)另一个构造器参数为 View(Context AttributeSet) ),现在版本的升级又新出了两个构造器(View(Context attribute style)带有主题样式的),不管那么多,我们还是只写本来的两个构造器就OK了。

3、在该class中调用onDraw方法和onMeasure()方法。

4、在布局中使用该View

5、进行绘制

2.1使用示例

  下面我们按照上面的步骤一步步进行

1、写一个class类继承自View

public class MyView extends View

2、在继承的class中写它的两个构造器

public MyView(Context context) {

super(context);

}

public MyView(Context context, AttributeSet attrs) {

super(context, attrs);

}

  1. 在该class中重写onDraw方法和onMeasure()方法。

onDraw(我们将在该方法中进行绘制图形)

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

}

onMeasure(获得画布的高度与宽度)

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);

}

补充:由于onMeasure方法中本身就有获取高度与宽度的方法,我们直接点进去(ctrl+左键),复制出来就可以了。

  1. 在布局中使用该View(布局时必须写全包名+类名)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity" >

<com.example.myview.MyView

android:layout_width="match_parent"

android:layout_height="match_parent"

5、进行绘制

我们要如何进行绘制呢?首先我们看些Canvas都能绘制写什么。

drawRect(float left, float top, float right, float bottom, Paint paint)

//绘制矩形(左上右下的坐标,我们可以理解为左上的坐标为我们确定了矩形的左上角点,右下坐标为我们确定了右下角的点,这样一个矩形区域就确定出来了,paint为画笔)

drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)

//绘制圆角矩形(左上右下的坐标)

drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)

//绘制弧(参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数二是起始角(度)在电弧的开始,

参数三扫描角(度)开始顺时针测量的,参数四是如果这是真的话,包括椭圆中心的电弧,并关闭它,实际绘制的是扇形,如果它是假这将是一个弧线,参数五是Paint对象)

drawOval(float left, float top, float right, float bottom, Paint paint)

//绘制椭圆

drawLine(float startX, float startY, float stopX, float stopY, Paint paint)

//绘制直线(XY起止坐标)

drawCircle(float cx, float cy, float radius, Paint paint)

//绘制圆形

drawText(String text, float x, float y, Paint paint)

//绘制文本

其他的不再进行列举,有需要可以查看API文档。

在参数中可以看到我们画图是需要画笔的,下面我们再来看下画笔(画漆)。这里展示一段代码相信你就能够明白了。

Paint mpaintline = new Paint();

mpaintline.setColor(Color.RED);

//设置线宽

mpaintline.setStrokeWidth(10);

//设置抗锯齿

mpaintline.setAntiAlias(true);

//设置空心,比如画实心圆还是空心圆

mpaintcircle.setStyle(Paint.Style.STROKE);

mpainttext.setTextSize(30);

//设置字的位置

mpainttext.setTextAlign(Align.CENTER);

mpainttext.setColor(Color.BLACK);

2.2表盘示例

上面说了那么多,我们来看一个具体而完整的实例,来整理一下思路。

public class MyView extends View

private int width;

private int height;

private Paint mpaintline;

private Paint mpaintcircle;

private Paint mpainttext;

private Calendar mcalendar;

private static final int NEED_INVALIDATE=0x23;

private Handler mhandler=new Handler(){

public void handleMessage(android.os.Message msg) {

switch (msg.what) {

case NEED_INVALIDATE:

//重新获取时间

mcalendar=Calendar.getInstance();

//重新绘制界面

invalidate();//告诉UI主线程重新绘制

//再次发送消息,递归调用,再次监测秒针

mhandler.sendEmptyMessageDelayed(NEED_INVALIDATE, 1000);

break;

default:

break;

}

};

};

public MyView(Context context) {

super(context);

}

public MyView(Context context, AttributeSet attrs) { //为了不是每次都创建Paint,我们在这里创建

super(context, attrs);

mcalendar=Calendar.getInstance();

mpaintline = new Paint();

mpaintline.setColor(Color.RED);

//设置线宽

mpaintline.setStrokeWidth(10);

//设置抗锯齿

mpaintline.setAntiAlias(true);

mpaintcircle = new Paint();

mpaintcircle.setColor(Color.GREEN);

mpaintcircle.setStrokeWidth(10);

//设置空心

mpaintcircle.setStyle(Paint.Style.STROKE);

mpainttext=new Paint();

mpainttext.setTextSize(30);

mpainttext.setTextAlign(Align.CENTER);

mpainttext.setColor(Color.BLACK);

//发送消息,监测秒针

mhandler.sendEmptyMessage(NEED_INVALIDATE);

}

//在此方法中进行绘制

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//绘制圆形

canvas.drawCircle(width/2, height/2, width/2-20, mpaintcircle);

//绘制表芯

canvas.drawCircle(width/2, height/2, 5, mpaintcircle);

//绘制表盘时我们采用旋转画布的思想,让画布进行旋转一定角度,绘制

for(int i=1;i<=12;i++){

//保存画布当前状态

canvas.save();

//指定旋转角度与旋转点

canvas.rotate(360/12*i,width/2,height/2);

//绘制表盘

canvas.drawLine(width/2, height/2-(width/2-20), width/2,height/2-width/2+40, mpaintline);

//绘制文字

canvas.drawText(""+i, width/2, height/2-width/2+70, mpainttext);

//恢复开始位置

canvas.restore();

}

int minute=mcalendar.get(Calendar.MINUTE);

int hour=mcalendar.get(Calendar.HOUR);

int second=mcalendar.get(Calendar.SECOND);

float minudegrees=minute/60f*360;

float hourdregrees=hour*60/12f/60*360;

float senconddegree=second/60f*360;

//绘制分针

canvas.save();

canvas.rotate(minudegrees,width/2,height/2);

canvas.drawLine(width/2, height/2, width/2, height/2-width/2+90, mpaintline);

canvas.restore();

//绘制时针

canvas.save();

canvas.rotate(hourdregrees,width/2,height/2);

canvas.drawLine(width/2, height/2, width/2, height/2-width/2+100, mpaintline);

canvas.restore();

//绘制秒针

canvas.save();

canvas.rotate(senconddegree,width/2,height/2);

canvas.drawLine(width/2, height/2, width/2, height/2-width/2+60, mpaintline);

canvas.restore();

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//固定

2.3绘制圆形progressbar

这里模拟下载,自定义了一个ProgressBar。在MyProgressCircle 中定义出最大进度和当前进度,给出当前进度的SET\GET方法,通过Mainactivity中改变Progres的当前进度,根据当前进度,不停修改半径,重新绘制表层绿色圆形。

public class MyProgressCircle extends View{

private int width;

private int height;

private int Maxprogress=100;

private int Currentprogress;

private Paint PaintBackGround;

private Paint PaintCurrent;

private Paint PaintText;

public int getMaxprogress() {

return Maxprogress;

}

public void setMaxprogress(int maxprogress) {

Maxprogress = maxprogress;

}

//当前进度的set、get方法

public int getCurrentprogress() {

return Currentprogress;

}

public void setCurrentprogress(int currentprogress) {

Currentprogress = currentprogress;

invalidate();

}

public MyProgressCircle(Context context) {

super(context);

// TODO Auto-generated constructor stub

}

public MyProgressCircle(Context context, AttributeSet attrs) {

super(context, attrs);

PaintBackGround=new Paint();

PaintBackGround.setColor(Color.GRAY);

PaintBackGround.setAntiAlias(true);

PaintBackGround.setStrokeWidth(10);

PaintCurrent=new Paint();

PaintCurrent.setColor(Color.GREEN);

PaintCurrent.setAntiAlias(true);

PaintCurrent.setStrokeWidth(10);

PaintText=new Paint();

PaintText.setColor(Color.BLACK);

PaintText.setAntiAlias(true);

PaintText.setTextAlign(Align.CENTER);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawCircle(width/2, height/2,width/2-30 , PaintBackGround);

//根据当前进度改变半径,绘制圆形

canvas.drawCircle(width/2, height/2,(float) (width/2-30)*Currentprogress/Maxprogress, PaintCurrent);

canvas.drawText(Currentprogress*100f/Maxprogress+"%", width/2,height/2, PaintText);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);

}

}

MainActivity中改变progress进度

public class MainActivity extends Activity implements OnClickListener{

private Button btn_circle_progress;

private MyProgressCircle myprogresscircle;

private int progress;

private Handler mhanHandler=new Handler(){

public void handleMessage(android.os.Message msg) {

switch (msg.what) {

case 0x23:

progress++;

if(progress<=100){

myprogresscircle.setCurrentprogress(progress);

mhanHandler.sendEmptyMessageDelayed(0x23, 200);

}

break;

default:

break;

}

};

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.circle_progress);

btn_circle_progress=(Button) findViewById(R.id.mbtn_circleprogress);

myprogresscircle=(MyProgressCircle) findViewById(R.id.mycircleprogress);

btn_circle_progress.setOnClickListener(this);

}

@Override

public void onClick(View v) {

mhanHandler.sendEmptyMessageDelayed(0x23, 1000);

}

}

2.4绘制弧形progressbar

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//设置画弧的区域

RectF oval1=new RectF(width/2-100,height/2-100,width/2+100,height/2+100);

canvas.drawArc(oval1, 270, Currentprogress, false, PaintCurrent);//第二个参数:顺时针起始位置;第三个参数:顺时针转的弧

canvas.drawText(Currentprogress*100f/Maxprogress+"%", width/2,height/2, PaintText);

}

MainActivity

public class MainActivity_ARC extends Activity implements OnClickListener{

private Button btn_arc_progress;

private MyArcProgress myprogressarc;

private int progress;

private Handler mhanHandler=new Handler(){

public void handleMessage(android.os.Message msg) {

switch (msg.what) {

case 0x23:

progress++;

if(progress<=360){

myprogressarc.setCurrentprogress(progress);

mhanHandler.sendEmptyMessageDelayed(0x23, 200);

}

break;

default:

break;

}

};

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.arc_progress);

btn_arc_progress=(Button) findViewById(R.id.mbtn_arcprogress);

myprogressarc= (MyArcProgress) findViewById(R.id.myarcprogress);

btn_arc_progress.setOnClickListener(this);

}

@Override

public void onClick(View v) {

mhanHandler.sendEmptyMessageDelayed(0x23, 1000);

}

}

2.5绘制多条线与矩形

public class MyRectProgress extends View{

private int width;

private int height;

private int Maxprogress=100;

private int Currentprogress;

private Paint PaintBackGround;

private Paint PaintCurrent;

private Paint PaintText;

private int i;

private float[] lines=new float[400];

public int getMaxprogress() {

return Maxprogress;

}

public void setMaxprogress(int maxprogress) {

Maxprogress = maxprogress;

}

public int getCurrentprogress() {

return Currentprogress;

}

public void setCurrentprogress(int currentprogress) {

Currentprogress = currentprogress;

lines[i]=50;

i++;

lines[i]=50+250f*Currentprogress/Maxprogress;

i++;

lines[i]=300;

i++;

lines[i]=50+250f*Currentprogress/Maxprogress;

invalidate();

}

public MyRectProgress(Context context) {

super(context);

// TODO Auto-generated constructor stub

}

public MyRectProgress(Context context, AttributeSet attrs) {

super(context, attrs);

PaintBackGround=new Paint();

PaintBackGround.setColor(Color.GRAY);

PaintBackGround.setAntiAlias(true);

PaintBackGround.setStrokeWidth(10);

PaintCurrent=new Paint();

PaintCurrent.setColor(Color.GREEN);

PaintCurrent.setAntiAlias(true);

PaintCurrent.setStrokeWidth(5);

PaintText=new Paint();

PaintText.setColor(Color.BLACK);

PaintText.setAntiAlias(true);

PaintText.setTextAlign(Align.CENTER);

PaintText.setTextSize(30);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//canvas.drawCircle(width/2, height/2,width/2-30 , PaintBackGround);

canvas.drawRect(50,50 ,300, 300, PaintBackGround);

canvas.drawLines(lines, PaintCurrent);

//canvas.drawLine(50,50+250f*Currentprogress/Maxprogress, 300, 50+250f*Currentprogress/Maxprogress, PaintCurrent);

canvas.drawText(Currentprogress*100f/Maxprogress+"%", width/2,height/2, PaintText);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);

}

}

2.5绘制渐变

样式就是我们开始时图片展示的样式

package com.example.myview;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.LinearGradient;

import android.graphics.Paint;

import android.graphics.Paint.Align;

import android.graphics.RectF;

import android.graphics.Shader;

import android.util.AttributeSet;

import android.view.View;

public class MyotherProgress extends View{

private int width;

private int height;

private int Maxprogress=100;

private int Currentprogress;

private Paint PaintBackGround;

private Paint PaintCurrent;

private Paint PaintText;

public int getMaxprogress() {

return Maxprogress;

}

public void setMaxprogress(int maxprogress) {

Maxprogress = maxprogress;

}

public int getCurrentprogress() {

return Currentprogress;

}

public void setCurrentprogress(int currentprogress) {

Currentprogress = currentprogress;

invalidate();

}

public MyotherProgress(Context context) {

super(context);

// TODO Auto-generated constructor stub

}

public MyotherProgress(Context context, AttributeSet attrs) {

super(context, attrs);

PaintBackGround=new Paint();

PaintBackGround.setColor(Color.GRAY);

PaintBackGround.setAntiAlias(true);

PaintBackGround.setStrokeWidth(10);

PaintCurrent=new Paint();

PaintCurrent.setColor(Color.GREEN);

PaintCurrent.setAntiAlias(true);

PaintCurrent.setStrokeWidth(10);

/* 设置渐变色 颜色是改变的 */

Shader mShader = new LinearGradient(0, 0, 100, 100,

new int[] { Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW,

Color.LTGRAY }, null, Shader.TileMode.REPEAT);

PaintCurrent.setShader(mShader);

PaintText=new Paint();

PaintText.setColor(Color.BLACK);

PaintText.setAntiAlias(true);

PaintText.setTextAlign(Align.CENTER);

PaintText.setTextSize(30);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//底层圆形

canvas.drawCircle(width/2, height/2,width/2-30 , PaintBackGround);

// 设置个新的长方形,扫描测量

RectF oval = new RectF(30,height/2-(width/2-30 ) , width-30 , height/2+width/2-30 );

//绘制扇形

// 画弧,第一个参数是RectF(确定绘制区域):

//该类是第二个参数是角度的开始,

//第三个参数是多少度,

//第四个参数是真的时候画扇形,是假的时候画弧线

canvas.drawArc(oval, 0, Currentprogress*360f/100, true, PaintCurrent);

canvas.drawText(Currentprogress*100f/Maxprogress+"%", width/2,height/2, PaintText);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);

}

}

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

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

相关文章

windows编译x265

msys2的安装参考&#xff1a; MSYS2安装_蜡笔小方的博客-CSDN博客 将下载好的x265放入msys2能找到的目录下&#xff1a; 打开msys2&#xff0c;切换到x265/build/msys-cl目录下 其中&#xff0c;build目录下是x265为了各种平台或者不同编译工具配的编译脚本&#xff1f;&…

儿童护目台灯哪种好用?几款真的保护视力的台灯品牌推荐

儿童眼睛还未发育完全&#xff0c;眼睛比较脆弱&#xff0c;但是现在的小孩子学习任务也比较繁重&#xff0c;经常晚上看书写字&#xff0c;所以选择合适的护眼台灯来保护眼睛很重要。 选择儿童护目台灯需要注意以下几个方面&#xff1a; &#xff08;一&#xff09;色温和亮…

图解KMP算法

子串的定位操作通常称作串的模式匹配。你可以理解为在一篇英语文章中查找某个单词是否存在&#xff0c;或者说在一个主串中寻找某子串是否存在。朴素的模式匹配算法假设我们要从下面的主串S "goodgoogle" 中&#xff0c;找到T "google" 这个子串的位置。…

“终于我从腾讯离职了...”一个年薪40W的测试工程师的自白....

”我递上了我的辞职信&#xff0c;不是因为公司给的不多&#xff0c;也不是因为公司待我不好&#xff0c;但是我觉得&#xff0c;我每天看着我憔悴的面容&#xff0c;每天晚上拖着疲惫的身体躺在床上&#xff0c;我都不知道人生的意义&#xff0c;是赚钱吗&#xff1f;是为了更…

哪种蓝牙耳机通话效果好?通话清晰的蓝牙耳机推荐

出门的时候&#xff0c;如果戴耳机和别人通话&#xff0c;就不必把耳机摘下来&#xff0c;接电话变得前所未有的简单。现在的蓝牙耳机&#xff0c;已经不是单纯的用来听音乐了&#xff0c;而是一种更好的功能。下面这四款蓝牙耳机不仅适合听歌&#xff0c;通话还清晰&#xff0…

C++---最长上升子序列模型---最大上升子序列和(每日一道算法2023.3.3)

注意事项&#xff1a; 本题为"线性dp—最长上升子序列的长度"的扩展题&#xff0c;所以dp思路这里就不再赘述。 题目&#xff1a; 比如&#xff0c;对于序列(1,7,3,5,9,4,8)&#xff0c;有它的一些上升子序列&#xff0c;如(1,7),(3,4,8)等。 这些子序列中和最大为…

【Web安全】PHP安全

一、文件包含漏洞严格来说&#xff0c;文件包含就是代码注入的一种。代码注入&#xff0c;其原理就是注入一段用户能控制的脚本或代码并让服务器端执行。代码注入的典型代表就是文件包含。文件包含可能会出现在JSP、PHP、ASP等语言中&#xff0c;常见函数如下&#xff1a;PHP&a…

好记又实用的获取电脑型号方法

个人常用的方法 方法二最好记又好用。 方法一 dxdiag命令 按下键盘WINR调出运行在输入框输入dxdiag命令后&#xff0c;按下回车&#xff1b;进入DirectX诊断工具&#xff0c;便可查看系统型号等信息。 这里就会显示系统型号。 方法二 设备和打印机 控制面板-查看方式-小图…

Kubernetes学习(二)Pod

创建Pod kubectl创建nginx pod 编写 nginx pod的yaml文件 apiVersion: v1 kind: Pod metadata:name: my-nginxlabels:name: my-nginx spec:containers:- image: nginxname: my-nginxresources:limits:memory: "128Mi"cpu: "500m"ports:- name: nginx-po…

周期性温度和压力波的PID自动控制解决方法

摘要&#xff1a;目前各种PID控制器仪表常用于简单的设定点&#xff08;Set Point&#xff09;和斜坡&#xff08;Ramp&#xff09;程序控制&#xff0c;但对于复杂的正弦波等周期性变量的控制则无能为力。为了采用标准PID控制器便捷和低成本的实现对正弦波等周期性变量的自动控…

TiDB Serverless 和技术生态全景

数据库不是单一软件&#xff0c;而是一个生态体系。成为一款好用的数据库&#xff0c;除了产品自身的能力外&#xff0c;繁荣的技术生态体系也至关重要&#xff0c;既可以提升使用体验&#xff0c;又可以降低使用门槛。 PingCAP 在 2022 年 11 月 1 日正式发布了 TiDB Cloud Se…

浏览器的渲染过程解析

文章目录浏览器渲染进程有哪些&#xff1f;浏览器的渲染过程浏览器渲染进程有哪些&#xff1f; GUI线程&#xff1a;负责渲染浏览器页面&#xff0c;解析html&#xff0c;css&#xff0c;构建DOM树&#xff0c;CSS规则树&#xff0c;渲染树和绘制页面&#xff0c;当界面需要重…

Unity使用webSocket与服务器通信(一)搭建一个简单地服务器和客户端

你想在unity WebGL里面使用TCP通信吗&#xff0c;那么你可以用一用webSocket。当然&#xff0c;桌面端也可以使用webSocket&#xff0c;这样Unity多平台发布的时候&#xff0c;业务层的通信代码可以使用一套&#xff0c;而不是桌面用socket&#xff0c;网页用http… 一、什么是…

精选博客系列|VMware 帮助服务提供商构建零碳未来

当谈到可持续发展的未来时&#xff0c;你首先想到的是哪些技术&#xff1f;大多数人会说电动汽车、太阳能电池板或风电场。但是&#xff0c;我们越来越需要将另一种技术放在列表的首位&#xff1a;通信网络。 领先的通信服务提供商 (CSP) 越来越多地致力于环境可持续性的前沿。…

IDCF DevOps黑客马拉松挑战赛(北京 上海 广州 杭州 大连)

IDCF DevOps黑客马拉松&#xff1a;“打造端到端的DevOps人才”&#xff01; “在36小时内从0到1打造并发布一款产品&#xff01;” DevOps实践与敏捷开发正在席卷IT公司&#xff0c;精益创业、设计思维、增长黑客等硅谷创新思维与方法&#xff0c;正在被越来越多具有真知灼见…

RestTemplate使用HttpClient连接池

文章目录RestTemplate使用HttpClient连接池ClientHttpRequestFactorySimpleClientHttpRequestFactorySimpleClientHttpRequestFactory 设置超时时间HttpURLConnection的缺点HttpComponentsClientHttpRequestFactoryPoolingHttpClientConnectionManager配置连接池HttpClient总结…

【教学典型案例】26.nacos的命名空间名字和id不一致

一&#xff1a;背景介绍 由于dev和localhost使用的同一个命名空间&#xff0c;我们多个服务相互调用的时候&#xff0c;由于开发人员本地启动把本地服务注册到和dev同一个命令空间下&#xff0c;导致dev环境部分功能不能使用&#xff08;在线人员列表无法加载出数据&#xff0…

DatenLord前沿技术分享 No.19

达坦科技专注于打造新一代开源跨云存储平台DatenLord&#xff0c;致力于解决多云架构、多数据中心场景下异构存储、数据统一管理需求等问题&#xff0c;以满足不同行业客户对海量数据跨云、跨数据中心高性能访问的需求。GPU编程可以大幅提升计算速度和效率&#xff0c;从而使得…

门诊患者正在流失?如何打造差异化服务,成功破局,留住患者?

无论是诊所还是医院&#xff0c;长久经营发展始终是围绕品牌、医生、技术、服务这些核心要素来进行运营。 尤其是民营医疗机构&#xff0c;要让患者满意认可&#xff0c;除了医生与诊疗技术&#xff0c;医疗服务也尤为重要。 但是很多民营医疗机构往往更注重前者&#xff0c;而…

新号涨粉22w,搞笑博主再次爆火,小红书近期创作趋势是什么?

2月借势元宵、情人节&#xff0c;小红书平台又涌现出哪些黑马博主&#xff1f;品牌在投放种草方面有何亮眼表现&#xff1f;为洞察小红书平台的内容创作趋势及品牌营销策略&#xff0c;新红推出2月月度榜单&#xff0c;从创作者及品牌两方面入手&#xff0c;解析月榜数据&#…