1. 定义自己的annotation注解。
定义findViewbyId这个功能的注解
package com.xxx.app.inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
int value() default (int) -1;
}
定义setOnclickListener的注解
package com.xxx.app.inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectClick {
int[] value();
}
2. 定义自己的注解处理类:
package com.xxx.app.inject;
import android.app.Activity;
import android.view.View;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Injector {
public static void injectView(Object obj, Object root) {
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Annotation[] annotations = field.getAnnotations();
if (annotations != null) {
for (Annotation annotation : annotations) {
if (annotation instanceof InjectView) {
InjectView injectView = (InjectView) annotation;
int value = injectView.value();
if (value != -1) {
try {
View view = getViewByRoot(root, value);
field.set(obj, view);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
break;
}
}
}
}
}
public static void injectClick(Object obj, Object root) {
Method[] methods = obj.getClass().getDeclaredMethods();
for (Method method : methods) {
Annotation[] annotations = method.getAnnotations();
if (annotations != null) {
for (Annotation annotation : annotations) {
if (annotation instanceof InjectClick) {
InjectClick inject = (InjectClick) annotation;
int[] value = inject.value();
if (value != null && value.length > 0) {
View.OnClickListener listener = (View.OnClickListener) obj;
try {
for (int res : value) {
View view = getViewByRoot(root, res);
if (view == null) {
throw new NullPointerException();
}
view.setOnClickListener(listener);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
} else if (annotation instanceof InjectLongClick) {
InjectLongClick inject = (InjectLongClick) annotation;
int[] value = inject.value();
if (value != null && value.length > 0) {
View.OnLongClickListener listener = (View.OnLongClickListener) obj;
try {
for (int res : value) {
View view = getViewByRoot(root, res);
if (view == null) {
throw new NullPointerException();
}
view.setOnLongClickListener(listener);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
}
}
}
}
public static View getViewByRoot(Object root, int res) {
View view = null;
if (root instanceof Activity) {
view = ((Activity)root).findViewById(res);
}
return view;
}
}
3. Activity中使用注解:
@InjectView(R.id.action_back)
private ImageView actionBack;
@InjectView(R.id.site_top_bg)
private ImageView mSiteTopBg;
@InjectView(R.id.site_name)
private TextView mSiteName;
@InjectView(R.id.site_producter)
private TextView mProducter;
@InjectView(R.id.site_logo)
private ImageRoundView mSiteLogo;
@InjectView(R.id.site_description)
private TextView mSiteDescription;
@InjectView(R.id.viewPager)
private ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_site);
Injector.injectView(this, this);
Injector.injectClick(this, this);
}
@Override
@InjectClick({R.id.action_back})
public void onClick(View v) {
int id = v.getId();
switch (id){
case R.id.action_back:
SiteDetailActivity.this.finish();
break; }
}
=============================================
一、布局文件的注解
我们在Android开发的时候,总是会写到setContentView方法,为了避免每次都写重复的代码,我们需要使用注解来代替我们做这个事情,只需要在类Activity上声明一个ContentView注解和对应的布局文件就可以了。
@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewUtils.injectContentView(this);
}
}
从上面可以看到,上面代码在MainActivity上面使用到了ContentView注解,下面我们来看看ContentView注解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
int value();
}
这个注解很简单,它有一个int的value,用来存放布局文件的id,另外它注解的对象为一个类型,需要说明的是,注解的生命周期会一直到运行时,这个很重要,因为程序是在运行时进行反射的,我们来看看ViewUtils.injectContentView(this)方法,它进行的就是注解的处理,就是进行反射调用setContentView()方法。
public static void injectContentView(Activity activity) {
Class a = activity.getClass();
if (a.isAnnotationPresent(ContentView.class)) {
// 得到activity这个类的ContentView注解
ContentView contentView = (ContentView) a.getAnnotation(ContentView.class);
// 得到注解的值
int layoutId = contentView.value();
// 使用反射调用setContentView
try {
Method method = a.getMethod(“setContentView”, int.class);
method.setAccessible(true);
method.invoke(activity, layoutId);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
如果对Java注解比较熟悉的话,上面代码应该很容易看懂。
二、字段的注解
除了setContentView之外,还有一个也是我们在开发中必须写的代码,就是findViewById,同样,它也属于简单但没有价值的编码,我们也应该使用注解来代替我们做这个事情,就是对字段进行注解。
@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {
@ViewInject(R.id.btn1)
private Button mButton1;
@ViewInject(R.id.btn2)
private Button mButton2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewUtils.injectContentView(this);
ViewUtils.injectViews(this);
}
}
上面我们看到,使用ViewInject对两个Button进行了注解,这样我们就是不用写findViewById方法,看上去很神奇,但其实原理很简单。我们先来看看ViewInject注解。
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewInject {
int value();
}
这个注解也很简单,就不说了,重点就是注解的处理了。
public static void injectViews(Activity activity) {
Class a = activity.getClass();
// 得到activity所有字段
Field[] fields = a.getDeclaredFields();
// 得到被ViewInject注解的字段
for (Field field : fields) {
if (field.isAnnotationPresent(ViewInject.class)) {
// 得到字段的ViewInject注解
ViewInject viewInject = field.getAnnotation(ViewInject.class);
// 得到注解的值
int viewId = viewInject.value();
// 使用反射调用findViewById,并为字段设置值
try {
Method method = a.getMethod(“findViewById”, int.class);
method.setAccessible(true);
Object resView = method.invoke(activity, viewId);
field.setAccessible(true);
field.set(activity, resView);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
上面的注释很清楚,使用的也是反射调用findViewById函数。
三、事件的注解
在Android开发中,我们也经常遇到setOnClickListener这样的事件方法。同样我们可以使用注解来减少我们的代码量。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://img-blog.csdnimg.cn/img_convert/aa26b92a1b5f7b697d5ffce791490bdc.jpeg)
总结
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2019-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。祝大家2021年万事大吉。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2019-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
[外链图片转存中…(img-sYUvGa9m-1712421580116)]
[外链图片转存中…(img-KqpVc1QF-1712421580117)]
[外链图片转存中…(img-d22nhHRO-1712421580117)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。祝大家2021年万事大吉。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!