Android自定义注解(一)

简介: 为什么要写这个,因为前段时间看了一下AOP相关的一些内容,然后也是太久没写注解,看得有点那啥不顺畅,所以想对注解做个总结。一.JAVA自带的注解(1)Override 覆盖(2)Deprecated 标记过期方法(3)SuppressWarnings 屏蔽警告二.

为什么要写这个,因为前段时间看了一下AOP相关的一些内容,然后也是太久没写注解,看得有点那啥不顺畅,所以想对注解做个总结。

一.JAVA自带的注解

(1)Override 覆盖
(2)Deprecated 标记过期方法
(3)SuppressWarnings 屏蔽警告

二.自定义注解

1.定义

我这里写个demo自定义一个注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface BindView {
    int value() default -1;
}

可以看出注解用@interface来标志。

2.元注解

可以看出在上边的定义中,上面还有两个注解,这些被称为元注解,什么是元注解,简单来说就是描述注解的注解
还有什么元数据的,元什么什么的,这个元其实不太好解释,我记得之前看过一个元数据的描述,英文是 data about data,这个元有这个about的那种感觉

元注解有4种
(1)@Retention 用来描述周期,Retention 有“保持时间”的意思,这个属性可以选三个值
SOURCE表示只在源码中有用,编译就没用了。
CLASS表示在编译中可用,运行就没用了。
RUNTIME表示运行时可用。
这三种的区别解释起来很麻烦,总之一搬我们都是使用RUNTIME

(2)@Target 用来描述作用域,Target有目标的意思,你这个注解要给哪个目标修饰,这个属性可以选以下的值
CONSTRUCTOR用于描述构造器
FIELD用于描述域
LOCAL_VARIABLE用于描述局部变量
METHOD用于描述方法
PACKAGE用于描述包
PARAMETER用于描述参数
这个就是说,你允许把注解写在什么地方。这个属性是可以多选的,比如@Target({ElementType.FIELD, ElementType.METHOD})

(3)@Inherited 描述是否可以为继承,默认是false

(4)@Documented 描述是否会保存到 Javadoc 文档中

一般我们只会用到前面两个,所以后面两个我就不解释了。

3.注解的值

可以给注解设置值,比如说我上面的代码,就在注解里写了个

int value() default -1;

表示在使用注解时需要传一个整形的值

@BindView(R.id.tv)
TextView textView;

我这传了个R.id.tv就是一个整形的值。只有一个值的时候,必须以** value()**来命名,然后调用时就直接传就行。我还是分情况来说吧。

(1)不需要传值的情况

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface BindView {

}

调用

@BindView
TextView textView;

(2)传一个值的情况
就是我上面写的代码

(3)传多个值的情况

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface BindView {
    int age;
    String name;
}

调用

@BindView(age = 18, name = "JackMa")
TextView textView;

最后,这个default 表示设置默认值的意思。

三.调用注解

上面我们创建出了注解并定义好,然后我们需要调用这个注解,那怎么调用呢,一般我们调用一个类或接口都是new 出来,但是这东西怎么看都觉得new不出来吧,所以我们需要用反射来获取到注解的对象,然后进行调用

我不想去讲反射的内容,不然就没完了。就说个思路,需要用到哪个方法可以去查api。
注解在Java中就是Annotation懂吧,所以在反射中和Annotation相关的方法都是和注解相关的方法。

比如说获取注解,我就可以调用.getAnnotation(BindView.class)
再比如说我判断注解存在不,可以调用isAnnotationPresent()
总之你只要记住注解是Annotation,之后你不管是在反射中还是在哪里找和注解相关的方法,都先往Annotation这个名词相关的地方找准没错。

如果你不懂反射这里说再多也没有。

四.案例

其实说了这么多,到底哪里需要使用到注解呢,如果不使用到,讲它有啥用,我个人是目前接触到AOP涉及注解比较频繁,其它时候,比如说ButterKnife,Dagger,Retrofit等等这些主流的框架都会用到注解,包括java后台,我接触过spring会涉及到IOC啊AOP啊这些思想用java来实现也是用到注解比较多,所以可以来写个小demo试试。

不如就仿照ButterKnife吧,我之前没看过ButterKnife的源码啊,我就按照我学会的注解的知识和ButterKnife的调用方法来仿写个ButterKnife

1.首先定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface BindView {
    int value() default -1;
}

定义注解,要求传个资源进来,默认是-1

2.按照ButterKnife的调用的样子来写调用的地方
public class MainActivity extends AppCompatActivity {

    @BindView(R.id.tv)
    TextView textView;
    @BindView(R.id.btn)
    Button btn;

    String yyy = "aasdasdas";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        textView.setText("wwwwwwwwwwwwww");
        btn.setText("btn");
    }
}

发现ButterKnife调用的地方使用这 ButterKnife.bind(this); 那我就推测findViewById就在这个ButterKnife类的bind方法中进行。

3.定义ButterKnife
public class ButterKnife {

    public static void bind(Activity activity){
        Class<?> cls = activity.getClass();
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            BindView bindView = field.getAnnotation(BindView.class);
            if (bindView != null) {
                int ids = bindView.value();
                try {
                    field.set(activity, activity.findViewById(ids));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

我这里就用了反射来操作,调用bind方法后,先用cls.getDeclaredFields();获取所有的全局变量,然后再对每个变量用field.getAnnotation(BindView.class);来获取这个变量上面的注解,如果存在的话 int ids = bindView.value(); 来获取我们传入的资源,最后调用findViewById

field.set(activity, activity.findViewById(ids));

很简单吧,三个类这样就能实现了ButterKnife的效果


img_5ac01d4d583815ddca92d8de2749129a.png
image.png

注意判空一定要写,即使你全部的变量都用了注解,但是如果你DeBug看看,你会发现,变量中不仅仅只有你定义的,还存在其他的。

其实上面都是瞎写的,ButterKnife的原理根本不是这样,虽然我没看过源码,但我听别人说过ButterKnife的实现并不是这样的,我这的demo只是仿照了这个功能,具体ButterKnife的原理以后如果有时间我会单独写。

通过上面的讲解就能简单的实现注解,我也顺便复习加总结了一遍。

目录
相关文章
|
9月前
|
Android开发 UED 计算机视觉
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
本文介绍了一款受游戏“金铲铲之战”启发的Android自定义View——线条等待动画的实现过程。通过将布局分为10份,利用`onSizeChanged`测量最小长度,并借助画笔绘制动态线条,实现渐变伸缩效果。动画逻辑通过四个变量控制线条的增长与回退,最终形成流畅的等待动画。代码中详细展示了画笔初始化、线条绘制及动画更新的核心步骤,并提供完整源码供参考。此动画适用于加载场景,提升用户体验。
623 5
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
|
9月前
|
Android开发
Android自定义view之利用PathEffect实现动态效果
本文介绍如何在Android自定义View中利用`PathEffect`实现动态效果。通过改变偏移量,结合`PathEffect`的子类(如`CornerPathEffect`、`DashPathEffect`、`PathDashPathEffect`等)实现路径绘制的动态变化。文章详细解析了各子类的功能与参数,并通过案例代码展示了如何使用`ComposePathEffect`组合效果,以及通过修改偏移量实现动画。最终效果为一个菱形图案沿路径运动,源码附于文末供参考。
186 0
|
9月前
|
Android开发 开发者
Android自定义view之利用drawArc方法实现动态效果
本文介绍了如何通过Android自定义View实现动态效果,重点使用`drawArc`方法完成圆弧动画。首先通过`onSizeChanged`进行测量,初始化画笔属性,设置圆弧相关参数。核心思路是不断改变圆弧扫过角度`sweepAngle`,并调用`invalidate()`刷新View以实现动态旋转效果。最后附上完整代码与效果图,帮助开发者快速理解并实践这一动画实现方式。
232 0
|
9月前
|
Android开发 数据安全/隐私保护 开发者
Android自定义view之模仿登录界面文本输入框(华为云APP)
本文介绍了一款自定义输入框的实现,包含静态效果、hint值浮动动画及功能扩展。通过组合多个控件完成界面布局,使用TranslateAnimation与AlphaAnimation实现hint文字上下浮动效果,支持密码加密解密显示、去除键盘回车空格输入、光标定位等功能。代码基于Android平台,提供完整源码与attrs配置,方便复用与定制。希望对开发者有所帮助。
185 0
|
9月前
|
XML Java Android开发
Android自定义view之网易云推荐歌单界面
本文详细介绍了如何通过自定义View实现网易云音乐推荐歌单界面的效果。首先,作者自定义了一个圆角图片控件`MellowImageView`,用于绘制圆角矩形图片。接着,通过将布局放入`HorizontalScrollView`中,实现了左右滑动功能,并使用`ViewFlipper`添加图片切换动画效果。文章提供了完整的代码示例,包括XML布局、动画文件和Java代码,最终展示了实现效果。此教程适合想了解自定义View和动画效果的开发者。
428 65
Android自定义view之网易云推荐歌单界面
|
9月前
|
XML 前端开发 Android开发
一篇文章带你走近Android自定义view
这是一篇关于Android自定义View的全面教程,涵盖从基础到进阶的知识点。文章首先讲解了自定义View的必要性及简单实现(如通过三个构造函数解决焦点问题),接着深入探讨Canvas绘图、自定义属性设置、动画实现等内容。还提供了具体案例,如跑马灯、折线图、太极图等。此外,文章详细解析了View绘制流程(measure、layout、draw)和事件分发机制。最后延伸至SurfaceView、GLSurfaceView、SVG动画等高级主题,并附带GitHub案例供实践。适合希望深入理解Android自定义View的开发者学习参考。
789 84
|
9月前
|
Android开发 开发者
Android自定义View之不得不知道的文件attrs.xml(自定义属性)
本文详细介绍了如何通过自定义 `attrs.xml` 文件实现 Android 自定义 View 的属性配置。以一个包含 TextView 和 ImageView 的 DemoView 为例,讲解了如何使用自定义属性动态改变文字内容和控制图片显示隐藏。同时,通过设置布尔值和点击事件,实现了图片状态的切换功能。代码中展示了如何在构造函数中解析自定义属性,并通过方法 `setSetting0n` 和 `setbackeguang` 实现功能逻辑的优化与封装。此示例帮助开发者更好地理解自定义 View 的开发流程与 attrs.xml 的实际应用。
274 2
Android自定义View之不得不知道的文件attrs.xml(自定义属性)
|
缓存 前端开发 Android开发
安卓开发中的自定义视图:从零到英雄
【10月更文挑战第42天】 在安卓的世界里,自定义视图是一块画布,让开发者能够绘制出独一无二的界面体验。本文将带你走进自定义视图的大门,通过深入浅出的方式,让你从零基础到能够独立设计并实现复杂的自定义组件。我们将探索自定义视图的核心概念、实现步骤,以及如何优化你的视图以提高性能和兼容性。准备好了吗?让我们开始这段创造性的旅程吧!
226 1
|
Android开发 开发者
安卓应用开发中的自定义视图
【9月更文挑战第37天】在安卓开发的海洋中,自定义视图犹如一座座小岛,等待着勇敢的探索者去发现其独特之处。本文将带领你踏上这段旅程,从浅滩走向深海,逐步揭开自定义视图的神秘面纱。
133 3
|
9月前
|
前端开发 Android开发 UED
讲讲Android为自定义view提供的SurfaceView
本文详细介绍了Android中自定义View时使用SurfaceView的必要性和实现方式。首先分析了在复杂绘制逻辑和高频界面更新场景下,传统View可能引发卡顿的问题,进而引出SurfaceView作为解决方案。文章通过Android官方Demo展示了SurfaceView的基本用法,包括实现`SurfaceHolder.Callback2`接口、与Activity生命周期绑定、子线程中使用`lockCanvas()`和`unlockCanvasAndPost()`方法完成绘图操作。
283 3

热门文章

最新文章