概述
本文通过在root的android手机中执行一个go程序,来简单记录这基本过程和过程中使用的工具。
more >>描述一对多的依赖的关系,当一个对象的状态发生变化时,所有依赖它的对象都会获得通知:
消息或者事件流动的通道,不同的组件或者模块通过这个通道获取获取和发布消息;
事件总线涉及到4个角色:
以上是事件总线的总体思想,如果我们设计一款EventBus,该考虑哪些设计呢?我觉得以下几个问题是比较核心的设计:
我看下EventBus是如何处理这些问题的(版本3.2.0),
EventvBus的订阅者通过注解实现注册,有个两个方式:
运行时加载订阅
基本思路是在register时,通过反射获取当前class的中所有使用了Subscriber注解的方法,把他们加到事件集合里;
我们重点分析注解查找方法SubscriberMethodFinder类的findUsingReflection方法
1 | // subscriberClass 就是通过EventBus.register的对象的类 |
这个里面有一个技巧需要注意,就是控制findState个数,以及在递归中使用。
编译时通过SubscriberIndex加载订阅
使用如例:
1 | @Subscribe(threadMode = ThreadMode.MAIN) |
基本实现是思路:使用注解生成器EventBusAnnotationProcessor编译时生成Subscribe的注册类。所以注册的整个过程由2个阶段构成,编译时和运行时。编译时负责收集所有了订阅的类及其类内的回调,运行时执行这些注册,并触发对应的回调。
EventBusAnnotationProcessor 负责解析注解类,收集并验证所有使用过Subscribe的方法和方法所在的类,基于收集到方法和类,生成Subscribe的注册类的java文件。
EventBusAnnotationProcessor 继承自AbstractProcessor类,AbstractProcessor类负责插入式注解处理器的注解处理过程,很多框架都使用这个技术,以后我会单独研究学习和大家分享,可以看这里简单了解。整体上这个类可以获取编译时环境,及注解的类型,使用注册的类型和方法,注解里使用方法等等,通过这个类我们基本上在编译时获取注解相关的所有信息;
需要注意的一点是,如果需要指定文件名和报名,可以在build.gradle 里做如下的声明:
1 | javaCompileOptions { |
AbstractProcessor有很多虚方法,最重要的是process,注解的处理主要通过这个方法处理。重点分析这个方法的处理流程:
这个方法有2个输入参数,annotations,指定注解类型的集合,roundEnvironment,用于查询使用指定注解类型的类型的处理器;
获取build.gradle中指定的包名,该包名是通过注解生成类的包名;
收集使用过指定注解的所有类型,并把这些数据组织成ListMap<TypeElement, ExecutableElement> list的数据;
依据上一步的list,验证注解类型的可见性,public为可见,private和protect,检查回调方法的参数类型是否是可见类和可用类;
生成代码,主要依据list做字符串拼接,文件的路径是以声明的包名目录,比如com.demo.EventBusIndex,其文件所在的位置是,代码目录/build/generated/ap_generated_sources/版本变体/out/com/demo/EventBusIndex.java
生成的文件的大概是这样的
1 | /** This class is generated by EventBus, do not edit. */ |
其中需要仔细理解的是putIndex(SubscriberInfo info),SubscriberInfo描述了包含订阅的类,及其所有的订阅方法
同时要在Application种手动的将生成的EventBusIndex类提供给EventBus
1 | EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build(); |
以上,EventBus实现了订阅者的管理和订阅的注册
每个月都有一天都会比较头疼,填写发票!每天的开发工作都要加班完成,这种琐碎的事情更不想做了,但是作为职场中,走报销是日常工作的一部分。作为写代码的手艺人,天天给客户赋能,为啥不利用技术给自己赋能呢?
忙里偷闲,搞起来吧!
描述下我们的报销流程:报销人整理票据,打印成纸质发票,打包,按照固定格式填写到google sheet上,将google sheet的链接共享给财务助理,报销人的流程就走完了;其中票据类型常用的是增值税发票,出租金发票;
这个流程中, 可以自动化的过程:票据整理,填写,发送链接。本身这最少投入,最大产出的思路分析,发送链接就是粘贴复制,自动化不够麻烦的。票据整理需要人工参与,需要考虑一种自动化的整理方式,产出数据,填写需要数据。
票据整理
填写自动化
1 | // type = 1, 五星酒店,type = 2, 航空旅费 |
整个开发历时3个半小时,经过以上的流程改造,实现了半自动化,每次填报发票能省去看发票找数字及填写过程,能省一半的时间,收益足矣。
使用shell写Android的自动构建脚本时,需要从build.gradle中读取当前的版本号,自动加1,最后写入build.gradle。其中使用到grep,sek命令,具体代码如下:
基本思路:
sed的一些技巧:
1 | gradleSrc=./ |
什么是机会?什么是运气?什么是实力?机会也是实力的一部分!
疫情的发生,让在线教育,在线办公火了,今天是开学第一天,比双十一的量大多了,绝大部分学校都是使用的在线服务,大部分的在线服务基本在崩溃与缓慢之间切换。
很多人练就了抓住机会的能力,可以当机会真的来的时候,我们是不是能够利用好机会呢。不积跬步无以至千里,同样的千里之堤毁于蚁穴,把握机会的能力是点滴积累的结果。
我们不仅要活在当下,还要心怀信念,这个信念就是机会一定会来,当下要做的所有事,就是要为那个一定来的机会夯基础,做准备!
mac升级到10.15.1,使用mac自带的归档使用工具解压zip文件时,有时会报错”错误22 - 无效的参数。“,
第一次遇到时以为是zip文件问题,后来又遇到,开始怀疑是个普遍问题。查了下资料确实普遍存在,官网帖子上很多网友在讨论这个问题,给出很多解决办法。不过亲测使用unar可以很好的解决这个问题。
1 | sudo brew install unar |
我喜欢相声。
小学初中时,听收音机,看综艺大观,唐爱国的懒汉糖葫芦是我最喜欢的相声,我们某个时候不就是那个懒汉吗,总是喜欢幻想,现实却是多么骨干。
高中时,大概2002年前后,省吃俭用,攒了5块钱,买了一盒相声大全的磁带,主要是姜昆和唐杰忠相声,里面有姜昆的虎口遐想等等,还有一个侯宝林的原声录音,这个磁带我翻来覆去的听。很多段子我都能说下来,说实话我是很喜欢姜昆和唐杰忠的相声,他们给了我那个年代的快乐。
在我大学的时候,睡前除了听中国之声的《天涯共此时》, 也开始听郭德纲的段子。MP3,MP4里面大部分是老郭的段子,那时候老郭还没有固定的“于谦”,段子的主角一般是“我”,里面的事都是自我的幻想,自我的讽刺,自我的挖苦,自我的乖张,自我的觉醒,自我的奋进,自我调侃,也不低俗,也不损人。那些段子就像是说我们自己的在学校或者刚工作时的挣扎,幻想,失落与调侃。
后来工作了也怎么听相声了,再后来,就老郭和于谦的段子了,再听就没有之前有趣,也是境地换了,老郭的段子除了笑,也没有啥了,渐渐也就不听了。
再后来就是老郭的各种八卦了,老郭其实不仅仅一个相声演员了,他更多的是个娱乐圈里的艺人了,电视,电影,综艺,没有他不参与的,这点有点像冯巩。其实我觉得也很难让他再拿出喜闻乐见的相声作品了。
作为普通观众,我觉得文艺作品一定要有情感,这样才能打动人心, 才有生命力;情感是复杂,喜怒哀乐,悲伤,失落,快乐,痛苦等等…
给我的感觉,这几年,老郭的段子只能给一类人看,就是缺”笑“的人,缺啥补啥。这类人慢慢成钢丝的主体,老郭也就越迎合他们,也就越来越没有雅俗共赏的元素了。
以理科生的科研思维和工程思路,一切都可以“公式”化,其实这里的公式化,窃以为是产业化。有商业头脑的老郭肯定知道这个,要不然,他也不会办相声培训班了。相声公式化,意在解决相声创作难的问题,我认为这是一个有效的途径,这是让相声走进专业课堂的一个途径。
这些年来,姜昆,冯巩等人都曾在相声人才的培养及相声教育上下了不少功夫,可是收效甚微,相声市场及人才还是萎靡不振。
相声产业化是老郭现在正在做的事,当年老郭以一个草根的人设,其独特的语言风格在当时算是一声春雷,惊醒了那些靠体制吃饭,靠师承糊弄观众的缺乏新意的相声们。
相声的其独特的语言特点,也让它的创新比较难,在当前网络传播快速的时代,一个包袱,甚至是包袱的思路,一经表演,就已经成为过去式,相声演员很难用一个段子一直表演,观众也不会买账。
传统的相声演员显然没有看到这种传播速度的改变,也没有看到越来越越多的挑剔的观众。观众们的审美发生了根本的变化,跟过时候,观众贪图眼前的快乐,他们很少考虑段子背后的东西。然而师承严重的体制内相声,一直沿袭着建国后相声变革后的理念,寓教于乐,使得他们在创作上的约束太多,以至于很难在把日常,世俗,市侩,市井的元素放在创作里,从而使得他们的创作源泉越发枯竭。
作为一个爱好者,我认为相声需要创新,我也不知道创新的方向在哪里,但我知道反正不应该是现在的这个样子;这种情况下,任何创新都是被容忍的,任何翻天覆地的创新都是从细微的改变而来。
以centos为例,简单介绍如何搭建git服务器。
1 | yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel |
创建一个git用户组和用户,用于运行git服务,并设置密码
1 | sudo groupadd git |
收集所有需要登录的用户的公钥,公钥位于id_rsa.pub, 把公钥导入到/home/git/.ssh/authorized_keys,如果需要创建:
1 | cd /home/git/ |
需要选定一个目录作为git仓库,比如/home/gitrepo/demo.git
1 | cd /home |
Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:
1 | chown -R git:git demo.git |
处于安全考虑,用户git禁用shell登录
1 | vi /etc/passwd |
至此,git仓库就可以使用了
1 | git clone git@192.168.1.1:/home/gitrepo/demo.git |
参考
关于nginx使用的一些基本知识和实践,持续更新。
nginx.config
nginx -t
验证配置文件/usr/local/etc/nginx/
1 | ln -s /usr/local/etc/nginx /Users/xxx/xxx |
配置
灵活使用include
常用命令
常用指令
1 | server_name www.fleven.com; |
匹配顺序
demo
1 | # 全局配置 |
关于shell使用的一些基本知识和实践,持续更新。
#! 是一种约定的写法,指示使用何种解释器;
为什么使用./xx.sh的方式执行shell文件?
./xx.sh 指定目录会让系统从指定的目录寻找可以执行的文件。如果是xx.sh,系统会从PATH中寻找可执行文件;
1 | 文件查找在很多系统中有存在,可以对比理解: |
反引号 和 $() 可以表示命令替换
1 | NPM_LOC_1=`which npm` |
= 之后有空格,可以表示命令替换
1 | a= ls ./ |
运算符和操作数之间要有空格
一般性输出使用echo,需要一定格式的可以使用printf
特殊符号
注释
1 | # 这是注释 |
1 | # 这是注释 |
变量
合法的变量名,数字,字母,下划线,不能以数字开头;
变量名和=之间不能有空格;
1 | name=`123` |
类型:字符串, 数字, 数组
1 | name='test' |
变量使用,使用${变量名},花括号可以省略,最佳实践是不要去掉花花括号;
使用readonly可以定义只读变量
删除变量
变量作用域
字符串
1 | name1='I love ' |
1 | name='I love shell!' |
1 | name='I love shell!' |
1 | name='I love shell!' |
数字
数组
1 | list=('java' 'c' 'javascript' 'c#') |
1 | list=('java' 'c' 'javascript' 'c#') |
1 | list=('java' 'c' 'javascript' 'c#') |
1 | list=('java' 'c' 'javascript' 'c#') |
1 | list=('java' 'c' 'javascript' 'c#') |
参数传递
使用$n获取传入的第n个参数
1 | echo "执行的文件名:$0"; |
基本运算符
数学运算一般使用其他命令,如expr
数学运算也可以使用如下符号
1 | a=1 |
算术运算, 加,减,乘,除,赋值,取余,相等,不等
1 | a=1 |
关系运算
只支持数字,不支持字符串
-eq
-ne
-gt
-lt
-ge
-le
1 | a=1 |
布尔运算
1 | a=1 |
逻辑运算符,使用双中括号
1 | a=1 |
字符串运算
= 两个字符串是否相等
!= 两个字符串是否不相等
-z 字符串长度是否是0
-n 字符串长度是否不为0
$ 字符串是否为空
字符串比较可以使用双中括号,双中括号提供了针对字符串比较的高级特性,使用双中括号 [[ ]] 进行字符串比较时,可以把右边的项看做一个模式,故而可以在 [[ ]] 中使用正则表达式:
1 | [[ "$script_location" != /* ]] |
1 | a="1" |
1 | a="1" |
文件测试运算
1 | file="./test.sh" |
控制流
1 | for var in item1 item2 item3 ... itmeN; do |
1 | while condition; do |
1 | case 值 in |
1 | name="apple" |
函数
1 | demofun() { |
1 | add() { |
输入输出重定向
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true