Android 自定义注解详解,android应用开发基础答案
在注解中,一般都会包含一些元素表示某些值,并且可以为这些元素设置默认值,没有元素的注解也称为标记注解(marker annotation)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD})
public @interface LogClassMessage {
public int id () default -1;
public String message() default “”;
}
注:虽然上面的 id 和 message 定义和接口的方法定义很类似,但是在注解中将 id 和 message 称为:int元素id , String 元素 message。而且注解元素的类型是有限制的,并不是任何类型都可以,主要包括:基本数据类型(理论上是没有基本类型的包装类型的,但是由于自动封装箱,所以也不会报错)、String 类型、enum 类型、Class 类型、Annotation 类型、以及以上类型的数组,(小伙伴们没有等字哦,说明目前注解的元素类型只支持上面列出的这几种),否则编译器便会提示错误。
invalid type ‘void ’ for annotation member //例如注解类型为void的错误信息
对于默认值限制 ,Bruce Eckel (美) 在其书中是这样描述的:编译器对元素的默认值有些过分挑剔,首先,元素不能有不确定的值。也就是说,元素必须要么具有默认值,要么在使用注解时提供注解的值。其次,对于非基本类型的元素,无论在源代码声明中,或者在注解接口中定义默认值时,都不能以 null 作为其值。这个约束使得处理器很难表现一个元素的存在或缺失的状态,因为在每个注解的声明中,所有元素都存在,并且都具有相应的值。为了绕开这个约束,我们只能自己定义一些特殊的值,例如空字符串或者负数,以此表示某个元素的不存在,这算得上是一个习惯用法。
3. 参考下系统的标准注解
怎么说呢,接触一种新的知识的途径有很多,可能每一种的结果都是大同小异的,都能让你学到东西,但是实现的方式、实现过程中的规范、方法和思路却并不一定是最佳的,本人选择的是借鉴源码,效果还不错,在这里推荐给大家。
上文讲到的是注解的基本语法,那么系统是怎么用的呢?首先让我们来看一下使用频率最高的 @Override :
@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public![](https://www.hualigs.cn/image/61dba891ed8ee.jpg) @interface Override { }
-
1
-
2
-
3
-
4
〔1〕首先系统定义一个没有元素的标记注解 Override ,随后使用元注解 @Target 指明 Override 注解只能应用于方法之上(你可以细想想,是不是在我们实际使用这个注解的时候,只能是重写的方法,没有见过重写类或者字段的吧),使用注解 @Retention 表示当前注解只能存在源代码中,并不会出现在编译之后的 class 文件之中。
@Override protected void onResume() { super.onResume(); }
-
1
-
2
-
3
-
4
〔2〕在活动 activity 中我们可以重写 onResume() 方法,添加注解 @override 之后编译器便会去检查父类中是否存在相同方法,如果不存在便会报错。
〔3〕也许到这里你会感到很疑惑,注解到底是怎么工作的,怎么系统这样定义一个注解 Override 它就能工作了?黑魔法吗,擦擦,完成看不到实现过程嘛(泪流满面),经过查阅了一些资料(非权威)了解到,其实处理过程都编写在了编译器里面,也就是说编译器已经给我们写好了处理方法,当编译器进行检查的时候就会调用相应的处理方法。
4. 注解处理器
介绍之前,先引用 Jeremy Meyer 的一段话:如果没有用来读取注解的工具,那么注解也不会比注释更有用。使用注解的过程中,很重要的一个部分就是创建与使用注解处理器。Java SE5 扩展了反射机制的API,以帮助程序员构造这类工具。同时,它还提供了一个外部工具 apt帮助程序员解析带有注解的 java 源代码。
根据上面描述我们可以知道,注解处理器并不是一个特定格式,并不是只有继承了 AbstractProcessor 这个抽象类才叫注解处理器,凡是根据相关API 来读取注解的类或者方法都可以称为注解处理器。
1、最简单的注解处理器莫过于,直接使用反射机制的 getDeclaredMethods 方法获取类上所有方法(字段原理是一样的),再通过调用 getAnnotation 获取每个方法上的特定注解,有了注解便可以获取注解之上的元素值,方法如下:
public void getAnnoUtil(Class<?> cl) { for(Method m : cl.getDeclaredMethods()) { LogClassMessage logClassMessage = m.getAnnotation(LogClassMessage .class); if(logClassMessage != null) { int id = logClassMessage.id(); String method = logClassMessage.message(); } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
2、由于反射对性能会有一定的损耗,所以上述类型的注解处理器并不占主流,现在使用最多的还是 AbstractProcessor 自定义注解处理器,因为后者并不需要通过反射实现,效率和直接调用普通方法没有区别,这也是为什么编译期注解比运行时注解更受欢迎,但是并不是说为了性能运行期注解就不能用了,只能说不能滥用,要在性能方面给予考虑。目前主要的用到运行期注解的框架差不多都有缓存机制,只有在第一次使用时通过反射机制,当再次使用时直接从缓存中取出。好了,说着说着就跑题,我们还是来聊一下这个 AbstractProcessor 类吧,到底有何魅力让这么多人为她沉迷,方法如下(注意得在 java Moudle 下哦,android project 没有提供相关的包):
/** * Created by zmj on 2017/6/19. */ public class MyFirstProcessor extends AbstractProcessor { /** * 做一些初始化工作,注释处理工具框架调用了这个方法, * 当我们使用这个方法的时候会给我们传递一个 ProcessingEnvironment * 类型的实参。 * 如果在同一个对象多次调用此方法,则抛出IllegalStateException异常 * @param processingEnvironment 这个参数里面包含了很多工具方法 */ @Override public synchronized void init(ProcessingEnvironment processingEnvironment) { /** * 返回用来在元素上进行操作的某些工具方法的实现 */ Elements es = processingEnvironment.getElementUtils(); /** * 返回用来创建新源、类或辅助文件的Filer */ Filer filer = processingEnvironment.getFiler(); /** * 返回用来在类型上进行操作的某些实用工具方法的实现 */ Types types = processingEnvironment.getTypeUtils(); /** * 这是提供给开发者日志工具,我们可以用来报告错误和警告以及提示信息 * 注意 message 使用后并不会结束过程 * Kind 参数表示日志级别 */ Messager messager = processingEnvironment.getMessager(); messager.printMessage(Diagnostic.Kind.ERROR,"例如当默认值为空则提示一个错误"); /** * 返回任何生成的源和类文件应该符合的源版本 */ SourceVersion version = processingEnvironment.getSourceVersion(); super.init(processingEnvironment); } /** * 注解的处理逻辑 * @param set * @param roundEnvironment * @return 如果返回true 不要求后续Processor处理它们,反之,则继续执行处理 */ @Override public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) { /** * TypeElement 这表示一个类或者接口元素集合 * 常用方法不多,TypeMirror getSuperclass()返回直接超类 * * 详细介绍下 RoundEnvironment 这个类 * 常用方法: * boolean errorRaised() 如果在以前的处理round中发生错误,则返回true * Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a) * 这里的 a 即你自定义的注解class类,返回使用给定注解类型注解的元素的集合 * Set<? extends Element> getElementsAnnotatedWith(TypeElement a) * * Element 的用法: * TypeMirror asType() 返回此元素定义的类型 如int * ElementKind getKind() 返回元素的类型 如 e.getkind() = ElementKind.FIELD 字段 * boolean equals(Object obj) 如果参数表示与此元素相同的元素,则返回true * Name getSimpleName() 返回此元素的简单名称 * List<? extends Elements> getEncloseElements 返回元素直接封装的元素 * Element getEnclosingElements 返回此元素的最里层元素,如果这个元素是个字段等,则返回为类 */ return false; } /** * 指出注解处理器 处理哪种注解 * 在 jdk1.7 中,我们可以使用注解 @SupportedAnnotationTypes()代替 */ @Override public Set<String> getSupportedAnnotationTypes() { return super.getSupportedAnnotationTypes(); } /** * 指定当前注解器使用的Jdk版本 * 在 jdk1.7 中,我们可以使用注解 @SupportedSourceVersion()代替 */ @Override public SourceVersion getSupportedSourceVersion() { return super.getSupportedSourceVersion(); } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
5. 自定义运行期注解(RUNTIME)
我们在开发中经常会需要计算一个方法所要执行的时间,以此来直观的比较哪个实现方式最优,常用方法是开始结束时间相减
System.currentTimeMillis()
但是当方法多的时候,是不是减来减去都要减的怀疑人生啦,哈哈,那么下面我就来写一个运行时注解来打印方法执行的时间。
1.首先我们先定义一个注解,并给注解添加我们需要的元注解:
/** * Created by zmj on 2017/6/12. * * 这是一个计算方法执行时间的注解 * 只能作用于方法之上 * 属于运行时注解,能被VM处理,可以通过反射得到注解信息 * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface CalculateMethodRunningTime { //要计算时间的方法的名字 String methodName() default "no method to set"; }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
2.利用反射方法在程序运行时,获取被添加注解的类的信息:
/** * Created by zmj on 2017/6/12. * * 注解实现过程中所需要的工具方法 * */ public class AnnotationUtils { //使用反射通过类名获取类的相关信息 public static void getClassInfo(String className) { try { Class c = Class.forName(className); //获取所有公共的方法 Method[] methods = c.getMethods(); for(Method m : methods) { Class<CalculateMethodRunningTime> ctClass = CalculateMethodRunningTime.class; if(m.isAnnotationPresent(ctClass)){ CalculateMethodRunningTime anno = m.getAnnotation(ctClass); //当前方法包含查询时间的注解时 if(anno != null){ long beginTime = System.currentTimeMillis(); m.invoke(c.newInstance(),null); long endTime = System.currentTimeMillis(); long time = endTime - beginTime; Log.i("Tag",anno.methodName()+"方法执行所需要时间:" + time + "ms"); } } } } catch (Exception e) { e.printStackTrace(); } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
3.在 activity 中使用注解,注意咱们的注解是作用于方法之上的:
public class ActivityAnnotattion extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_anno); AnnotationUtils.getClassInfo("com.annotation.zmj.annotationtest.ActivityAnnotattion"); } @CalculateMethodRunningTime(methodName = "method1") public void method1() { long i = 100000000L; while(i > 0) { i--; } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
4.运行结果:
6. 自定义编译期注解(CLASS)
为什么我要最后说编译期注解呢,因为相对前面的自定义注解来说,编译期注解有些难度,涉及到的东西比较多,但其却是平时用到的最多的注解,因为编译期注解不存在反射,所以对性能没有影响。
本来也想用绑定 view 的例子讲解,但是现在这样的 demo 网上真是各种泛滥啊,而且还有各路大牛写的,所以我就没必要班门弄斧了。在我们的实际开发中,肯定都被跳转界面烦过,几乎每个界面都会来个:
Intent intent = new Intent (this,NextActivity.class);
startActivity (intent);
好烦人,所以本着方便就是改进的原则,让我们定义一个编译期注解,来自动生成上述的代码,想想每次需要的时候只需要一个注解就能跳转到想要跳转的界面是不是很刺激。
1.首先新建一个 android 项目,在创建两个 java module(File -> New -> new Module ->java Module),因为有的类在android项目中不支持,建完后项目结构如下:
其中 annotation 中盛放自定义的注解,annotationprocessor 中创建注解处理器并做相关处理,最后的 app 则为我们的项目。
注意:MyFirstProcessor类为上文讲解 AbstractProcessor 所建的类,可以删去,跟本项目没有关系。
2.新建后的三个工程进行依赖,注解处理器必须依赖注解 module ,而app 需要同时依赖注解 module 和 注解处理器 module,这个很好理解,这三个都是独立的,你如果不进行依赖怎么去调用。
3.编写自定义注解,这是一个应用到字段之上的注解,被注解的字段为传递的参数。
/** * 这是一个自定义的跳转传值所用到的注解 * value 表示要跳转到哪个界面activity的元素,传入那个界面的名字 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.FIELD) public @interface IntentField { String value () default " "; }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
3.自定义注解处理器,获取被注解元素的类型,进行相应的操作,方法不懂的上文应该都有解释。
/** * 这是一个自定义注解处理器 */ @AutoService(javax.annotation.processing.Processor.class) public class MyProcessot extends AbstractProcessor{ private Map<Element, List<VariableElement>> items = new HashMap<>(); private List<Generator> generators = new LinkedList<>(); /** * 做一些初始化工作 */ @Override public synchronized void init(ProcessingEnvironment processingEnvironment) { super.init(processingEnvironment); Utils.init(); generators.add(new ActivityEnterGenerator()); generators.add(new ActivityInitFieldGenerator()); } @Override public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) { //获取所有注册IntentField注解的元素 for (Element elem : roundEnvironment.getElementsAnnotatedWith(IntentField.class)) { //主要获取ElementType 是不是null,即class,interface,enum或者注解类型 if (elem.getEnclosingElement() == null) { //直接结束处理器 return true; } //如果items的key不存在,则添加一个key if (items.get(elem.getEnclosingElement()) == null) { items.put(elem.getEnclosingElement(), new LinkedList<VariableElement>()); } //我们这里的IntentField是应用在一般成员变量上的注解 if (elem.getKind() == ElementKind.FIELD) { items.get(elem.getEnclosingElement()).add((VariableElement)elem); } } List<VariableElement> variableElements; for (Map.Entry<Element, List<VariableElement>> entry : items.entrySet()) { variableElements = entry.getValue(); if (variableElements == null || variableElements.isEmpty()) { return true; } //去通过自动javapoet生成代码 for (Generator generator : generators) { generator.genetate(entry.getKey(), variableElements, processingEnv); generator.genetate(entry.getKey(), variableElements, processingEnv); } } return false; } /** * 指定当前注解器使用的Java版本 */ @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } /** * 指出注解处理器 处理哪种注解 */ @Override public Set<String> getSupportedAnnotationTypes() { Set<String> annotations = new LinkedHashSet<>(2); annotations.add(IntentField.class.getCanonicalName()); return annotations; } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
4.这是一个工具类方法,提供了本 demo 中所用到的一些方法,其实实际里面的方法都很常见,只不过做了一个封装而已。
public class Utils { private static Set<String> supportTypes = new HashSet<>(); /** * 当getIntent的时候,每种类型写的方式都不一样,所以把每种方式都添加到了Set容器中 */ static void init() { supportTypes.add(int.class.getSimpleName()); supportTypes.add(int[].class.getSimpleName()); supportTypes.add(short.class.getSimpleName()); supportTypes.add(short[].class.getSimpleName()); supportTypes.add(String.class.getSimpleName()); supportTypes.add(String[].class.getSimpleName()); supportTypes.add(boolean.class.getSimpleName()); supportTypes.add(boolean[].class.getSimpleName()); supportTypes.add(long.class.getSimpleName()); supportTypes.add(long[].class.getSimpleName()); supportTypes.add(char.class.getSimpleName()); supportTypes.add(char[].class.getSimpleName()); supportTypes.add(byte.class.getSimpleName()); supportTypes.add(byte[].class.getSimpleName()); supportTypes.add("Bundle"); } /** * 获取元素所在的包名 * @param element * @return */ public static String getPackageName(Element element) { String clazzSimpleName = element.getSimpleName().toString(); String clazzName = element.toString(); return clazzName.substring(0, clazzName.length() - clazzSimpleName.length() - 1); } /** * 判断是否是String类型或者数组或者bundle,因为这三种类型getIntent()不需要默认值 * @param typeName * @return */ public static boolean isElementNoDefaultValue(String typeName) { return (String.class.getName().equals(typeName) || typeName.contains("[]") || typeName.contains("Bundle")); } /** * 获得注解要传递参数的类型 * @param typeName 注解获取到的参数类型 * @return */ public static String getIntentTypeName(String typeName) { for (String name : supportTypes) { if (name.equals(getSimpleName(typeName))) { return name.replaceFirst(String.valueOf(name.charAt(0)), String.valueOf(name.charAt(0)).toUpperCase()) .replace("[]", "Array"); } } return ""; } /** * 获取类的的名字的字符串 * @param typeName 可以是包名字符串,也可以是类名字符串 * @return */ static String getSimpleName(String typeName) { if (typeName.contains(".")) { return typeName.substring(typeName.lastIndexOf(".") + 1, typeName.length()); }else { return typeName; } } /** * 自动生成代码 */ public static void writeToFile(String className, String packageName, MethodSpec methodSpec, ProcessingEnvironment processingEnv, ArrayList<FieldSpec> listField) { TypeSpec genedClass; if(listField == null) { genedClass = TypeSpec.classBuilder(className) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addMethod(methodSpec).build(); }else{ genedClass = TypeSpec.classBuilder(className) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addMethod(methodSpec) .addFields(listField).build(); } JavaFile javaFile = JavaFile.builder(packageName, genedClass) .build(); try { javaFile.writeTo(processingEnv.getFiler()); } catch (IOException e) { e.printStackTrace(); } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
5.自定义一个接口,目的是为了把我们需要自动生成的每个java文件的方法都独立出去,使代码更清晰。
/** * Created by zmj on 2017/6/16. * * 定义一个接口,能让每个需要自动生成代码的类都抽象出去 * */ public interface Generator { void genetate(Element typeElement , List<VariableElement> variableElements , ProcessingEnvironment processingEnv); }
-
1
-
2
-
3
-
4
-
5
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 【采购方案(lcp-28-java)】
采购方案(lcp-28-java) 小力将 N 个零件的报价存于数组 nums。小力预算为 target,假定小力仅购买两个零件,要求购买零件的花费不超过预算,请问他有多少种采购方案。 注意:答案需要以 1e9 7 (1000000007) 为底取模,如&…...
2024/4/14 17:48:16 - 聊聊测试团队在NPS变革中可以做什么
这是鼎叔的第八篇原创文章。行业大牛和刚毕业的小白,都可以进来聊聊。 欢迎关注本人专栏和微信公众号《敏捷测试转型》,大量原创思考文章陆续推出。 11月在MTSC-中国移动互联网测试开发大会,以及深圳敏捷之旅中,鼎叔分享了《提升…...
2024/4/23 6:49:36 - 迷宫问题(递归调用的回溯)
通过递归调用解决迷宫问题 什么是迷宫? 相信大家都玩在4399里玩过迷宫游戏。 如下图 图中左上角的小猫需要到达右下角小鱼干的位置游戏才算成功。 当然我们有上帝视角非常容易可以到达小鱼干的位置获得成功。 那么我们如何让电脑帮我们去解决这个问题呢ÿ…...
2024/4/14 17:48:21 - Maven笔记 [视频参考狂神说]
Maven 为什么要学习这个技术❓ 在Javaweb开发中,需要使用大量的jar包,我们手动去导入;如何能够让一个东西自动帮我导入和配置这个jar包。 由此,Maven诞生了! Maven项目架构管理工具 Maven的核心思想:约…...
2024/4/20 13:49:38 - float和double的精度和取值范围计算方法
C/C++各数据类型大小和取值范围 类型名称字节数取值范围signed char1-2^7(-128) ~ 2^7-1(127)unsigned char10 ~ 2^8-1(255)short int 或 short2-2^15(-32 768) ~ 2^15-1(32 767)unsigned short int 或 unsigned short20 ~ 2^16-1(65 535)int4-2^31(-2 147 483 648) ~ 2^31-1(2…...
2024/4/23 18:56:30 - 每天一道英文题,ICPC不自闭(3)
Codeforces Global Round 16 - B 题目翻译 二进制字符串是由字符 0 和 1 组成的字符串。 让二进制字符串的 MEX 为0、1或2中不在字符串中出现的最小数字。例如,001011 的 MEX 为 2,因为 0 和 1 在字符串中至少出现一次,1111 MEX 为 0 &…...
2024/4/18 17:29:21 - centos7.9中安装和卸载VNCServer
桌面程序已安装,退出VNCServer6.8,我用的是比较笨的办法(初学) 第一步 # cd /lib# ls ......firmware java-1.8.0 locale rpm vncfontconfig java-ext modprobe.d sendmail yum-plugins 第二步 # rm …...
2024/4/14 17:48:11 - L1-015跟奥巴马一起画正方形(python3)
思路:首先输入一个长度和一个符号,行是列的50%所以我们采用四舍五入,在遍历出符号就可以了 # 接收长和符号 length, symbol input().split( )length int(length)width round(length/2,0) # 四舍五入if 3 < length < 21:for i in…...
2024/4/7 4:06:55 - Linux内核学习9——内核多任务并发实例(下)
接上一节https://blog.csdn.net/weixin_45730790/article/details/122521234 为了在内核中模拟多任务并发访问共享链表,我们需要完成下面几个任务。 首先,需要在内核中建立一个共享链表,并使用自旋锁结构对其进行访问保护利用工作队列机制建…...
2024/4/14 17:48:06 - flutter 仿网易云音乐(2)
gitee项目地址 github项目地址 如果喜欢请点点star 这里今天说一下项目的播放器选择 查看了一下pub.dev 上主流的播放器插件主要有audioplayers和just_audio 额外提一嘴android 和 ios 的配置 android AndroidManifest.xml <manifest xmlns:android"http://s…...
2024/4/17 23:21:58 - keycloak入门搭建(上篇)
安装的话在这里就不赘述了,安装成功后进入以下控制页面。访问路径是:服务器IP:端口号/auth/ 初始只有英文,在主题那里 启用国际化,选上CN,再登录一下就可以选择中文了。 废话不多说,添加域,自己…...
2024/4/14 17:48:01 - 分享H5扫雷搭建源码修复版
亲测有效...
2024/4/14 17:48:11 - 3.7.2 显示相机位姿
这一小节有几个小问题 1. Pangolin的安装 请查看我的另一篇博客:https://blog.csdn.net/qq_39236499/article/details/122537176?spm1001.2014.3001.5501 2. 跑3.7.2的代码编译可能的报错情况 terminate called after throwing an instance of std::runtime_er…...
2024/4/14 17:48:01 - MySQL实战四十五讲笔记
第一天:SQL查询语句是如何执行 SQL可以划分成:Server层、存储引擎层次 Server层:包括连接器、分析器、优化器、执行器等(涵盖Mysql的大部分核心功能),包含内置函数等,所有跨存储引擎的功能都是在…...
2024/4/14 17:48:21 - 安装Cmder加入右键菜单快捷方式以及解决拒绝访问, ShellMenu, line494....等问题
在cmder软件目录下运行: cmder /register user 或者 cmder /register all 如果出现拒绝访问, ShellMenu, line494…这个错误 以管理员身份运行cmd 切换到cmd.exe所在文件夹 再输入 cmder /register all 就可以了...
2024/4/14 17:47:56 - 压缩和解压-Linux-学习笔记(十)
Linux上使用最多的压缩格式是 zip 和 tar.gz 。Linux上的压缩格式放在windows系统下都可以正常打开 Linux不支持 Windows下的 RAR 格式的压缩文件。Windows和Linux互通通常选择 zip gzip格式 # 仅对文件有效,对文件夹无效,压缩有文件删除,解…...
2024/4/15 13:10:27 - 【py.checkio】Grille Cipher Attack
题目:Grille Cipher Attack - python coding challenges - Py.CheckiO 代码: from typing import List import numpy as np from itertools import combinationsdef find_grille(plaintext: str, cryptogram: str) -> List[str]:# 密文输出方法同题…...
2024/4/14 17:49:11 - JN数据加载
操作 在D:\python机器学习\数据路径下添加housing.csv文件。 数据来自于:https://github.com/ageron/handson-ml2 数据文件位于:handson-ml2-master/datasets/housing/housing.csv 新建ipynb文件。 加载库 import pandas as pd 加载数据 pathD:/pyt…...
2024/4/5 5:18:02 - [工具推荐] element-ui表单设计/代码生成器
文章目录导读form-generatorform-generatorJFormDesignermxDev参考资料导读 日期: 2022-1-17 天下武功,唯快不破。写代码也是这样,在Coding业漫长的进化史中,各种框架层出不穷,程序猿们想了各种方案来帮助自己更快的完…...
2024/4/14 17:49:01 - Android 知识简记 快速回顾各种知识,相关资料参考
UDP 无连接;不可靠;无序;面向报文;速度快;轻量;适用于即时通讯、视频通话等 TCP 三次握手 A:你能听到吗? B:我能听到,你能听到吗? Aÿ…...
2024/4/14 18:08:42
最新文章
- Xamarin.Android项目使用ConstraintLayout约束布局
Xamarin.AndroidX.ConstraintLayout Xamarin.Android.Support.Constraint.Layout Xamarin.AndroidX.ConstraintLayout.Solver Xamarin.AndroidX.DataBinding.ViewBinding Xamarin.AndroidX.Legacy.Support.Core.UI Xamarin.AndroidX.Lifecycle.LiveData ![在这里插入图片描述]…...
2024/5/4 1:14:43 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - 开启 Keep-Alive 可能会导致http 请求偶发失败
大家好,我是蓝胖子,说起提高http的传输效率,很多人会开启http的Keep-Alive选项,这会http请求能够复用tcp连接,节省了握手的开销。但开启Keep-Alive真的没有问题吗?我们来细细分析下。 最大空闲时间造成请求…...
2024/5/1 13:02:34 - 阿里云弹性计算通用算力型u1实例性能评测,性价比高
阿里云服务器u1是通用算力型云服务器,CPU采用2.5 GHz主频的Intel(R) Xeon(R) Platinum处理器,ECS通用算力型u1云服务器不适用于游戏和高频交易等需要极致性能的应用场景及对业务性能一致性有强诉求的应用场景(比如业务HA场景主备机需要性能一致)…...
2024/5/1 13:48:44 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/1 17:30:59 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/2 16:16:39 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/4/29 2:29:43 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/3 23:10:03 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/4/27 17:58:04 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/4/27 14:22:49 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/4/28 1:28:33 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/4/30 9:43:09 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/4/27 17:59:30 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/2 15:04:34 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/4/28 1:34:08 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/4/26 19:03:37 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/4/29 20:46:55 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/4/30 22:21:04 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/1 4:32:01 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/4/27 23:24:42 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/4/28 5:48:52 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/4/30 9:42:22 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/2 9:07:46 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/4/30 9:42:49 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57