Java方面
Java基础部分
抽象类与接口的区别别
- 抽象类,采用 修饰符 + abstract class来定义,和普通类一样,可以定义常量、方法、抽象方法、一般方法和构造方法,是类共性的提取
- 接口, 采用 修饰符 + interface来定义,可以定义常量(默认就是public static的),可以声明方法(java 8以后方法可以有默认实现,不过需要加上default关键字),是一种规范,实现接口的类必须提供接口中定义方法的实现。
- Java是单继承,多实现的
做一个有追求的青年
Android Notification适配
背景
最近项目App 在Android 8.0上默认不显示通知,查了一下原因,是因为通知设置的级别太低。同时由于Android 8.0以上会列出相应的渠道名称,发现我们的渠道名称居然设置成了发起通知对应的Service的名称,借此契机,就来写一下通知相关的东西,主要从以下几个方面着手:
在Java语言中,要重载一个方法,除了要与原方法具有相同的简单名称之外,还要求必须拥有一个与原方法不同的特征签名;
特征签名就是一个方法中各个参数在常量池中的字段符号引用的集合,也就是因为返回值不会包含在特征签名之中,因此Java语言里面是无法仅仅依靠返回值的不同来对一个已有方法进行重载。
但在Class文件格式之中,特征签名的范围更大一些,只要描述符不是完全一致的两个方法也可以共存。
也就是说,如果两个方法有相同的名称和特征签名,但返回值不同,那么也是可以合法存于同一个Class文件中的。
以下两个方法被认为是方法的重载
1 | public void setNameAndId(String name, long id) { |
说明:传入的参数会自动被转换为Long(自动装箱),但通过Method.getParameterTypes()
获取到的参数类型却是 方法declare时的类型,所以如果直接通过传入参数的类型跟Method.getParameterTypes()
获取到的类型比较,是获取不到相应的Method的
Class.getDeclaredMethods()
获取的是类自己定义的所有方法(不包含其父类或接口的定义的方法)或类重写或实现的父类或接口的方法。
最近要做一个看图找字功能的游戏化场景,决定采用原生实现,具体就是利用放大镜找到图片中的汉字,识别当前区域和目标区域,在松手后给出判断。要实现这个demo需要解决如下问题:
ShaderDrawable
和Path
;基本原理都是将要放大区域的目标像素按一定的比例通过矩阵变化来进行放大处理。
ShapeDrawable
来确定放大的区域,然后采用BitmapShader
来实现区域的放大。(BitmapShader
,Shader的一种,作用是将Bitmap以纹理的方式绘制出来)Path
,利用clipPath获取要放大的区域,然后在放大的区域中绘制放大后的像素;Magnifier
组件来实现(API 28以上,即Android 9系统以上系统才有系统级支持,API 29以上支持Builder配置);这种方式主要利用ShapeDrawable来确定位置,利用BitmapShader来处理放大效果,具体实现方式也分一下几个步骤:
获取源bitmap,即获取要放大处理的bitmap;
设置放大区域,并根据放大区域来创建相应的ShapeDrawable
(ShapeDrawable
支持不同的形状,具体可以参考ShapeDrawable
的API);
根据放大区域,从源bitmap裁剪出对应范围的cutBitmap,然后对cutBitmap进行放大处理得到scaledBitmap(调用Bitmap.createScaledBitmap
方法);
这时候的scaledBitmap就有放大效果了,只需要将scaledBitmap设置到BitmapShader
中去即可(BitmapShader
支持纹理的绘制方式,具体参见TileMode
;
将得到的BitmapShader
设置到ShapeDrawable
的Paint
中;
绘制出ShapeDrawable
;
这种方式主要采用Path来确定位置,然后利用Matrix来实现放大、平移操作,关于Matrix相关说明,见底部知识储备Matrix相关。
具体实现步骤:
根据需要的放大配置(如放大倍数factor,放大位置,确定Path)
通过clipPath裁剪出要放大的区域;
根据放大倍数,通过Matrix的setScale方法来设置放大系数
通过Matrix的postTranslate来修正放大中心
1 | float dx = -curX*(factor-1); |
获取放大后的bitmap
调用canvas 包含matrix的drawBitmap方法,进行bitmap绘制;
根据文档的说法,这个放大效果可以应用到任何View上。这个组件有几个关键的内部类
Magnifier.Builder
,放大镜效果的配置参数都在这个Builder对象里;
InternalPopupWindow
,内部实现的一个PopupWindow
SurfaceInfo
,放大镜效果用到的Surface和与Surface相关的信息;
Magnifier类在被加载的时候就启动了一个 sPixelCopyHandlerThread 的线程,即像素拷贝线程,由此可见Magnifier的实现方式应该和像素拷贝有关,后面会分析到
下面结合Magnifier的使用,来对Magnifier的源码进行分析。
API 28 之前,通过 Magnifier的构造函数来创建:
1 | public Magnifier(@NonNull View view) { |
API 29 之前,可以通过 Magnifier.Builder来构建:
1 | Magnifier magnifier = new Magnifier.Builder(targetView) |
调用Magnifier的show方法可以显示出放大镜,有两个show方法,分别是
public void show(float sourceCenterX, float sourceCenterY)
public void show(float sourceCenterX, float sourceCenterY, float magnifierCenterX, float magnifierCenterY)
参数的意义分别表示要放大内容的中心x坐标、要放大内容的中心y坐标,放大镜的中心x坐标、放大镜的中心y坐标。
下面分析一下show方法
1 | public void show(@FloatRange(from = 0) float sourceCenterX, |
在performPixelCopy
像素拷贝成功后,会调用mWindow.updateContent()
,这个方法内部会进行时图内容的更新
获取bitmap的方式这里不赘述,根据不同的业务场景,有不同的获取方式:
BitmapFactory.decodeXXX方法,支持从文件、drawable资源、byte[]、InputStream中获取Bitmap
Fresco图片加载框架获取最终展示的bitmap方式:
1 | new BaseControllerListener<Object>() { |
View
的setDrawingCacheEnabled(boolean enabled)
方法
Matrix相关知识详解 android matrix 最全方法详解
Shader 是一个基类对象,在绘制时会返回一个水平跨越的颜色对象,主要功能是在绘制时通过setShader方法设置着色器的子类对象之后,任何对象(除了位图之外)都可从着色器中得到它的想要的颜色。系统提供的子类有:
BitmapShader,位图的图像渲染器,上述就利用了Bitmap Shader来实现了放大镜效果;
ComposeShader ,组合渲染器;
LinearGradient,线性渲染器;
SweepGradient,梯度渲染器(即扫描渲染),可以使用该渲染器实现,如:微信等雷达扫描效果、手机卫士垃圾扫描。
RadialGradient,环形渲染器,一般的水波纹效果,充电水波纹扩散效果、调色板都可以使用该渲染器实现。
可转债定义
可转换公司债券(简称可转换债券)是指发行人依照法定程序发行,在一定期限内依据约定的条件可以转换为股份的公司债券。这种债券兼具债权和认股权双重属性。
可转债每个交易日9:15开始交易。
债券现货采用竞价交易方式,交易时间为:
每个交易日9:15-9:25为开盘集合竞价时间;9:30-11:30,13:00-14:57为连续竞价时间;14:57-15:00为收盘集合竞价时间。
内盘与外盘
主要罗列开源库的文章,分析的进度