自定义控件android.r,Android控件架构与自定义控件

前言

最近在开发的路上越走越远了,每天在看各位大神公众号更新内容是自定义View的时候,一些小的内容有点模具,决定回过头来温习一下过往的内容。此篇也是根据android群英传来总结的一篇文章。

1 Android控件架构

Android的每个控件都是占一块矩形的区域,大致的分两类,继承View和ViewGroup,ViewGroup相当于一个容器,他可以管理多个字View,整个界面上的控件形成了一个树形结构,也就是我们常说的控件树,上层控件负责下层控件的测量和绘制,并且传递交互事件,通过findviewbyid()这个方法来获取,其实就是遍历查找,在树形图的顶部都有一个ViewParent对象,这就是控制核心,所有的交互管理事件都是由它统一调度和分配,从而进行整个视图的控制

2 View的测量

我们想要绘制一个View,首先还是得知道这个View的大小,系统是如何把他绘制出来的,在Android中,我们要想绘制一个View,就必须要知道这个View的大小,然后告诉系统,这个过程在onMeasure()中进行。

Android给我们提供了一个设计短小精悍的类——MeasureSpec类,通过他来帮助我们测量View, MeasureSpec是一个32位的int值,其中高2位为测量模式,低30为测量的大小,在计算中使用位运算时为了提高并且优化效率

三种测量模式如下:

EXACTLY 精确值模式

表示父视图希望子视图的大小应该是由specSize的值来决定的,系统默认会按照这个规则来设置子视图的大小,开发人员当然也可以按照自己的意愿设置成任意的大小。

AT_MOST最大值模式

控件的尺寸不超过父控件允许的最大尺寸即可

UNSPECIFIED

表示开发人员可以将视图按照自己的意愿设置成任意的大小,没有任何限制。这种情况比较少见,不太会用到。

一份模板代码:

private int measureWidth(int measureSpec) {

int result = 0;

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

if (specMode == MeasureSpec.EXACTLY) {

result = specSize;

} else {

result = 200;

if (specMode == MeasureSpec.AT_MOST) {

result = Math.min(result, specSize);

}

}

return result;

}

3 View的绘制

Canvas顾名思义,画布的意思,而onDraw()就一个参数,就是Canvas了,我们要在其他地方绘制的话,就需要new对象了

Canvas canvas = new Canvas(Bitmap);

//绘制直线

canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint);

//绘制矩形

canvas.drawRect(float left, float top, float right, float bottom, Paint paint);

//绘制圆形

canvas.drawCircle(float cx, float cy, float radius, Paint paint);

//绘制字符

canvas.drawText(String text, float x, float y, Paint paint);

//绘制图形

canvas.drawBitmap(Bitmap bitmap, float left, float top, Paint paint);

4 ViewGroup的测量

前面也说过,ViewGroup是老大,他是用来管理View的,包括View的大小什么的,当我们的ViewGroup大小是包裹内容的时候,实际上ViewGroup会遍历所有的子View,来获取View的大小,从而决定自身的大小,而在其他模式下,会通过具体的值来自定自身的大小

ViewGroup遍历所有的View会调用所有的View的onMeasure()方法来获取测量结果,当子View测量完毕之后,,就需要将子View放在合适的地方,这部分是由onLayout()来进行的,在我们自定义ViewGroup的时候,一般都要重写onLayout()方法控制子View显示位置的逻辑,同样,如果需要wrap_content属性,那就必须重写onLayout()方法了,这点和View是相同的

5 ViewGroup的绘制

ViewGroup在一般情况下是不会绘制的,因为他本身没有需要绘制的东西,如果不是指定ViewGroup的背景颜色,他连onDraw()都不会调用,但是ViewGroup会使用dispatchDraw()来绘制其他子View,其过程同样是遍历所哟普的子View,并调用子View的绘制方法来完成绘制的

6 自定义View

自定义View一直是个难点,Android自带的控件很难满足我们的需求,所欲我们需要重写控件或者自定义一个View,但是一般强大的View,都还是存在少许的bug的,而且现在Android ROM的多样性,适配问题也越来越麻烦了,当然,自定义View你熟悉之后,可以了解系统绘制控件的原理,而且能让你的APP更加美观,强大。

在View中通常有以下比较重要的回调方法

首先,我们应该了解一下比较重要的回调方法:

onDraw() 绘制View的显示内容

onMeasure() 使用此方法时多是该View支持wrap_content属性

onFinishInflate() 从XML加载组件后回调

onSizeChanged() 组件大小改变后回调

onMeasure(int widthMeasureSpec, int heightMeasureSpec)回调该方法进行测量

onLayout(boolean changed, int left, int top, int right, int bottom)回调该方法确定显示位置

onTouchEvent(MotionEvent event) 监听到触摸事件时的回调

以上就是几种常用的回调的方法.上面的方法并不需要全部写出来,看个人需要,一般我们实现自定义控件有三种方法

对现有的控件进行扩展

通过组件来实现新的控件

重写View来实现全新的控件

6.1 对现有控件进行扩展

这是一个我们十分常用的一个方法,用来对现有的控件进行扩展,比如TextView需要渐变啊什么的,挺常用的,这里我们就来写一个小栗子,我們先來看下效果

183ded0b8680

public class MyTextView extends TextView {

private Paint mPaint1, mPaint2;

public MyTextView(Context context) {

super(context);

initView();

}

public MyTextView(Context context, AttributeSet attrs) {

super(context, attrs);

initView();

}

public MyTextView(Context context, AttributeSet attrs,

int defStyleAttr) {

super(context, attrs, defStyleAttr);

initView();

}

private void initView() {

mPaint1 = new Paint();

mPaint1.setColor(getResources().getColor(

android.R.color.holo_blue_light));

mPaint1.setStyle(Paint.Style.FILL);

mPaint2 = new Paint();

mPaint2.setColor(Color.YELLOW);

mPaint2.setStyle(Paint.Style.FILL);

}

@Override

protected void onDraw(Canvas canvas) {

// 绘制外层矩形

canvas.drawRect(

0,

0,

getMeasuredWidth(),

getMeasuredHeight(),

mPaint1);

// 绘制内层矩形

canvas.drawRect(

10,

10,

getMeasuredWidth() - 10,

getMeasuredHeight() - 10,

mPaint2);

canvas.save();

// 绘制文字前平移10像素

canvas.translate(10, 0);

// 父类完成的方法,即绘制文本

super.onDraw(canvas);

canvas.restore();

}}

一个稍微复杂的TextView:

183ded0b8680

这个可以利用LinearGradient,Shader,Matrix,来完成,来实现一个闪闪发光的闪动效果,我们充分的利用Shader渲染器,来设置一个不断变化的LinearGradient,首先我们要在onSizeChanged()方法中完成一些初始化操作

public class CoolTextView extends TextView {

private int mViewWidth;

//初始化画笔

private Paint mPaint;

//渲染器

private LinearGradient mLinearGradient;

//矩阵

private Matrix matrix;

private int mTranslate;

public CoolTextView(Context context) {

super(context);

}

public CoolTextView(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

mPaint=new Paint();

if (mViewWidth==0){

mViewWidth=getMeasuredWidth();

if (mViewWidth>0){

//获取当前TextView的画笔

mPaint=getPaint();

//渲染器

mLinearGradient=new LinearGradient(0,0,mViewWidth,0,

new int[]{Color.BLUE, 0xffffffff, Color.BLUE},

null, Shader.TileMode.CLAMP);

mPaint.setShader(mLinearGradient);

matrix=new Matrix();

}

}

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

if (matrix!=null){

//修改可以改变显示的速度

mTranslate+=mViewWidth/10;

if (mTranslate>1*mViewWidth){

mTranslate=-mViewWidth;

}

matrix.setTranslate(mTranslate,0);

mLinearGradient.setLocalMatrix(matrix);

//每隔100毫秒闪动一下

postInvalidateDelayed(100);

}

}

/*

LinearGradient参数:

float x0: 渐变起始点x坐标

float y0:渐变起始点y坐标

float x1:渐变结束点x坐标

float y1:渐变结束点y坐标

int[] colors:颜色 的int 数组

float[] positions: 相对位置的颜色数组,可为null, 若为null,可为null,颜色沿渐变线均匀分布

Shader.TileMode tile: 渲染器平铺模式*/

}

**6.2 复合控件 **

创建一个复核人控件可以很好的创建出具有重要功能的控件集合,这种方式经常需要继承一个合适的ViewGroup,再给他添加指定功能的控件,从而组成一个新的合适的控件,通过这种方式创建的控件,我们一般都会给他指定的一些属性,让他具有更强的扩展性,下面就以一个TopBar为例子,讲解如何创建复合控件

定义属性

我们需要给他定义一些属性,这样的话,我们需要在values下新建一个attrs.xml文件

我们在代码中是可以用< declare-styleable >标签去声明一些属性的,然后name相当于ID让我们的类可以找到,,确定好之后,我们新建一个类,就叫TopBarView

package com.zc.demo;

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.drawable.Drawable;

import android.util.AttributeSet;

import android.view.ViewGroup;

/**

* TopBar

* Created by Zc on 17/8/31.

*/

public class TopBarView extends ViewGroup {

private int mLeftTextColor;

private Drawable mLeftBackground;

private String mLeftText;

private int mRightTextColor;

private Drawable mRightBackgroup;

private String mRightText;

private float mTitleSize;

private int mTitleColor;

private String mTitle;

//带参构造方法

public TopBarView(Context context, AttributeSet attrs) {

super(context, attrs);

//通过这个方法,你可以从你的attrs.xml文件下读取读取到的值存储在你的TypedArray

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TopBar);

//读取出相应的值设置属性

mLeftTextColor = ta.getColor(R.styleable.TopBar_leftTextColor, 0);

mLeftBackground = ta.getDrawable(R.styleable.TopBar_leftBackground);

mLeftText = ta.getString(R.styleable.TopBar_leftText);

mRightTextColor = ta.getColor(R.styleable.TopBar_rightTextColor, 0);

mRightBackgroup = ta.getDrawable(R.styleable.TopBar_rightBackground);

mRightText = ta.getString(R.styleable.TopBar_rightText);

mTitleSize = ta.getDimension(R.styleable.TopBar_titleTextSize, 10);

mTitleColor = ta.getColor(R.styleable.TopBar_titleTextColor, 0);

mTitle = ta.getString(R.styleable.TopBar_title);

//获取完TypedArray的值之后,一般要调用recyle方法来避免重复创建时候的错误

ta.recycle();

}

6.3 重写View来实现全新的控件

当我们Android原生的控件不满足的话,我们可以继承原来的控件修改,也可以组合起来使用,更加可以继承View创建一个新的控件View

183ded0b8680

效果如图所示

public class CircleProgressView extends View {

private int mMeasureHeigth;

private int mMeasureWidth;

private Paint mCirclePaint;

private float mCircleXY;

private float mRadius;

private Paint mArcPaint;

private RectF mArcRectF;

private float mSweepAngle;

private float mSweepValue = 66;

private Paint mTextPaint;

private String mShowText;

private float mShowTextSize;

public CircleProgressView(Context context, AttributeSet attrs,

int defStyleAttr) {

super(context, attrs, defStyleAttr);

}

public CircleProgressView(Context context, AttributeSet attrs) {

super(context, attrs);

}

public CircleProgressView(Context context) {

super(context);

}

@Override

protected void onMeasure(int widthMeasureSpec,

int heightMeasureSpec) {

mMeasureWidth = MeasureSpec.getSize(widthMeasureSpec);

mMeasureHeigth = MeasureSpec.getSize(heightMeasureSpec);

setMeasuredDimension(mMeasureWidth, mMeasureHeigth);

initView();

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

// 绘制圆

canvas.drawCircle(mCircleXY, mCircleXY, mRadius, mCirclePaint);

// 绘制弧线

canvas.drawArc(mArcRectF, 270, mSweepAngle, false, mArcPaint);

// 绘制文字

canvas.drawText(mShowText, 0, mShowText.length(),

mCircleXY, mCircleXY + (mShowTextSize / 4), mTextPaint);

}

private void initView() {

float length = 0;

if (mMeasureHeigth >= mMeasureWidth) {

length = mMeasureWidth;

} else {

length = mMeasureHeigth;

}

mCircleXY = length / 2;

mRadius = (float) (length * 0.5 / 2);

mCirclePaint = new Paint();

mCirclePaint.setAntiAlias(true);

mCirclePaint.setColor(getResources().getColor(

android.R.color.holo_blue_bright));

mArcRectF = new RectF(

(float) (length * 0.1),

(float) (length * 0.1),

(float) (length * 0.9),

(float) (length * 0.9));

mSweepAngle = (mSweepValue / 100f) * 360f;

mArcPaint = new Paint();

mArcPaint.setAntiAlias(true);

mArcPaint.setColor(getResources().getColor(

android.R.color.holo_blue_bright));

mArcPaint.setStrokeWidth((float) (length * 0.1));

mArcPaint.setStyle(Style.STROKE);

mShowText = setShowText();

mShowTextSize = setShowTextSize();

mTextPaint = new Paint();

mTextPaint.setTextSize(mShowTextSize);

mTextPaint.setTextAlign(Paint.Align.CENTER);

}

private float setShowTextSize() {

this.invalidate();

return 50;

}

private String setShowText() {

this.invalidate();

return "Panda_Program";

}

public void forceInvalidate() {

this.invalidate();

}

public void setSweepValue(float sweepValue) {

if (sweepValue != 0) {

mSweepValue = sweepValue;

} else {

mSweepValue = 25;

}

this.invalidate();

}

}

在来一个例子 效果如下所示

183ded0b8680

模拟音频输入

public class VolumeView extends View {

private int mWidth;

private int mRectWidth;

private int mRectHeight;

private Paint mPaint;

private int mRectCount;

private int offset = 5;

private double mRandom;

private LinearGradient mLinearGradient;

public VolumeView(Context context) {

super(context);

initView();

}

public VolumeView(Context context, AttributeSet attrs) {

super(context, attrs);

initView();

}

public VolumeView(Context context, AttributeSet attrs,

int defStyleAttr) {

super(context, attrs, defStyleAttr);

initView();

}

private void initView() {

mPaint = new Paint();

mPaint.setColor(Color.BLUE);

mPaint.setStyle(Paint.Style.FILL);

mRectCount = 12; //条形数量

}

//条形的渐变色

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

mWidth = getWidth();

mRectHeight = getHeight();

mRectWidth = (int) (mWidth * 0.6 / mRectCount);

mLinearGradient = new LinearGradient(

0,

0,

mRectWidth,

mRectHeight,

Color.YELLOW,

Color.BLUE,

Shader.TileMode.CLAMP);

mPaint.setShader(mLinearGradient);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

for (int i = 0; i < mRectCount; i++) {

mRandom = Math.random();

float currentHeight = (float) (mRectHeight * mRandom);

canvas.drawRect(

(float) (mWidth * 0.4 / 2 + mRectWidth * i + offset),

currentHeight,

(float) (mWidth * 0.4 / 2 + mRectWidth * (i + 1)),

mRectHeight,

mPaint);

}

//300毫秒重新绘制一次

postInvalidateDelayed(300);

}

}

7 自定义ViewGroup

这个管理子View的管理者,我们来定义一下,通常我们自定义ViewGroup是需要onMeasure()来测量的,然后重写onLayout()来确定位置,重写onTouchEvent()来相应事件

接下来制作一个仿ScrollView的效果并且增加粘性事件。

public class MyScrollView extends ViewGroup {

private int mScreenHeight;

private Scroller mScroller;

private int mLastY;

private int mStart;

private int mEnd;

public MyScrollView(Context context) {

super(context);

initView(context);

}

public MyScrollView(Context context, AttributeSet attrs) {

super(context, attrs);

initView(context);

}

public MyScrollView(Context context, AttributeSet attrs,

int defStyleAttr) {

super(context, attrs, defStyleAttr);

initView(context);

}

private void initView(Context context) {

WindowManager wm = (WindowManager) context.getSystemService(

Context.WINDOW_SERVICE);

DisplayMetrics dm = new DisplayMetrics();

wm.getDefaultDisplay().getMetrics(dm);

mScreenHeight = dm.heightPixels;

mScroller = new Scroller(context);

}

@Override

protected void onLayout(boolean changed,

int l, int t, int r, int b) {

int childCount = getChildCount();

// 设置ViewGroup的高度

MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();

mlp.height = mScreenHeight * childCount;

setLayoutParams(mlp);

for (int i = 0; i < childCount; i++) {

View child = getChildAt(i);

if (child.getVisibility() != View.GONE) {

child.layout(l, i * mScreenHeight,

r, (i + 1) * mScreenHeight);

}

}

}

@Override

protected void onMeasure(int widthMeasureSpec,

int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int count = getChildCount();

for (int i = 0; i < count; ++i) {

View childView = getChildAt(i);

measureChild(childView,

widthMeasureSpec, heightMeasureSpec);

}

}

@Override

public boolean onTouchEvent(MotionEvent event) {

int y = (int) event.getY();

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

mLastY = y;

mStart = getScrollY();

break;

case MotionEvent.ACTION_MOVE:

if (!mScroller.isFinished()) {

mScroller.abortAnimation();

}

int dy = mLastY - y;

if (getScrollY() < 0) {

dy = 0;

}

if (getScrollY() > getHeight() - mScreenHeight) {

dy = 0;

}

scrollBy(0, dy);

mLastY = y;

break;

case MotionEvent.ACTION_UP:

int dScrollY = checkAlignment();

if (dScrollY > 0) {

if (dScrollY < mScreenHeight / 3) {

mScroller.startScroll(

0, getScrollY(),

0, -dScrollY);

} else {

mScroller.startScroll(

0, getScrollY(),

0, mScreenHeight - dScrollY);

}

} else {

if (-dScrollY < mScreenHeight / 3) {

mScroller.startScroll(

0, getScrollY(),

0, -dScrollY);

} else {

mScroller.startScroll(

0, getScrollY(),

0, -mScreenHeight - dScrollY);

}

}

break;

}

postInvalidate();

return true;

}

private int checkAlignment() {

int mEnd = getScrollY();

boolean isUp = ((mEnd - mStart) > 0) ? true : false;

int lastPrev = mEnd % mScreenHeight;

int lastNext = mScreenHeight - lastPrev;

if (isUp) {

//向上的

return lastPrev;

} else {

return -lastNext;

}

}

@Override

public void computeScroll() {

super.computeScroll();

if (mScroller.computeScrollOffset()) {

scrollTo(0, mScroller.getCurrY());

postInvalidate();

}

}

}

8 事件拦截机制分析

这章讲的是一个事件拦截机制的一些基本概念,,当Android系统扑捉到用户的各种输入事件之后,如何准确的传递给真正需要这个事件的控件尼?其实Android提供了一套非常完善的事件传递,处理机制,来帮助开发者完成准确的事件分配和处理要想了解拦截机制,我们首先要知道什么事触摸事件,一般MotionEvent提供的手势,我们常用的几个DOWN,UP,MOVE什么的在MotionEvent中封装了很多东西,比如获取坐标点event.getX()和getRawX()获取

一般ViewGroup我们需要重写三个方法

@Override

public boolean dispatchTouchEvent(MotionEvent ev) {

return super.dispatchTouchEvent(ev);

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

return super.onInterceptTouchEvent(ev);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

return super.onTouchEvent(event);

}

而View则只要重写两个方法

@Override

public boolean dispatchTouchEvent(MotionEvent ev) {

return super.dispatchTouchEvent(ev);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

return super.onTouchEvent(event);

}

小结

至此空间架构与自定义控件基础内容就完成了,日后碰见有趣的自定义控件,我会更新在我的博客上,欢迎浏览

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

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

相关文章

基于 PTS 压测轻松玩转问题诊断

简介&#xff1a;性能测试 PTS&#xff08;Performance Testing Service&#xff09;是具备强大的分布式压测能力的 SaaS 压测平台&#xff0c;可模拟海量用户的真实业务场景&#xff0c;全方位验证业务站点的性能、容量和稳定性。 作者&#xff1a;智云 为什么要做压测的问题…

阿里云开源业内首个应用多活项目 AppActive,与社区共建云原生容灾标准

简介&#xff1a;继高可用架构团队的 Sentinel、Chaosblade 开源后&#xff0c;第三个重磅高可用产品&#xff1a;应用多活 AppActive 正式开源&#xff0c;形成高可用的三架马车&#xff0c;帮助企业构建稳定可靠的企业级生产系统&#xff0c;提高企业面对容灾、容错、容量等问…

清晰还原31年前现场,火山引擎超清修复Beyond经典演唱会

7月3日晚&#xff0c;抖音携手环球音乐旗下厂牌宝丽金&#xff0c;直播经过火山引擎超清修复的Beyond Live1991生命接触演唱会及纪念音乐会精选内容&#xff0c;吸引了超1.4亿人次观看。 Beyond是一支成立于1983年的摇滚乐队&#xff0c;随着粤语音乐的兴起&#xff0c;Beyond…

如何定位并修复 HttpCore5 中的 HTTP2 流量控制问题

简介&#xff1a;开篇吹一波阿里云性能测试服务 PTS&#xff0c;PTS 在 2021 年 5 月份已经上线了对 HTTP2 协议的支持&#xff08;底层依赖 httpclient5&#xff09;&#xff0c;在压测时会通过与服务端协商的结果来决定使用 HTTP1.1 或者 HTTP2 协议。 作者&#xff1a;风起…

全链路灰度之 RocketMQ 灰度

简介&#xff1a;本文将以上次介绍过的《如何用 20 分钟就能获得同款企业级全链路灰度能力&#xff1f;》中的场景为基础&#xff0c;来进一步介绍消息场景的全链路灰度。 作者&#xff1a;亦盏 之前的系列文章中&#xff0c;我们已经通过全链路金丝雀发布这个功能来介绍了 M…

普洛斯数据中心发布DC Brain系统,科技赋能智慧化运营管理

7月5日&#xff0c;普洛斯数据中心发布了DC Brain智慧化运营管理系统。该系统由普洛斯历时两年自主研发&#xff0c;契合现代化数据中心平台的发展趋势。目前已应用于普洛斯旗下数据中心&#xff0c;并有对外输出的成功案例&#xff0c;面向行业&#xff0c;赋能中小规模运营商…

mi6 android版本,小米6:我依旧是王,MIUI10.4.2稳定版与AndroidP同时到来

原标题&#xff1a;小米6&#xff1a;我依旧是王&#xff0c;MIUI10.4.2稳定版与AndroidP同时到来小米6作为小米数字系列最受欢迎的机型之一&#xff0c;从上市到下架热度一直未减&#xff0c;它也是众多米粉心目中小米数字系列最成功的机型没有之一。但是&#xff0c;再怎么讲…

如何利用 AHAS 保障 Web 服务稳如磐石?

简介&#xff1a;应用高可用服务 AHAS (Application High Availability Service) 是经阿里巴巴内部多年高可用体系沉淀下来的云产品&#xff0c;基于阿里开源流控降级组件 Sentinel&#xff0c;以流量与容错为切入点&#xff0c;从流量控制、不稳定调用隔离、熔断降级、热点流量…

KubeDL HostNetwork:加速分布式训练通信效率

简介&#xff1a;ubeDL 为分布式训练作业带来了 HostNetwork 网络模式&#xff0c;支持计算节点之间通过宿主机网络相互通信以提升网络性能&#xff0c;同时适应 RDMA/SCC 等新型高性能数据中心架构的网络环境&#xff0c;此外&#xff0c;KubeDL 针对 HostNetwork 模式带来的 …

阿里云容器服务差异化 SLO 混部技术实践

简介&#xff1a;阿里巴巴在“差异化 SLO 混合部署”上已经有了多年的实践经验&#xff0c;目前已达到业界领先水平。所谓“差异化 SLO”&#xff0c;就是将不同类型的工作负载混合运行在同一节点&#xff0c;充分利用工作负载对资源 SLO 需求特征的不同&#xff0c;提升资源整…

鸿蒙系统被烧毁,华为鸿蒙操作系统再次被质疑 国产是原罪

国产是原罪&#xff0c;国际驰名双标现象严重&#xff0c;为何对待国产的东西要格外刻薄&#xff1f;华为手机版鸿蒙系统正式发布&#xff0c;但却引来一片嘲讽&#xff0c;这些人简直是刷新三观。如果一个产品是相同的价格&#xff0c;国产的用料更足但是还不够成熟&#xff1…

云原生落地大爆发,企业和开发者如何把握先机?

简介&#xff1a;回顾 2021 年&#xff0c;云原生有哪些重大技术突破&#xff1f;云原生时代下开发模式、技术标准等不断变化&#xff0c;企业应该如何落地云原生&#xff1f;开发者应掌握哪些能力&#xff1f;本文将为你一一解说。 作者&#xff1a;伍杏玲 随着云计算产业走…

Gartner发布中国人工智能软件市场指南,激烈竞争下走向差异化

作者 | Gartner高级研究总监 方琦 供稿 | Gartner 人工智能&#xff08;AI&#xff09;软件是中国企业投资和关注的重点。中国的AI软件市场在持续快速增长&#xff0c;竞争非常激烈。AI软件企业使用一种或多种AI技术&#xff08;见图1&#xff09;&#xff0c;帮助企业解读事件…

华为Mate是鸿蒙系统,华为mate30概念新机:4500mAh+5G网络+“鸿蒙”系统 这才是华为...

对于现在的华为手机来说&#xff0c;很多消费者的态度不一样&#xff0c;有的觉得华为手机性价比不高&#xff0c;有的则觉得华为手机质量很好&#xff0c;配置也非常的高。而我觉得&#xff0c;华为手机最值得敬佩&#xff0c;敬佩的是华为不屈的精神&#xff0c;敬佩的是远见…

平安保险基于 SPI 机制的 RocketMQ 定制化应用

简介&#xff1a;本文讲讲述平安保险为何选择 RocketMQ&#xff0c;以及在确定使用消息中间件后&#xff0c;又是如何去选择哪款消息中间件的。 作者&#xff1a;孙园园&#xff5c;平安人寿资深开发 为什么选用 RocketMQ 首先跟大家聊聊我们为什么会选用 RocketMQ&#xff…

Redis 内存优化神技,小内存保存大数据

作者 | 码哥呀来源 | 码哥字节这次跟大家分享一些优化神技&#xff0c;当你面试或者工作中你遇到如下问题&#xff0c;那就使出今天学到的绝招&#xff0c;一招定乾坤&#xff01;❝如何用更少的内存保存更多的数据&#xff1f;我们应该从 Redis 是如何保存数据的原理展开&…

SchedulerX 如何帮助用户解决分布式任务调度难题?

简介&#xff1a;本文分别对任务调度平台的资源定义、可视化管控能力、分布式批处理能力进行了简述&#xff0c;并基于 SchedulerX 的能力结合实际业务场景提供了一些基础参考案例。希望通过上述内容能让大家方便地熟悉任务调度平台接入使用概况&#xff0c;对于现有用户也可结…

如何做“健康码”的性能压测

简介&#xff1a;随着无线设备的普及和 5G 的大力建设&#xff0c;越来越多的线上系统、小程序成为了人们生活中必不可少的工具。对于这些工具&#xff0c;都会面对一个问题&#xff1a;系统能承受多少用户同时访问&#xff0c;面对突发的流量洪峰&#xff0c;能否保证系统无故…

对话 MySQL 之父:一个优秀程序员可抵5个普通程序员

【CSDN 编者按】MySQL之父Monty有着四十多年的编程经验&#xff0c;从儿时的兴趣到长大后的深耕&#xff0c;他在编程领域不断钻研&#xff0c;最终成为编程大师。《新程序员004》带你走进Monty的程序人生&#xff0c;谈谈他在编程方面的最新感悟以及对未来的预测。作者 | 郭露…

服务网格 ASM 年终总结:最终用户如何使用服务网格?

简介&#xff1a;本文不打算回顾 Istio 或是阿里云服务网格 ASM 的变化或趋势&#xff0c;我们来聊一聊阿里云 ASM 服务网格&#xff0c;它的最终用户是如何使用服务网格的。 作者&#xff1a;叶剑宏 背景 阿里云服务网格 ASM 于 2020 年 2 月公测&#xff0c;近 2 年的时间…