Android中级——屏幕和绘图
屏幕和绘图
- 屏幕
- 系统屏幕密度
- 独立像素密度dp
- 单位转换
- XML绘图(需放在Drawable)
- Bitmap
- Shape
- Layer
- Selector
- 绘图技巧
- Canvas
- Layer
- PorterDuffXfermode
- Shader
- PathEffect
- SurfaceView
屏幕
- 屏幕大小:指屏幕对角线长度,单位为寸
- 分辨率:指屏幕宽高的像素点个数,如720x1280
- PPI:每英寸像素(Pixels Per Inch),指对角线的像素点数除以屏幕大小,又称屏幕密度DPI(Dots Per Inch)
系统屏幕密度
不同手机的大小和像素密度都不同,为统一,定义了几个标准的DPI值
独立像素密度dp
相同的像素,在不同密度的屏幕上显示,长度会不同,因为高密度的屏幕包含更多像素点
- 规定密度为mdpi(即密度值为160)时1px=1dp
- 故上图各分辨率的换算比例为3:4:6:8:12
单位转换
如下工具类提供了px、dp、sp的互相转换
public class DisplayUtil {// dp = 像素/密度public static int px2dip(Context context, float pxValue) {float scale = context.getResources().getDisplayMetrics().density;return (int) (pxValue / scale + 0.5f);}public static int dip2px(Context context, float dipValue) {float scale = context.getResources().getDisplayMetrics().density;return (int) (dipValue * scale + 0.5f);}// sp = 像素/缩放密度public static int px2sp(Context context, float pxValue) {float fontScale = context.getResources().getDisplayMetrics().scaledDensity;return (int) (pxValue / fontScale + 0.5f);}public static int sp2px(Context context, float spValue) {float fontScale = context.getResources().getDisplayMetrics().scaledDensity;return (int) (spValue * fontScale + 0.5f);}
}
或可以使用TypedValue.applyDimension()方法
public int dp2px(int dp) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,getResources().getDisplayMetrics());
}public int sp2px(int sp) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,sp,getResources().getDisplayMetrics());
}
XML绘图(需放在Drawable)
Bitmap
如下引用图片并转为Bitmap
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"android:src="@mipmap/ic_launcher" />
Shape
Shape可实现不同类型的形状,如下实现渐变阴影
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><gradientandroid:angle="45"android:endColor="#805FBBFF"android:startColor="#FF5DA2FF" /><paddingandroid:bottom="7dp"android:left="7dp"android:right="7dp"android:top="7dp" /><corners android:radius="8dp" />
</shape>
效果如图
Layer
Layer可实现类似PS中图层的概念
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@mipmap/ic_launcher" /><itemandroid:bottom="50dp"android:drawable="@mipmap/ic_launcher"android:left="50dp"android:right="50dp"android:top="50dp" />
</layer-list>
上面两个item分别为图片进行叠加,效果如图
Selector
Selector实现不同事件设置反馈,如下实现修改为圆角矩形,点击后切换颜色
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:state_pressed="true"><shape android:shape="rectangle"><solid android:color="#33444444" /><corners android:radius="5dp" /><padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" /></shape></item><item><shape android:shape="rectangle"><solid android:color="#FFFFFF" /><corners android:radius="5dp" /><padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" /></shape></item>
</selector>
绘图技巧
Canvas
下面为常用的方法
- save():将已绘制图像保存,在此之后的操作绘制在新图层
- restore():合并图层,将save()之后绘制的图像和save()之前的合并
- translate():坐标系平移
- ratate():坐标系旋转
如下绘制一个时钟,通过平移、旋转坐标系简化实现
public class Clock extends View {private int mWidth;private int mHeight;public Clock(Context context) {super(context);}public Clock(Context context, AttributeSet attrs) {super(context, attrs);}public Clock(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mWidth = getMeasuredWidth();mHeight = getMeasuredHeight();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 绘制外圆,以(mWidth / 2, mHeight / 2)为圆形,以mWidth / 2为半径Paint paintCircle = new Paint();paintCircle.setStyle(Paint.Style.STROKE);paintCircle.setAntiAlias(true);paintCircle.setStrokeWidth(5);canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, paintCircle);// 绘制刻度Paint paintDegree = new Paint();for (int i = 0; i < 24; i++) {if (i == 0 || i == 6 || i == 12 || i == 18) {paintDegree.setStrokeWidth(5);paintDegree.setTextSize(30);canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,mWidth / 2, mHeight / 2 - mWidth / 2 + 60,paintDegree);String degree = String.valueOf(i);canvas.drawText(degree,mWidth / 2 - paintDegree.measureText(degree) / 2,mHeight / 2 - mWidth / 2 + 90,paintDegree);} else {paintDegree.setStrokeWidth(3);paintDegree.setTextSize(15);canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,mWidth / 2, mHeight / 2 - mWidth / 2 + 30,paintDegree);String degree = String.valueOf(i);canvas.drawText(degree,mWidth / 2 - paintDegree.measureText(degree) / 2,mHeight / 2 - mWidth / 2 + 60,paintDegree);}// 将画布以圆心旋转15°,简化坐标运算canvas.rotate(15, mWidth / 2, mHeight / 2);}// 绘制指针Paint paintHour = new Paint();paintHour.setStrokeWidth(20);Paint paintMinute = new Paint();paintMinute.setStrokeWidth(10);canvas.save();canvas.translate(mWidth / 2, mHeight / 2); // 将坐标系平移到圆点,再画指针canvas.drawLine(0, 0, 100, 100, paintHour);canvas.drawLine(0, 0, 100, 200, paintMinute);canvas.restore();}
}
Layer
图层基于栈结构,入栈后操作都发生在该图层上,出栈后则把图像绘制到上层Canvas
- 入栈:saveLayer()、saveLayerAlpha()
- 出栈:restore()、restoreToCount()
public class MyView extends View {private static final String TAG = MyView.class.getSimpleName();private Paint mPaint;public MyView(Context context) {this(context, null);}public MyView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyView(Context context, AttributeSet attrs, int defStyleAttr) {this(context, attrs, defStyleAttr, 0);}public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);mPaint = new Paint();}@Overrideprotected void onDraw(Canvas canvas) {canvas.drawColor(Color.WHITE);mPaint.setColor(Color.BLUE);canvas.drawCircle(150, 150, 100, mPaint);canvas.saveLayerAlpha(0, 0, 400, 400, 127);mPaint.setColor(Color.RED);canvas.drawCircle(200, 200, 100, mPaint);canvas.restore();}
}
如下图,透明度为127的红色圆叠加在蓝色圆上方
PorterDuffXfermode
PorterDuffXfermod设置的是两个图层交集区域的显示方式,dst是先画的图形,而src是后画的图形,共有16种模式,如图
如下实现圆角图形,mOut为先画的图像,mBitmap为后画的图像,用SrcIn取交集
public class MyView extends View {private static final String TAG = MyView.class.getSimpleName();private Bitmap mBitmap;private Bitmap mOut;private Paint mPaint;public MyView(Context context) {this(context, null);}public MyView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyView(Context context, AttributeSet attrs, int defStyleAttr) {this(context, attrs, defStyleAttr, 0);}public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);mOut = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(mOut);mPaint = new Paint();mPaint.setAntiAlias(true);canvas.drawRoundRect(0, 0, mBitmap.getWidth(), mBitmap.getHeight(), 80, 80, mPaint);mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));canvas.drawBitmap(mBitmap, 0, 0, mPaint);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawBitmap(mOut, 0, 0, null);}
}
效果如图
如下代码设置透明的画笔,实时获取坐标调用drawPath()涂抹上面的图层,实现刮刮乐
public class XfermodeView extends View {private Bitmap mBgBitmap, mFgBitmap;private Paint mPaint;private Canvas mCanvas;private Path mPath;public XfermodeView(Context context) {this(context, null);}public XfermodeView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public XfermodeView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mPaint = new Paint();mPaint.setAlpha(0);mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeJoin(Paint.Join.ROUND);mPaint.setStrokeWidth(50);mPaint.setStrokeCap(Paint.Cap.ROUND);mPath = new Path();mBgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.b);mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(), mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);mCanvas = new Canvas(mFgBitmap);mCanvas.drawColor(Color.GRAY);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mPath.reset();mPath.moveTo(event.getX(), event.getY());break;case MotionEvent.ACTION_MOVE:mPath.lineTo(event.getX(), event.getY());break;}mCanvas.drawPath(mPath, mPaint);invalidate();return true;}@Overrideprotected void onDraw(Canvas canvas) {canvas.drawBitmap(mBgBitmap, 0, 0, null);canvas.drawBitmap(mFgBitmap, 0, 0, null);}
}
Shader
用于实现渐变、渲染效果,包括
- BitmapShader——位图Shader
- LinnerGradient——线性Shader
- RadialGradient——光束Shader
- SweepGradient——梯度Shader
- ComposeShader——混合Shader
上述渐变都有三种模式选择:
- CLAMP:拉伸,拉伸的是图片最后一个像素,不断重复
- REPEAT:重复,横向、纵向不断重复
- MIRROR:镜像,横向、纵向不断翻转重复
如下,将图片填充到BitmapShader,创建一支具有图像填充功能的Paint
public class MyView extends View {private static final String TAG = MyView.class.getSimpleName();private Bitmap mBitmap;private Paint mPaint;private BitmapShader mBitmapShader;public MyView(Context context) {this(context, null);}public MyView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyView(Context context, AttributeSet attrs, int defStyleAttr) {this(context, attrs, defStyleAttr, 0);}public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);mPaint = new Paint();mPaint.setShader(mBitmapShader);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawCircle(mBitmap.getWidth() / 2.0f, mBitmap.getHeight() / 2.0f, 50, mPaint);}
}
利用Paint在图片中心绘制圆形,效果如下
如下改为REPEAT,并扩大半径,可看到图片不断重复绘制
public class MyView extends View {private static final String TAG = MyView.class.getSimpleName();private Bitmap mBitmap;private Paint mPaint;private BitmapShader mBitmapShader;public MyView(Context context) {this(context, null);}public MyView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyView(Context context, AttributeSet attrs, int defStyleAttr) {this(context, attrs, defStyleAttr, 0);}public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);mPaint = new Paint();mPaint.setShader(mBitmapShader);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawCircle(mBitmap.getWidth() / 2.0f, mBitmap.getHeight() / 2.0f, 500, mPaint);}
}
如下利用PorterDuffXfermode和LinnerGradient实现倒影效果的图片
public class ReflectView extends View {private Bitmap mSrcBitmap, mRefBitmap;private Paint mPaint;private PorterDuffXfermode mXfermode;public ReflectView(Context context, AttributeSet attrs) {super(context, attrs);init();}private void init() {mSrcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.b);Matrix matrix = new Matrix();matrix.setScale(1F, -1F);//垂直翻转mRefBitmap = Bitmap.createBitmap(mSrcBitmap, 0, 0,mSrcBitmap.getWidth(), mSrcBitmap.getHeight(), matrix, true);mPaint = new Paint();mPaint.setShader(new LinearGradient(0, mSrcBitmap.getHeight(),0, mSrcBitmap.getHeight() * 2,0xDD000000, 0x10000000, Shader.TileMode.REPEAT));mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.BLACK);//原图canvas.drawBitmap(mSrcBitmap, 0, 0, null);//倒影图canvas.drawBitmap(mRefBitmap, 0, mSrcBitmap.getHeight(), null);mPaint.setXfermode(mXfermode);//绘制渐变效果层canvas.drawRect(0, mRefBitmap.getHeight(), mRefBitmap.getWidth(), mSrcBitmap.getHeight() * 2, mPaint);mPaint.setXfermode(null);}
}
先将图片翻转,再添加黑色透明度递减的渐变,DST_IN是为了避免上面的图像被渐变效果遮挡
PathEffect
PathEffect指用各种笔触效果来绘制一个路径
如上,分别为
- 无效果
- CornerPathEffect:线段拐角圆滑
- DiscretePathEffect:线段出现杂点
- DashPathEffect:绘制虚线,用一个数组来设置各个点之间的间隔,还可设置偏移量实现动态路径效果
- PathPathEffect:类似DashPathEffect,但还可设置点的图形,如上面的圆点虚线
- ConposePathEffect:组合效果
public class MyView extends View {private static final String TAG = MyView.class.getSimpleName();private Path mPath;private PathEffect[] mPathEffect;private Paint mPaint;public MyView(Context context) {this(context, null);}public MyView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyView(Context context, AttributeSet attrs, int defStyleAttr) {this(context, attrs, defStyleAttr, 0);}public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);mPaint = new Paint();mPaint.setStyle(Paint.Style.STROKE);mPath = new Path();mPath.moveTo(0, 0);for (int i = 0; i <= 30; i++) {mPath.lineTo(i * 35, (float) (Math.random() * 100));}mPathEffect = new PathEffect[6];mPathEffect[0] = null;mPathEffect[1] = new CornerPathEffect(30);mPathEffect[2] = new DiscretePathEffect(3.0F, 5.0F);mPathEffect[3] = new DashPathEffect(new float[]{20, 10, 5, 10}, 0);Path path = new Path();path.addRect(0, 0, 8, 8, Path.Direction.CCW);mPathEffect[4] = new PathDashPathEffect(path, 12, 0, PathDashPathEffect.Style.ROTATE);mPathEffect[5] = new ComposePathEffect(mPathEffect[3], mPathEffect[1]);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);for (PathEffect pathEffect : mPathEffect) {mPaint.setPathEffect(pathEffect);canvas.drawPath(mPath, mPaint);canvas.translate(0, 200);}}
}
SurfaceView
Android通过VSYNC信号刷新View进行屏幕的重绘,时间间隔为16ms,若在需要频繁刷新的界面上执行太多的操作逻辑,则容易阻塞主线程,造成画面卡顿
当需要频繁刷新或刷新时数据处理量比较大时,可使用SurfaceView
- View用于主动刷新,SurfaceView用于被动刷新
- View在主线程刷新,SurfaceView在子线程刷新
- View绘图未使用双缓冲机制,SurfaceView则使用双缓冲机制
SurfaceView的模板代码如下,主要原理是初始化时自行创建子线程并调用draw()方法绘制
public class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback, Runnable {//内部Holder,用于获取Canvas和提交绘制private SurfaceHolder mHolder;//用于控制线程的标志位private boolean mIsDrawing;//用于绘图的Canvasprivate Canvas mCanvas;public SurfaceViewTemplate(Context context) {this(context, null);}public SurfaceViewTemplate(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SurfaceViewTemplate(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mHolder = getHolder();mHolder.addCallback(this); //将自身作为回调setFocusableInTouchMode(true);setFocusable(true);this.setKeepScreenOn(true);}//创建时开启线程,调用draw()@Overridepublic void surfaceCreated(SurfaceHolder holder) {mIsDrawing = true;new Thread(this).start();}//改变时回调@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}//结束时回调@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {mIsDrawing = false;}@Overridepublic void run() {while (mIsDrawing) {draw();}}private void draw() {try {mCanvas = mHolder.lockCanvas();//获取Canvas开始绘制,获取的并非新的Canvas,而是上次的} catch (Exception e) {e.printStackTrace();} finally {if (mHolder != null) {//绘制完后需提交mHolder.unlockCanvasAndPost(mCanvas);}}}
}
如下代码利用SurfaceView实现正弦函数的动态绘制
public class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback, Runnable {private SurfaceHolder mHolder;private boolean mIsDrawing;private Canvas mCanvas;private int x;private int y;private Path mPath;private Paint mPaint;public SurfaceViewTemplate(Context context) {this(context, null);}public SurfaceViewTemplate(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SurfaceViewTemplate(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mPath = new Path();mPaint = new Paint();mPaint.setStyle(Paint.Style.STROKE);mHolder = getHolder();mHolder.addCallback(this);setFocusableInTouchMode(true);setFocusable(true);this.setKeepScreenOn(true);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {mIsDrawing = true;new Thread(this).start();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {mIsDrawing = false;}@Overridepublic void run() {while (mIsDrawing) {draw();x += 1;y = (int) (100 * Math.sin(x * 2 * Math.PI / 180) + 400);mPath.lineTo(x, y);}}private void draw() {try {mCanvas = mHolder.lockCanvas();mCanvas.drawColor(Color.WHITE); //设置背景mCanvas.drawPath(mPath, mPaint);} catch (Exception e) {e.printStackTrace();} finally {if (mHolder != null) {mHolder.unlockCanvasAndPost(mCanvas);}}}
}
效果如图
如下代码利用SurfaceView实现绘图板,根据手指移动绘制路径,在draw()中调用sleep()避免过度频繁绘制
相关文章:

Android中级——屏幕和绘图
屏幕和绘图屏幕系统屏幕密度独立像素密度dp单位转换XML绘图(需放在Drawable)BitmapShapeLayerSelector绘图技巧CanvasLayerPorterDuffXfermodeShaderPathEffectSurfaceView屏幕 屏幕大小:指屏幕对角线长度,单位为寸分辨率&#x…...

Linux - 第6节 - 动态库和静态库
1.静态库与动态库概念 静态库(.a):程序在编译链接的时候把库的代码拷贝到可执行文件中。程序运行的时候将不再需要静态库。动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用…...

【Java学习笔记】12.Character 类及String 类
前言 本章介绍Java的Character 类和String 类。 Java Character 类 Character 类用于对单个字符进行操作。 Character 类在对象中包装一个基本类型 char 的值 实例 char ch a;// Unicode 字符表示形式 char uniChar \u039A; // 字符数组 char[] charArray { a, b, c, d…...

【C++修炼之路】26.C++11(语法糖)
每一个不曾起舞的日子都是对生命的辜负 C11C11(语法糖)本节目标一.C11简介二.统一的列表初始化2.1 {}初始化2.2 std::initializer_list三.声明3.1 auto3.2 decltype3.3 nullptr四.总结C11(语法糖) 本节目标 C11简介 列表初始化 变量类型推导 一.C11简介 在2003年C标准委员…...

KD610精密油介损体积电阻率测试仪
一、概述 KD610精密油介损体积电阻率测试仪是用于绝缘油等液体绝缘介质的介质损耗角及体积电阻率的高精密仪器。 二、产品特点 1.仪器内部采用数字技术,具备多种模式测式。 2.智能自动化测量。 3.配备了大屏幕(2401…...

快速了解原码、反码、补码和位运算
我们知道计算机使用的是二进制,我们⽤⼀个字节,也就是8个bit 来表示⼆进制数。 原码 十进制 原码20000 0010-21000 0010 原码其实是最容易理解的,只不过需要利⽤⼆进制中的第⼀位来表示符号位,0表示正数,1表示…...

算法的复杂度介绍
算法的复杂度介绍 算法(Algorithm)是指用来操作数据、解决程序问题的一组方法。对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有很大的区别。 为什么要进行算法分析&…...

教你如何搭建店铺—收支管理系统,demo可分享
1、简介1.1、案例简介本文将介绍,如何搭建店铺-收支管理。1.2、应用场景以店铺收支管理为核心,维度数据分析,智能指导门店经营,账目清晰一目了然,店铺经营更高效。2、设置方法2.1、表单搭建1)新建表单【客户…...

java性能分析-堆内存最佳实践-堆分析
堆内存最佳实践 优化垃圾回收器标志参数很重要但是采用更好的编程实践获得更大的性能提升 1.谨慎的创建对象并尽快的丢弃,是更好的内存是提高gc更好的方法 2.频繁创建某种类型的对象会导致整体的性能变差 对象复用设计 线程局部变量 每个线程中创建一个局部变量…...

3月8号作业
题目:题目一:vmlinux可执行文件如何产生题目二:整理内核编译流程:uImage,zImage,Image,vmlinux之间的关系答案一:在内核源码目录下vi Makefile,搜索vmlinux目标,vmlinux: scripts/li…...

Flink相关介绍
简介 Flink的定位是:Apache Flink是一个框架和分布式处理引擎,如图所示,用于对无界和有界数据流进行有状态计算。Flink被设计在所有常见的集群环境运行,以内存执行速度和任意规模来执行计算。 Flink 框架处理流程应用场景 1、电…...

Java 8 排序
今天分享 Java 8 进行排序的 10 个姿势,其实就是把 Java 8 中的 Lambda、Stream、方法引用等知识点串起来 传统排序 现在有一个 List 集合: public static List<User> LIST new ArrayList() {{add(new User("Lisa", 23));add(new Us…...

Blazor_WASM之4:路由
Blazor_WASM之4:路由 路由模板 通过 Router组件可在 Blazor 应用中路由到 Razor 组件。 Router 组件在 Blazor 应用的 App 组件中使用。App组件模板如下 <Router AppAssembly"typeof(Program).Assembly"><Found Context"routeData"…...

对Vue响应式的理解
1. 啥是响应式? (1).所谓的数据响应式就是能够使数据变化可以被检测到并且对这种变化做出响应式的机制 2. 为什么vue需要响应式? (1).MVVM框架中要解决的核心问题数据驱动视图,数据的改变引起视图的更新ÿ…...

磁盘阵列Raid探讨
最近公司买服务器,顺便了解一下服务器配置方面的问题 以下讨论的都是入门级服务器配置,全部是主观意见,没有任何科学依据,欢迎大家讨论 Raid0,Raid1,Raid10,Raid5,Raid6(Raid5热备)…...

基于MyBatis依次、批量、分页增删改查
我们知道处理数据有三种思路:依次、批量、分页,对应方法如下 依次处理:在 Java 里面写 for 循环,依次使用 SQL 语句,频繁连接断开数据库批量处理:在 MyBatis 里面用 <foreach> 拼接成一条长 SQL 语句…...

Tomcat源码分析-Session源码解析
tomcat session 设计分析 tomcat session 组件图如下所示,其中 Context 对应一个 webapp 应用,每个 webapp 有多个 HttpSessionListener, 并且每个应用的 session 是独立管理的,而 session 的创建、销毁由 Manager 组件完成&…...

常见数据模型
目录 1.1两类数据模型 1.2概念模型 1.3数据模型的组成要素 1.4常见数据模型 层次模型 网状模型 关系模型 数据模型是对现实世界数据特征的抽象,也就是说数据模型是用来描述数据、组织数据和对数据进行操作的。数据模型是数据库系统的核心和基础。 1.1两类数…...

Lesson 8.3 ID3、C4.5 决策树的建模流程 Lesson 8.4 CART 回归树的建模流程与 sklearn 参数详解
文章目录一、ID3 决策树的基本建模流程二、C4.5 决策树的基本建模流程1. 信息值(information value)2. C4.5 的连续变量处理方法三、CART 回归树的基本建模流程1. 数据准备2. 生成备选规则3. 挑选规则4. 进行多轮迭代5. 回归树的预测过程四、CART 回归树…...

阿里云手机短信登录
阿里云短信服务介绍阿里云短信服务(Short Message Service)是广大企业客户快速触达手机用户所优选使用的通信能力。调用API或用群发助手,即可发送验证码、通知类和营销类短信;国内验证短信秒级触达,到达率最高可达99%&…...

Android Camera SDK NDK NDK_vendor介绍
Android Camera JNI NDK NDK_vendor介绍前言主要有哪几种interface?Android SDKCamera API 1Camera API 2小结Android NDKNDK InterfaceNDK Vendor Interface小结Camera VTS Testcase总结Reference前言 本篇博客是想介绍Android camera从application layer到camera…...

SQL基础语句小结
🍎道阻且长,行则将至。🍓 目录 一、SQL概述 1.简介 2.格式语法 3.SQL分类 二、DDL操作数据库 1.创建数据库 2.查询与使用 3.删除数据库 三、DDL:操作表 (1)数据类型 (2)创建表 (3)查询当前数据库的表 (4)删除表 (5)修改表 四、DML…...

管理类书籍推荐
管理类书籍对于每一位想要获得管理能力提升或者实现职业生涯更上一层楼的企业管理者或领导者而言,都是不可或缺的一项重要学习工具。作为管理工作从事者的职场必需品,一本出色的管理类书籍可以为我们提供大量宝贵的经验与专业建议,从而让管理…...

win10 mingw 调用python
ubuntu调用pythonhttps://blog.csdn.net/qq_39942341/article/details/129333969 我这里mingw是用msys2的 opencv也是msys2装的 安装msys2和opencv可以参考这个https://blog.csdn.net/qq_39942341/article/details/129380197?spm1001.2014.3001.5502 环境变量里加入python路…...

教你使用三种方式写一个最基本的spark程序
当需要处理大规模数据并且需要进行复杂的数据处理时,通常会使用Hadoop生态系统中的Hive和Spark来完成任务。在下面的例子中,我将说明如何使用Spark编写一个程序来处理Hive中的数据,以满足某个特定需求。假设我们有一个Hive表,其中…...

软件设计师错题集
软件设计师错题集一、计算机组成与体系结构1.1 浮点数1.2 Flynn分类法1.3 指令流水线1.4 层次化存储体系1.4.1 程序的局限性1.5 Cache1.6 输入输出技术1.7 总线系统1.8 CRC循环冗余校验码二、数据结构与算法基础2.1 队列与栈2.2 树与二叉树的特殊性2.3 最优二叉树(哈…...

【华为机试真题详解 Python实现】静态扫描最优成本【2023 Q1 | 100分】
文章目录前言题目描述输入描述输出描述示例 1输入:输出:示例 2输入:输出:题目解析参考代码前言 《华为机试真题详解》专栏含牛客网华为专栏、华为面经试题、华为OD机试真题。 如果您在准备华为的面试,期间有想了解的…...

算法刷题总结 (四) 动态规划
算法总结4 动态规划一、动态规划1.1、基础问题11.1.1、509. 斐波那契数列1.1.2、70. 爬楼梯1.1.3、746. 使用最小花费爬楼梯1.2、基础问题21.2.1、62. 不同路径1.2.2、63. 不同路径Ⅱ1.2.3、343. 整数拆分1.2.4、96. 不同的二叉搜索树1.3、背包问题1.3.1、01背包1.3.1.1、单次选…...

Grafana 转换数据的工具介绍
转换数据 Grafana 可以在数据显示到面板前对数据进行处理 1、点击Transform选项卡 2、选择要使用的转换类型,不同的转换类型配置不同 3、要新增转换类型,点击Add transformation 4、使用右上角调式按钮可以调式转换 支持的转换类型: Add f…...

Linux 学习笔记
一、 概述 1. 操作系统 ① 计算机由硬件和软件组成 ② 操作系统属于软件范畴,主要作用是协助用户调度硬件工作,充当用户和计算机硬件之间的桥梁 ③ 常见的操作系统 🤠 PC端:Windows、Linux、MacOS🤠 移动端&#…...