Android——教你10分钟手敲 Butter Knife(小刀注解)

教你10分钟手敲 Butter Knife(小刀注解)

 

在用 AndroidStudio 集成 Butter Knife(小刀注解)的时候感觉像极了J2EE的Spring IOC容器 自己研究了一下,我来分享一下,小编会:多注释,多贴码,尽量降低同学们的学习时间成本,希望喜欢 花里胡哨 的同学不容错过。(求关注(✪ω✪))

简单介绍Butter Knife(小刀注解)是什么鬼:

原生的获取组件是这样的:

public class MainActivity extends AppCompatActivity {//定义组件private TextView main_tv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);main_tv = findViewById(R.id.main_tv);//获取组件main_tv.setText("卡哇伊");//使用组件}
}

使用 Butter Knife(小刀注解)后的获取组件是这样子的:

public class MainActivity extends AppCompatActivity {@BindView(R.id.main_tv)  private TextView main_tv;//定义组件@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButterKnife.bind(this);   //绑定activitymain_tv.setText("卡哇伊");//使用组件}}

在实际项目中有什么好处呢?

Butter Knife(小刀注解) 优点:

1、强大的View绑定和Click事件处理功能,简化代码,提升开发效率

2、方便的处理Adapter里的ViewHolder绑定问题

3、运行时不会影响APP效率,使用配置方便

4、代码清晰,可读性强

利用插件一键生成,爽到嗨。省去了 findViewById 。不就是利用注解赋值嘛,来小编带你10分钟搞定。

第一步:新建一共空的工程,并新建必要的文件目录 annotation、entity、fragment、util

第二步:在  新建一个注解 取名为 GT_View 并添加相应代码:

GT_View 注解代码:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GT_View {int value();
}

第三步:新建一个 GT_Util.java 的Java文件:

GT_Util 代码:(直接复制粘贴,代码有注释,Java基础好点的看懂的快些)

public class GT_Util {/*** 注入所有注解* @param activity*/public static void initAll(Activity activity){initView(activity);                 //为加载 组件 初始化}/***注入控件* @param activity*/private static void initView(Activity activity){Class<? extends Activity> clazz = activity.getClass();                              //获取该类信息Field[] fields = clazz.getDeclaredFields();                                         //获致所有成员变更for (Field field:fields) {                                                          //遍历所有当前 Activity 的成员变量GT_View initView = field.getAnnotation(GT_View.class);                          //获取当前变量的 GT_View 注解if(initView != null){                                                           //如果为 null 则表明当前成员变量没有被 GT_View 注解标注int viewId = initView.value();                                              //获取当前注解上标注的 组件IDtry {Method method = clazz.getMethod("findViewById", int.class);     //获取当前Activity中 findViewById 方法method.setAccessible(true);                                             //设置 findViewById 方法的 访问权限field.setAccessible(true);                                              //设置 当前成员变量的 访问权限Object object = method.invoke(activity, viewId);                        //注入数据:将ID 注入到 findViewById 中 并返回 Viewfield.set(activity,object);                                             //将返回的 View 设置到 Activity 中} catch (Exception e) {e.printStackTrace();}}}}}

第四步:修改xml文件,并在Activity添加相应代码:

activity_main.xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/main_tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"android:textSize="24sp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java 文件:

public class MainActivity extends AppCompatActivity {@GT_View(R.id.main_tv)private TextView main_tv;   //定义组件@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);GT_Util.initAll(this);           //绑定Activitymain_tv.setText("卡哇伊");       //使用组件}}

运行效果图:

总结:简单吧,10分钟做到这里差不多了,感谢你的阅读。٩(๑>◡<๑)۶ 

如果你并不满足于此,请继续阅读下面。

关注博主最新发布库:GitHub - 1079374315/GT

如果你并不满足于此,不如再花10分钟来搞定这些? 求关注(◕ᴗ◕✿)

@GT_Activity(R.layout.activity_main)//省去了 setContentView 方法
public class MainActivity extends AppCompatActivity {@GT_View(R.id.ioc_tv)private TextView tv;//获取View组件@GT_Object(valueString = "1079",valueInt = 21,types = {GT_Object.TYPE.STRING, GT_Object.TYPE.INT}, functions = {"setUsername","setAge"})private LoginBean loginBean;//获取带参数的实体类@GT_Res.GT_String(R.string.StringTest)private String data;//注入 res下string 字符串资源@GT_Res.GT_Color(R.color.colorTest)private int MyColor;//注入 res下color 颜色资源@GT_Res.GT_Drawable(R.drawable.ic_launcher_background)private Drawable btnBG;//注入 res下drawable 图片资源@GT_Res.GT_Dimen(R.dimen.tv_size)private float TextSize;//注入 res下dimen 尺寸资源@GT_Res.GT_Animation(R.anim.alpha)private Animation animation;//注入 res下anim 动画资源 @GT_Res.GT_StringArray(R.array.ctype)private String[] strArray;//注入 res下array string数组资源 @GT_Res.GT_IntArray(R.array.textInt)private int[] intArray;//注入 res下array int数组资源 @GT_Res.GT_Layout(R.layout.activity_main)private View layout;//注入 res下array 布局资源 @Collection.List({Fragment_1.class,Fragment_2.class,Fragment_3.class})List<Object> fragmentList;//实例化3个Fragment并注入到List中@Collection.Map({Fragment_1.class,Fragment_2.class,Fragment_3.class})Map<Object,Object> fragmentMap;//实例化3个Fragment并注入到Map中@Collection.Set({Fragment_1.class,Fragment_2.class,Fragment_3.class})Set<Object> fragmentSet;//实例化3个Fragment并注入到Set中@GT_Click({R.id.ioc_btn01,R.id.ioc_btn02,R.id.ioc_btn03})public void testBtnOnCLick(View view){//监听多按钮单击事件

既然你往下滑,那说明我们都是 好奇心 强的人,说好10分钟,我们时间紧迫赶紧的。(๑╹◡╹)ノ"""

第一步:添加必要的注解类 : 

Collection、GT_Activity、GT_Click、GT_Object、GT_Res、GT_View、OnClickEvent

Collection:注解代码如下

/*** 集合注解*/
public @interface Collection {/*** List 注解*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface List {Class[] value();}/*** Map 注解*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface Map {Class[] value();}/*** Set 注解*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface Set {Class[] value();}}

GT_Activity:注解代码如下

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface GT_Activity {int value();
}

GT_Click:注解代码如下

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@OnClickEvent(listenerType = View.OnClickListener.class,listenerSetter = "setOnClickListener",methodName = "onClick")
public @interface GT_Click {int[] value();
}

GT_Object:注解代码如下

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GT_Object {interface TYPE {String BYTE = "byte";String SHORT = "short";String INT = "int";String LONG = "long";String FLOAT = "float";String DOUBLE = "double";String BOOLEAN = "boolean";String CHAR = "char";String STRING = "String";String BYTES = "bytes";String SHORTS = "shorts";String INTS = "ints";String LONGS = "longs";String FLOATS = "floats";String DOUBLES = "doubles";String BOOLEANS = "booleans";String CHARS = "chars";String STRINGS = "Strings";}/** 单参数的传递 **/byte        valueByte()     default 0;short       valueShort()    default 0;int         valueInt()      default 0;long        valueLong()     default 0L;float       valueFloat()    default 0.0f;double      valueDouble()   default 0.0d;boolean     valueBoolean()  default false;char        valueChar()     default 0;String      valueString()   default "";/** 多参数的传递 **/byte[]      valueBytes()     default {};short[]     valueShorts()    default {};int[]       valueInts()      default {};long[]      valueLongs()     default {};float[]     valueFloats()    default {};double[]    valueDoubles()   default {};boolean[]   valueBooleans()  default {};char[]      valueChars()     default {};String[]    valueStrings()   default {};/** 修改参数的类型 **/String      type()           default "";String[]    types()          default {};/** 要赋值的方法 **/String      function()       default "";String[]    functions()      default {};}

GT_Res:注解代码如下

/*** 资源注解*/
public @interface GT_Res {/*** 字符串 注解*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface GT_String {int value();}/*** 颜色 注解*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface GT_Color {int value();}/*** 尺寸 注解*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface GT_Dimen {int value();}/*** 图片 注解*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface GT_Drawable {int value();}/*** 动画 注解*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface GT_Animation {int value();}/*** 字符串数组 注解*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface GT_StringArray {int value();}/*** 整数数组 注解*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface GT_IntArray {int value();}/*** 将 xml 文件解析成 View 注解*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface GT_Layout {int value();}}

OnClickEvent:注解代码如下

@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClickEvent {Class<?> listenerType();//接口类型String listenerSetter();//设置的方法String methodName();//接口里面要实现的方法
}

第二步:更新 GT_Util.java 文件

注意:代码有点多(接近千行),但原理都与上面详细讲解的差异不多所以就直接贴码了。

public class GT_Util {//Fragment 注入public static void initAll(Object object, View view){initView(object,view);                 //为加载 组件 初始化initClick(object,view);                //为加载 组件单击 初始化initObject(object);                    //为加载 Object 成员变量初始化initList(object);                      //为加载 List 成员变量初始化initMap(object);                       //为加载 Map 成员变量初始化initSet(object);                       //为加载 Set 成员变量初始化initAnimation(object,view);            //为加载 Animation 资源初始化initDimen(object,view);                //为加载 Dimen 资源初始化initDrawable(object,view);             //为加载 Style 资源初始化initColor(object,view);                //为加载 Color 资源初始化initString(object,view);               //为加载 String 资源初始化initIntArray(object,view);             //为加载 IntArray 资源初始化initStringArray(object,view);          //为加载 StringArray 资源初始化initLayout(object,view);               //为加载 Layout 资源初始化}/*** Fragment 中的使用*//** Fragment 注入控件*/private static void initView(Object object,View view){Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields = clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_View initView = field.getAnnotation(GT_View.class);if(initView != null){int viewId = initView.value();try {View viewById = view.findViewById(viewId);field.setAccessible(true);field.set(object,viewById);} catch (Exception e) {e.printStackTrace();}}}}/** 注入点击事件 */private static void initClick(Object object,View view){Class<? extends Object> clazz = object.getClass();Method[] methods= clazz.getMethods();//获取所有声明为公有的方法for (Method method:methods){//遍历所有公有方法Annotation[] annotations = method.getAnnotations();//获取该公有方法的所有注解for (Annotation annotation:annotations){//遍历所有注解Class<? extends Annotation> annotationType = annotation.annotationType();//获取具体的注解类OnClickEvent onClickEvent = annotationType.getAnnotation(OnClickEvent.class);//取出注解的onClickEvent注解if(onClickEvent!=null){//如果不为空try {Method valueMethod=annotationType.getDeclaredMethod("value");//获取注解InjectOnClick的value方法int[] viewIds= (int[]) valueMethod.invoke(annotation, (Object[]) null);//获取控件值Class<?> listenerType = onClickEvent.listenerType();//获取接口类型String listenerSetter = onClickEvent.listenerSetter();//获取set方法String methodName = onClickEvent.methodName();//获取接口需要实现的方法MyInvocationHandler handler = new MyInvocationHandler(object);//自己实现的代码,负责调用handler.setMethodMap(methodName,method);//设置方法及设置方法Object object2 = Proxy.newProxyInstance(listenerType.getClassLoader(),new Class<?>[]{listenerType},handler);//创建动态代理对象类for (int viewId:viewIds){//遍历要设置监听的控件View view2 = view.findViewById(viewId);//获取该控件Method m = view2.getClass().getMethod(listenerSetter, listenerType);//获取方法m.invoke(view2,object2);//调用方法}} catch (Exception e) {e.printStackTrace();}}}}}/** 注入 Animation 资源字符串 **/private static void initAnimation(Object object, View view) {Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_Animation initView = field.getAnnotation(GT_Res.GT_Animation.class);if(initView!=null){int viewRes = initView.value();try {Context context = view.getContext();if(context != null){Animation animation = AnimationUtils.loadAnimation(context, viewRes);field.setAccessible(true);field.set(object,animation);}} catch (Exception e) {e.printStackTrace();}}}}/** 注入 Dimen 资源字符串 **/private static void initDimen(Object object, View view) {Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_Dimen initView = field.getAnnotation(GT_Res.GT_Dimen.class);if(initView!=null){int viewRes = initView.value();try {float dimension = view.getResources().getDimension(viewRes);field.setAccessible(true);field.set(object,dimension);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 Drawable 资源字符串 **/private static void initDrawable(Object object, View view) {Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_Drawable initView = field.getAnnotation(GT_Res.GT_Drawable.class);if(initView!=null){int viewRes = initView.value();try {Drawable drawable = view.getResources().getDrawable(viewRes);field.setAccessible(true);field.set(object,drawable);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 Color 资源字符串 **/private static void initColor(Object object, View view) {Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_Color initView = field.getAnnotation(GT_Res.GT_Color.class);if(initView!=null){int viewRes = initView.value();try {int color = view.getResources().getColor(viewRes);field.setAccessible(true);field.set(object,color);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 String 资源字符串 **/private static void initString(Object object, View view) {Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_String initView = field.getAnnotation(GT_Res.GT_String.class);if(initView!=null){int viewRes = initView.value();try {String string = view.getResources().getString(viewRes);field.setAccessible(true);field.set(object,string);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 Int 资源字符串数组 **/private static void initIntArray(Object object, View view) {Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_IntArray initView = field.getAnnotation(GT_Res.GT_IntArray.class);if(initView!=null){int viewRes = initView.value();try {int[] intArray = view.getResources().getIntArray(viewRes);field.setAccessible(true);field.set(object,intArray);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 String 资源字符串数组 **/private static void initStringArray(Object object, View view) {Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_StringArray initView = field.getAnnotation(GT_Res.GT_StringArray.class);if(initView!=null){int viewRes = initView.value();try {String[] stringArray = view.getResources().getStringArray(viewRes);field.setAccessible(true);field.set(object,stringArray);} catch (Exception e) {e.printStackTrace();}}}}/** 解析 Layout 资源文件成 View **/private static void initLayout(Object object, View view) {Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_Layout initView = field.getAnnotation(GT_Res.GT_Layout.class);if(initView!=null){int viewRes = initView.value();try {Context context = view.getContext();if(context != null){View viewLayout = LayoutInflater.from(context).inflate(viewRes, null);field.setAccessible(true);field.set(object,viewLayout);}} catch (Exception e) {e.printStackTrace();}}}}/** 注入 List 资源字符串 **/private static void initList(Object object) {Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {Collection.List initView = field.getAnnotation(Collection.List.class);if(initView!=null){Class[] classes = initView.value();List<Object> objectList = new ArrayList<>();//创建一个 ListViewfor(Class cla : classes){String classPage = cla.toString();String[] s = classPage.split(" ");classPage = s[1];//实例化一个对象Object object2 = null;try {object2 = Class.forName(classPage).newInstance();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}objectList.add(object2);//添加每一个经过反射得到的 对象}try {field.setAccessible(true);field.set(object,objectList);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 Map 资源字符串 **/private static void initMap(Object object) {Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {Collection.Map initView = field.getAnnotation(Collection.Map.class);if(initView!=null){Class[] classes = initView.value();Map<Object,Object> objectMap = new HashMap<>();//创建一个 Mapfor(Class cla : classes){String classPage = cla.toString();String[] s = classPage.split(" ");classPage = s[1];//实例化一个对象Object object2 = null;try {object2 = Class.forName(classPage).newInstance();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}objectMap.put(cla,object2);//保存每个创建出来的 对象 key 为 每个对象的 class}try {field.setAccessible(true);field.set(object,objectMap);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 Set 资源字符串 **/private static void initSet(Object object) {Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {Collection.Set initView = field.getAnnotation(Collection.Set.class);if(initView!=null){Class[] classes = initView.value();Set<Object> objectSet = new HashSet<>();//创建一个 Setfor(Class cla : classes){String classPage = cla.toString();String[] s = classPage.split(" ");classPage = s[1];//实例化一个对象Object object2 = null;try {object2 = Class.forName(classPage).newInstance();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}objectSet.add(object2);//保存每个创建出来的 对象}try {field.setAccessible(true);field.set(object,objectSet);} catch (Exception e) {e.printStackTrace();}}}}/*** Activity 中的使用*//*** activity 注入* @param activity*/public static void initAll(Activity activity){initActivity(activity);             //为加载 Activity 布局初始化initView(activity);                 //为加载 组件 初始化initClick(activity);                //为加载 组件单击 初始化initObject(activity);               //为加载 Object 成员变量初始化initAnimation(activity);            //为加载 Animation 资源初始化initDimen(activity);                //为加载 Dimen 资源初始化initDrawable(activity);             //为加载 Style 资源初始化initColor(activity);                //为加载 Color 资源初始化initString(activity);               //为加载 String 资源初始化initIntArray(activity);             //为加载 IntArray 资源初始化initStringArray(activity);          //为加载 StringArray 资源初始化initLayout(activity);               //为加载 Layout 资源初始化}/** 解析 Layout 资源文件成 View **/private static void initLayout(Activity activity) {Class<? extends Activity> clazz = activity.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_Layout initView = field.getAnnotation(GT_Res.GT_Layout.class);if(initView!=null){int viewRes = initView.value();try {View view = LayoutInflater.from(activity).inflate(viewRes, null);field.setAccessible(true);field.set(activity,view);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 Int 资源字符串数组 **/private static void initIntArray(Activity activity) {Class<? extends Activity> clazz = activity.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_IntArray initView = field.getAnnotation(GT_Res.GT_IntArray.class);if(initView!=null){int viewRes = initView.value();try {int[] intArray = activity.getResources().getIntArray(viewRes);field.setAccessible(true);field.set(activity,intArray);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 String 资源字符串数组 **/private static void initStringArray(Activity activity) {Class<? extends Activity> clazz = activity.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_StringArray initView = field.getAnnotation(GT_Res.GT_StringArray.class);if(initView!=null){int viewRes = initView.value();try {String[] stringArray = activity.getResources().getStringArray(viewRes);field.setAccessible(true);field.set(activity,stringArray);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 Animation 资源字符串 **/private static void initAnimation(Activity activity) {Class<? extends Activity> clazz = activity.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_Animation initView = field.getAnnotation(GT_Res.GT_Animation.class);if(initView!=null){int viewRes = initView.value();try {Animation animation = AnimationUtils.loadAnimation(activity, viewRes);field.setAccessible(true);field.set(activity,animation);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 Dimen 资源字符串 **/private static void initDimen(Activity activity) {Class<? extends Activity> clazz = activity.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_Dimen initView = field.getAnnotation(GT_Res.GT_Dimen.class);if(initView!=null){int viewRes = initView.value();try {float dimension = activity.getResources().getDimension(viewRes);field.setAccessible(true);field.set(activity,dimension);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 Drawable 资源字符串 **/private static void initDrawable(Activity activity) {Class<? extends Activity> clazz = activity.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_Drawable initView = field.getAnnotation(GT_Res.GT_Drawable.class);if(initView!=null){int viewRes = initView.value();try {Drawable drawable = activity.getResources().getDrawable(viewRes);field.setAccessible(true);field.set(activity,drawable);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 Color 资源字符串 **/private static void initColor(Activity activity) {Class<? extends Activity> clazz = activity.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_Color initView = field.getAnnotation(GT_Res.GT_Color.class);if(initView!=null){int viewRes = initView.value();try {int color = activity.getResources().getColor(viewRes);field.setAccessible(true);field.set(activity,color);} catch (Exception e) {e.printStackTrace();}}}}/** 注入 String 资源字符串 **/private static void initString(Activity activity) {Class<? extends Activity> clazz = activity.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Res.GT_String initView = field.getAnnotation(GT_Res.GT_String.class);if(initView!=null){int viewRes = initView.value();try {String string = activity.getResources().getString(viewRes);field.setAccessible(true);field.set(activity,string);} catch (Exception e) {e.printStackTrace();}}}}/*** 参数版* @param object*/private static void initObject(Object object){Class<? extends Object> clazz = object.getClass();//获取该类信息Field[] fields = clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_Object initView = field.getAnnotation(GT_Object.class);if(initView != null){//获取 完整的类路径String classPage = field.toString();String[] s = classPage.split(" ");classPage = s[1];//实例化一个对象Object object2 = null;try {object2 = Class.forName(classPage).newInstance();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}//获取参数的值类型String type = initView.type();String[] types = initView.types();//创建保存 参数类型的容器List<Object> valueList = new ArrayList<>();if(type.length() != 0){valueType(type,valueList,initView,0);//将当前的单个数据赋值到 listView 中}else if(types.length != 0){for(int i = 0; i < types.length; i++){valueType(types[i],valueList,initView,i);//将当前的多个数据赋值到 listView 中}}String function = initView.function();String[] functions = initView.functions();/*** 获取当前方法所有方法*/if(function.length() != 0 && valueList.size() != 0){functionValue(field,object2,function,valueList,0);//对相应的方法进行赋值}else if(functions.length != 0 && valueList.size() != 0){for(int i = 0; i < functions.length; i++){functionValue(field,object2,functions[i],valueList,i);//对相应的方法进行赋值}}//给注解下面的 成员变量注入值try {field.setAccessible(true);field.set(object,object2);} catch (IllegalAccessException e) {e.printStackTrace();}}}}private static void functionValue(Field field, Object object, String functionName, List<Object> valueList, int index){if(functionName.length() != 0 && valueList.size() != 0){Class<?> aClass = object.getClass();Method[] methods = aClass.getMethods();//获取当前类中所有方法for(int i = methods.length-1; i >= 0 ; i--){String name = methods[i].getName();if(name.equals(functionName)){try {Method method = getAllValueTypeMethod(valueList.get(index),functionName,aClass);method.setAccessible(true);field.setAccessible(true);method.invoke(object, valueList.get(index));} catch (Exception e) {GT.log_i("赋值报错");e.printStackTrace();}}}}}/*** 自获取当前传入数据的类型* @param data* @param functionName* @param aClass* @return*/private static Method getAllValueTypeMethod(Object data, String functionName, Class<?> aClass){Method method = null;Class<?> aClass1 = data.getClass();switch (aClass1.toString()){case "class java.lang.Byte":try {method =  aClass.getMethod(functionName, byte.class);} catch (NoSuchMethodException e) {
//                    e.printStackTrace();}break;case "class java.lang.Short":try {method =  aClass.getMethod(functionName, short.class);} catch (NoSuchMethodException e) {
//                    e.printStackTrace();}break;case "class java.lang.Integer":try {method =  aClass.getMethod(functionName, int.class);} catch (NoSuchMethodException e) {
//                    e.printStackTrace();}break;case "class java.lang.Long":try {method =  aClass.getMethod(functionName, long.class);} catch (NoSuchMethodException e) {
//                    e.printStackTrace();}break;case "class java.lang.Float":try {method =  aClass.getMethod(functionName, float.class);} catch (NoSuchMethodException e) {
//                    e.printStackTrace();}break;case "class java.lang.Double":try {method =  aClass.getMethod(functionName, double.class);} catch (NoSuchMethodException e) {
//                    e.printStackTrace();}break;case "class java.lang.Boolean":try {method =  aClass.getMethod(functionName, boolean.class);} catch (NoSuchMethodException e) {
//                    e.printStackTrace();}break;case "class java.lang.Character":try {method =  aClass.getMethod(functionName, char.class);} catch (NoSuchMethodException e) {
//                    e.printStackTrace();}break;case "class java.lang.String":try {method =  aClass.getMethod(functionName, String.class);} catch (NoSuchMethodException e) {
//                    e.printStackTrace();}break;}return method;}/*** 给 listView 赋值* @param type* @param list* @param values*/private static void valueType(String type, List<Object> list, GT_Object values, int index){switch (type){/** 单个参数的赋值 **/case "byte":list.add(values.valueByte());break;case "short":list.add(values.valueShort());break;case "int":list.add(values.valueInt());break;case "long":list.add(values.valueLong());break;case "float":list.add(values.valueFloat());break;case "double":list.add(values.valueDouble());break;case "boolean":list.add(values.valueBoolean());break;case "char":list.add(values.valueChar());break;case "String":list.add(values.valueString());break;/** 多个参数的赋值 **/case "bytes":byte[] bytes = values.valueBytes();for(byte value:bytes){list.add(value);}break;case "shorts":short[] shorts = values.valueShorts();list.add(shorts[index]);break;case "ints":int[] ints = values.valueInts();list.add(ints[index]);break;case "longs":long[] longs = values.valueLongs();list.add(longs[index]);break;case "floats":float[] floats = values.valueFloats();list.add(floats[index]);break;case "doubles":double[] doubles = values.valueDoubles();list.add(doubles[index]);break;case "booleans":boolean[] booleans = values.valueBooleans();list.add(booleans[index]);break;case "chars":char[] chars = values.valueChars();list.add(chars[index]);break;case "Strings":String[] strings = values.valueStrings();list.add(strings[index]);break;}}/*** 注入 ContextView* @param activity*/private static void initActivity(Activity activity){Class<? extends Activity> mClass = activity.getClass();//获取该类信息GT_Activity contentView = mClass.getAnnotation(GT_Activity.class);//获取该类 ContextView 的注解类//如果有注解if(contentView != null){int viewId = contentView.value();//获取注解类参数try {Method method = mClass.getMethod("setContentView",int.class);//获取该方法的信息method.setAccessible(true);//获取该方法的访问权限method.invoke(activity,viewId);//调用该方法的,并设置该方法参数} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}}/***注入控件* @param activity*/private static void initView(Activity activity){Class<? extends Activity> clazz = activity.getClass();//获取该类信息Field[] fields=clazz.getDeclaredFields();//获致所有成员变更for (Field field:fields) {GT_View initView = field.getAnnotation(GT_View.class);if(initView!=null){int viewId=initView.value();try {Method method = clazz.getMethod("findViewById", int.class);method.setAccessible(true);field.setAccessible(true);Object object = method.invoke(activity, viewId);field.set(activity,object);} catch (Exception e) {e.printStackTrace();}}}}/*** 注入点击事件* @param activity*/private static void initClick(Activity activity){Class<? extends Activity> clazz = activity.getClass();Method[] methods= clazz.getMethods();//获取所有声明为公有的方法for (Method method:methods){//遍历所有公有方法Annotation[] annotations = method.getAnnotations();//获取该公有方法的所有注解for (Annotation annotation:annotations){//遍历所有注解Class<? extends Annotation> annotationType = annotation.annotationType();//获取具体的注解类OnClickEvent onClickEvent = annotationType.getAnnotation(OnClickEvent.class);//取出注解的onClickEvent注解if(onClickEvent!=null){//如果不为空try {Method valueMethod=annotationType.getDeclaredMethod("value");//获取注解InjectOnClick的value方法int[] viewIds= (int[]) valueMethod.invoke(annotation, (Object[]) null);//获取控件值Class<?> listenerType = onClickEvent.listenerType();//获取接口类型String listenerSetter = onClickEvent.listenerSetter();//获取set方法String methodName = onClickEvent.methodName();//获取接口需要实现的方法MyInvocationHandler handler = new MyInvocationHandler(activity);//自己实现的代码,负责调用handler.setMethodMap(methodName,method);//设置方法及设置方法Object object= Proxy.newProxyInstance(listenerType.getClassLoader(),new Class<?>[]{listenerType},handler);//创建动态代理对象类for (int viewId:viewIds){//遍历要设置监听的控件View view=activity.findViewById(viewId);//获取该控件Method m=view.getClass().getMethod(listenerSetter, listenerType);//获取方法m.invoke(view,object);//调用方法}} catch (Exception e) {e.printStackTrace();}}}}}//注解帮助类static class MyInvocationHandler implements InvocationHandler {private Object object;private Map<String, Method> methodMap = new HashMap<>(1);public MyInvocationHandler(Object object) {this.object = object;}public void setMethodMap(String name, Method method) {this.methodMap.put(name, method);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (object != null) {String name = method.getName();method= this.methodMap.get(name);if (method != null) {return method.invoke(object, args);}}return null;}}}

一下子码这么多,我也是第一次写博客写这么多,我们休息一下,我们看个美景,缓缓眼睛疲劳

接下来,我们就只欠东风了。

第三步:新建必要的文件:

LoginBean、Fragment_1、Fragment_2、Fragment_3

LoginBean:代码如下

public class LoginBean {private String username;private String password;private int age;public void setAge(int age) {this.age = age;}public LoginBean() {super();}public LoginBean(String username, String password, int age) {this.username = username;this.password = password;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "LoginBean{" +"username='" + username + '\'' +", password='" + password + '\'' +", age=" + age +'}';}}

Fragment_1:代码如下

public class Fragment_1 extends Fragment {private static final String TAG = "GT_";public static Fragment_1 newInstance() {Bundle args = new Bundle();Log.i(TAG,"Fragment_1 newInstance");Fragment_1 fragment = new Fragment_1();fragment.setArguments(args);return fragment;}public Fragment_1(){Log.i(TAG,"Fragment_1");}}

Fragment_2:代码如下

public class Fragment_2 extends Fragment {private static final String TAG = "GT_";public static Fragment_2 newInstance() {Bundle args = new Bundle();Log.i(TAG,"Fragment_2 newInstance");Fragment_2 fragment = new Fragment_2();fragment.setArguments(args);return fragment;}public Fragment_2(){Log.i(TAG,"Fragment_2");}}

Fragment_3:代码如下

public class Fragment_3 extends Fragment {private static final String TAG = "GT_";public static Fragment_3 newInstance() {Bundle args = new Bundle();Log.i(TAG,"Fragment_3 newInstance");Fragment_3 fragment = new Fragment_3();fragment.setArguments(args);return fragment;}public Fragment_3(){Log.i(TAG,"Fragment_3");}}

第四步:添加测试资源文件

alpha.xml 代码:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><!-- alpha 设置透明度fromAlpha :  起始点的透明度toAlpha   :  结束点的透明度duration  :  设置透明度渐变的时间 已毫秒为单位repeatCount: 设置重复次数repeatMode:  reverse(反向) | restart(重新开始)  设置重复方式--><alphaandroid:fromAlpha="0.5"android:toAlpha="1"android:duration="2000"/></set>

activity_main.xml 代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/ioc_tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:id="@+id/ioc_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="单击测试"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintVertical_bias="0.603" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintBottom_toTopOf="@+id/ioc_tv"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"><Buttonandroid:id="@+id/ioc_btn01"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="按钮1" /><Buttonandroid:id="@+id/ioc_btn02"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="按钮2" /><Buttonandroid:id="@+id/ioc_btn03"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="按钮3" /></LinearLayout></androidx.constraintlayout.widget.ConstraintLayout>

arrays.xml 代码:

<?xml version="1.0" encoding="utf-8"?>
<resources><!--定义字符串元素--><string-array name="ctype"><item>全部</item><item>电影</item><item>娱乐</item><item>图书</item><item>运动</item></string-array><!--定义整数类型数组--><integer-array name="textInt"><item>1</item><item>2</item><item>3</item></integer-array></resources>

colors.xml 代码:

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="colorPrimary">#008577</color><color name="colorPrimaryDark">#00574B</color><color name="colorAccent">#D81B60</color><color name="colorTest">#FFE700</color>
</resources>

dimens.xml 代码:

<?xml version="1.0" encoding="utf-8"?>
<resources><!--定义尺寸资源--><dimen name="tv_size">10sp</dimen></resources>

strings.xml 代码:

<resources><string name="app_name">Butter Knife(小刀注解)</string><string name="StringTest">测试数据</string>
</resources>

最后步:添加测试代码

MainActivity.java 代码:

@GT_Activity(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {@GT_View(R.id.ioc_tv)private TextView tv;@GT_View(R.id.ioc_btn)private Button btn;@GT_Object(valueString = "1079",valueInt = 21,types = {GT_Object.TYPE.STRING, GT_Object.TYPE.INT}, functions = {"setUsername","setAge"})private LoginBean loginBean;@GT_Res.GT_String(R.string.StringTest)private String data;@GT_Res.GT_Color(R.color.colorTest)private int MyColor;@GT_Res.GT_Drawable(R.drawable.ic_launcher_background)private Drawable btnBG;@GT_Res.GT_Dimen(R.dimen.tv_size)private float TextSize;@GT_Res.GT_Animation(R.anim.alpha)private Animation animation;@GT_Res.GT_StringArray(R.array.ctype)private String[] strArray;@GT_Res.GT_IntArray(R.array.textInt)private int[] intArray;@GT_Res.GT_Layout(R.layout.activity_main)private View layout;private static final String TAG = "GT_";protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);GT_Util.initAll(this);//绑定 ActivityGT.log_e( "onCreate: tv = " + tv + " btn:" + btn);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.i(TAG,"loginBean: " + loginBean);Log.i(TAG,"data: " + data);Log.i(TAG,"color: " + MyColor);Log.i(TAG,"Drawable: " + btnBG);Log.i(TAG,"TextSize: " + TextSize);Log.i(TAG,"animation: " + animation);Log.i(TAG,"strArray: " + strArray);Log.i(TAG,"intArray: " + intArray);Log.i(TAG,"layout: " + layout);tv.setText("实现成功!");btn.setTextColor(MyColor);btn.setTextSize(TextSize);btn.setBackgroundDrawable(btnBG);btn.startAnimation(animation);}});}@GT_Click({R.id.ioc_btn01,R.id.ioc_btn02,R.id.ioc_btn03})public void testBtnOnCLick(View view){switch (view.getId()){case R.id.ioc_btn01:Log.i(TAG,"单击 1 号" );break;case R.id.ioc_btn02:Log.i(TAG,"单击 2 号" );break;case R.id.ioc_btn03:Log.i(TAG,"单击 3 号" );break;}}}

终于完成了所有代码的编写,现在我们来看看你花这10分钟到底值不值吧。٩(๑>◡<๑)۶ 

运行效果图:

打印日志:

08-30 12:11:33.918 3723-3723/com.gsls.myapplication E/GT_e: ------- onCreate: tv = androidx.appcompat.widget.AppCompatTextView{5552d29 V.ED.... ......ID 0,0-0,0 #7f08004d app:id/ioc_tv} btn:androidx.appcompat.widget.AppCompatButton{fbce8ae VFED..C. ......I. 0,0-0,0 #7f080049 app:id/ioc_btn}
08-30 12:11:41.841 3723-3723/com.gsls.myapplication I/GT_: 单击 1 号
08-30 12:11:42.408 3723-3723/com.gsls.myapplication I/GT_: 单击 2 号
08-30 12:11:43.001 3723-3723/com.gsls.myapplication I/GT_: 单击 3 号
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: loginBean: LoginBean{username='1079', password='null', age=21}
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: data: 测试数据
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: color: -6400
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: Drawable: android.graphics.drawable.VectorDrawable@2280d25b
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: TextSize: 10.0
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: animation: android.view.animation.AnimationSet@3e537af8
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: strArray: [Ljava.lang.String;@cd31bd1
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: intArray: [I@1d02b636
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: layout: androidx.constraintlayout.widget.ConstraintLayout{11703937 V.E..... ......I. 0,0-0,0}
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: loginBean: LoginBean{username='1079', password='null', age=21}
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: data: 测试数据
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: color: -6400
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: Drawable: android.graphics.drawable.VectorDrawable@2280d25b
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: TextSize: 10.0
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: animation: android.view.animation.AnimationSet@3e537af8
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: strArray: [Ljava.lang.String;@cd31bd1
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: intArray: [I@1d02b636
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: layout: androidx.constraintlayout.widget.ConstraintLayout{11703937 V.E..... ......I. 0,0-0,0}

总结:看我这么辛苦。 点个关注呗<(▰˘◡˘▰)>

关注博主最新发布库:https://github.com/1079374315/GT

本篇文章源码地址:github地址:GitHub - 1079374315/GT_IOC: 教你10分钟手敲 Butter Knife(小刀注解)

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

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

相关文章

最新织梦程序精仿小刀娱乐网资源网主题模板源码

介绍&#xff1a; 当初花了300块买的一套源码&#xff0c;跟小刀同款一模一样&#xff0c;仿的大鹏资源网 网盘下载地址&#xff1a; https://zijiewangpan.com/NfH3vcZyxvf 图片&#xff1a;

小刀娱乐网源码2020版

简介&#xff1a; 小刀娱乐网源码是aspaccess/mssql架构网站系统&#xff0c;电脑版&#xff0c;手机版&#xff0c;平板版无缝切换&#xff0c;一个后台同步管理&#xff0c;整站生成静态利于搜索收录&#xff0c;dreamweaver打开可视化修改。 专为制作“小刀娱乐网、QQ教程…

最新精仿小刀娱乐资源网模板源码,带前台会员投稿审核功能

介绍&#xff1a; 安装方法一&#xff1a; 1、将根目录文件上传服务器 2、将根目录1x6d.sql导入mysql数据库 3、环境需要支持PHP5.6&#xff08;推荐PHP7.2&#xff09;&#xff0c;mysql5.0 4、配置数据库Conf/config.php 填写数据库账户密码 5、删除根目录安装文件install …

新版仿小刀资源网模板—木鱼cms

介绍&#xff1a; 仿小刀资源网模板新鲜出炉&#xff0c;使用的是muyucms 仿小刀资源网页面 1比1还原 这套模板使用了全新的轻量cms系统 木鱼cms 网盘下载地址&#xff1a; http://kekewl.net/38Bsc80j7460 图片&#xff1a;

晗枫emlog仿小刀网修复版模板

介绍&#xff1a; 晗枫开源的emlog仿小刀HFdao模板&#xff0c;测试之后和小刀网的没什么差别&#xff0c;EMLOG用户的福利模板&#xff0c;全开源免费发布。 JS各大搜索引擎自动提交收录&#xff01; 最后如果自己二开请留个版权作者开发不易&#xff0c;不做伸手党&#xff…

php小刀娱乐网源码,PHP精仿小刀娱乐网资源下载站网站整站源码

【温馨提示】源码包解压密码&#xff1a;www.youhutong.com 资源描述 PHP精仿小刀娱乐网资源下载站网站整站源码 源码介绍&#xff1a; 网友花了300多元买的源码。 该源码使用dedecms系统去仿小刀娱乐网资源下载站一套源码模板&#xff0c;安装简单。非常适合做资源素材站用。 …

emlog程序仿小刀娱乐网模板最终版本分享

介绍&#xff1a; 上个版本本次修复广告横幅只显示大图的问题&#xff0c;修复文字广告在手机不显示文章置顶广告移除热门&#xff0c; 现在不在热门显示了修复免责一类&#xff0c;关于这些&#xff0c;不再是看文章那种了左侧大图轮播去掉&#xff0c;不在显示箭头&#xff…

Emlog程序小刀娱乐网同款顶踩插件

介绍&#xff1a; 插件适用于EMLOG&#xff0c;插件仿的小刀娱乐网插件。 没个样式也非常好看加上两个表情包 很有趣&#xff0c;就插件已经适用Emlog系统了&#xff0c;效果还不错&#xff01; 将压缩包里的digg文件上传到你emlog的插件目录下即可 然后在echo_log.php文章页的…

emlog高仿小刀新版本模板

介绍&#xff1a; 此模板是模仿小刀的模板&#xff0c;修改首页左广告图下内容&#xff0c;比之前更实用。 修复无法搜索以及标签问题。 删除文章页千篇一律的免责声明。 添加右侧投稿和top悬浮标&#xff0c;可以和之前的top共存。 友链中的部分链接可以在module.php修改。 最…

最新emlog程序仿小刀模板源码

介绍&#xff1a; 此模板是模仿小刀的模板&#xff0c;修改首页左广告图下内容&#xff0c;比之前更实用。 修复无法搜索以及标签问题。 删除文章页千篇一律的免责声明。 添加右侧投稿和top悬浮标&#xff0c;可以和之前的top共存。 友链中的部分链接可以在module.php修改。 最…

EMLOG插件采集小刀模板

介绍&#xff1a; 插件目前支持采集&#xff0c;只需输入网站文章地址&#xff0c;然后绑定你自己网站的分类ID就行了。 网盘下载地址&#xff1a; http://kekewangLuo.net/uP8ixoLc0k4 图片&#xff1a;

象棋里的小刀剜心

象棋里的小刀剜心&#xff0c;也叫"小鬼拍门"&#xff0c;指得是&#xff0c;用兵吃到对方的士&#xff0c;然后用其他子力击杀将(帅)的方法。这种杀法需要提前计算好攻击的方向、子力的运输步骤等。下面介绍其典型案例。 1、"顿挫"小刀剜心 1.1 残局图 …

欧洲地图

1、欧洲地图 2、欧洲地形图

chatgpt赋能python:Python调色板:一篇全面介绍

Python调色板&#xff1a;一篇全面介绍 如果您正在寻找一个有效的编程语言&#xff0c;那么Python很可能就是您需要的。Python是一种高级编程语言&#xff0c;它已经成为最流行的编程语言之一&#xff0c;尤其是在数据分析、科学计算、云计算和机器学习方面。而今天我们要介绍…

ChatGPT「代码解释器」来了!图片秒变视频

转自&#xff1a;智元 【新智元导读】坐等3个多月&#xff0c;ChatGPT「代码解释器」终于全面开放了&#xff0c;一大波魔法来袭。 家人们&#xff0c;终于来了&#xff01; 刚刚&#xff0c;ChatGPT「代码解释器」测试版正式向所有Plus用户开放。 OpenAI的科学家Karpathy对此还…

chatgpt赋能python:Python调色板

Python调色板 在python中&#xff0c;绘制有吸引力的图表可以让数据更好地展示。一个好的颜色方案可以让这些图表更加优美和易于理解。python中有许多工具&#xff0c;可以帮助我们为图表选择适当的颜色&#xff0c;其中调色板&#xff08;palette&#xff09;是其中之一。 什…

大模型时代的prompt学习(持续更新)

目录 为什么要学prompt基本原则prompt撰写框架Base Prompt FrameworkCRISPE Prompt Framework 场景撰写文案文档竞品分析产品设计数据分析 chain of thoughtzero shotin context learning(few shot)Self-Consistency Program-Aidedprompt tipsTo Do and Not To Doadd examples引…

提示工程的前世今生

原文链接&#xff1a;芝士AI吃鱼 通过提示进行情境学习 在生物学中&#xff0c;涌现是一种令人难以置信的特性&#xff0c;由于相互作用的结果&#xff0c;各个部分聚集在一起&#xff0c;表现出新的行为&#xff08;称为涌现&#xff09;&#xff0c;这是你在较小的尺度上看不…

[230627] 阅读TOP001汇总|9:20-10:20

前言 &#x1f3e0;个人主页&#xff1a;我是沐风晓月 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是沐风晓月&#xff0c;阿里云社区博客专家 &#x1f609;&#x1f609; &#x1f495; 座右铭&#xff1a; 先努力成长自己&#xff0c;再帮助更多的人,一起加油进…

ChatBI:智能问答报表,助力职场数据分析与运营

随着企业数据的不断增长和商业竞争的加剧&#xff0c;越来越多的企业开始关注商业情报分析(BI)。BI可以帮助企业更好地了解市场趋势、客户需求和业务运营等方面的信息&#xff0c;从而更好地制定商业策略和决策。然而&#xff0c;传统的BI工具往往需要人工干预和专业技能&#…