Android Learning 2

今天先创建第一个app,跟的课程是google推荐的Developing Android Apps with Kotlin https://classroom.udacity.com/courses/ud9012 由于上面这个课程都是视频,所以也跟着google的kotlin android training get started补充理论知识 1. Explore Android Studio 上一篇文章已经讲过了gradle在项目中的结构,除了gradle外,其它的代码文件的分布也和java的项目类似,主要说一下其它文件夹。 res/layout android的布局文件夹,每一个Activity对应一个xml布局文件,在布局文件里面可以看到Activity的页面UI显示。 AndroidManifest.xml 一直以为是mainfest,结果是manifest(清单),列举了android系统运行app所需要的清单(Activity列表和权限)。 2. Anatomy(剖析) of Basic Android Project 下面就开始进行第一个app的开发,app叫dice roller(投色子),创建一个空项目后打开运行可以看到Hello World,就证明整个环境是通的。下面看代码。 MainActivity 首先看到的类是MainActivity,MainActivity就是Hello world这个页面的Activity。而页面的layout就是res/layout下的activity_main.xml,layout命名规则名称后置。对于Activity和layout中的xml的理解,和前端的html和js的关系类似,js处理交互逻辑,html显示页面UI,这里就是Activity处理交互逻辑,xml文件显示页面UI。 1 class MainActivity : AppCompatActivity() { ... 可以看到MainActicity继承自AppCompatActivity,AppCompatAcitvity是Activity的一个子类,兼容性和新特性都很好。 onCreate() 1 2 3 4 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } Activity不用构造器去初始化对象,而是用生命周期函数,onCreate()就是一个生命周期函数,它是Activity生命周期中的开始。 ...

<span title='2022-03-18 10:20:34 +0800 +0800'>March 18, 2022</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;YuanPeng11

Android Learning 1

2021年10月份成为兼职Android开发,之前一直没正式系统学习,现在开一个series来记录Android的学习。 Gradle 开始学习android的时候,相信gradle是大家绕不开的一个地方,因为android的环境很难调通,很多依赖下载也是状况百出。但是即使这样,很多人也是选择解决问题后就不去深究背后的原理,选择直接绕过gradle直接写项目,遂在android学习的第一章先学习gradle。 题外话,最新版的springboot已经由maven改为使用gradle来进行构建项目。 什么是Gradle gradle本质上是个打包工具,结合了ant和maven的优点(没感觉出来) https://www.zhihu.com/question/30432152 先把普通的gradle目录结构放出来,便于后面的理解。 1 2 3 4 5 6 7 8 9 root: gradle: wrapper: - gradle-wrapper.properties # 指定gradle版本号 - gradle-wrapper.jar # 安装部署gradle包 - build.gradle # 构建脚本 - settings.gradle # 指定工程名 - gradlew.bat # windows安装gradle命令 去执行jar包 - gradlew # linux安装gradle命令 去执行jar包 Gradle Wrapper(gradlew) 直到现在见到Gradle Wrapper(包装纸)也很迷惑,不知道这是什么,有什么作用。下面先从官方的解释开始看起: ...

<span title='2022-03-17 10:35:42 +0800 +0800'>March 17, 2022</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;YuanPeng11

揭秘Classpath

环境变量CLASSPATH 在安装Java环境的时候,我们需要配置PATH和CLASSPATH。 PATH:PATH比较好理解,我们在命令行需要执行某个命令的时候如python的时候,如果没有配置PATH,则需要进入python.exe所在的文件夹下,然后执行python。那配置PATH中的python所在路径,其实就相当于简化了这个过程,当配置完成后再执行python,首先去PATH中从左到右搜索所有的路径,直到搜索到python.exe,然后利用该路径执行命令,如果找不到则提示该命令不存在。 CLASSPATH:CLASSPATH其实也很好理解,这里来一段Java官方文档的解释: The CLASSPATH variable is one way to tell applications, including the JDK tools, * where to look for user classes *. (Classes that are part of the JRE, JDK platform, and extensions should be defined through other means, such as the bootstrap class path or the extensions directory.) 名如其人,classpath就是classes所在的path,那设置CLASSPATH的作用就是指定java类所在的目录,当我们执行java命令的时候,java需要去哪里找class文件呢,这时候就需要设置classpath,我们可以输出当前环境的classpath查看: * echo %CLASSPATH% * 1 .;C:\Program Files\Java\jdk1.8.0_181\lib;C:\Program Files\Java\jdk1.8.0_181\lib\tools.jar CLASSPATH的扫描同样是从左向右的。我们可以看到参数以 ; 分割,那么第一个参数 *.*指代的就是当前目录,意思是java去当前目录下寻找class文件进行执行。 Spring中的classpath 我们在很多的项目代码的config代码中都可以看到 @PropertySource(value = "classpath:map-config.yaml") 类似的代码,在这里也用到了classpath,这里的classpath什么作用呢? ...

<span title='2022-03-15 17:23:11 +0800 +0800'>March 15, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;YuanPeng11

设计模式-策略模式实战

策略模式概念 https://refactoringguru.cn/design-patterns/strategy 实战应用 背景 健康码组件对接的前端门禁设备都多种开门的方式,刷证,人脸,二维码等。对于每一种开门方式,其需要的返回结果是一样的,只是内部的处理方式不一样。所以这里使用策略模式+工厂模式来实现,通过一个入口以及不同的type来实现调用不同的实现类。具体代码如下。 代码 1. 创建一个Handler接口类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /** * @Author Yuanpeng * @Description 处理健康码请求携带参数的类 根据不同的类型进行 不同的处理 * @Date 2022/1/10 */ public interface HealthCodeHandler { /** * 处理健康码信息的逻辑 * @param query 前置信息 * @return 处理的结果 包括开门信息 健康码信息 核酸信息 疫苗信息等 */ HealthCodeResult handle(HealthCodeQuery query); /** * 获取请求的类型 1.人员唯一标识 personId 2.身份证号 3.二维码 4.人员卡号 5.人脸图片 6.市民卡 * @return 类型 */ Integer getType(); } 2. 创建不同的Handler实现类,这里以二维码的实现类举例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 /** * @Author Yuanpeng * @Description 处理二维码的实现类 * @Date 2022/1/10 */ @Service public class QrCodeHandler implements HealthCodeHandler { private static final Logger log = LoggerFactory.getLogger(QrCodeHandler.class); @Override public HealthCodeResult handle(HealthCodeQuery query) { HealthCodeResult result = ResultUtils.getDefaultHeathCodeResult(query, false); // logic code return result; } @Override public Integer getType() { return HealthCodeConstants.QR_CODE_TYPE; } 3. 将所有实现了Handler接口类的实例注入容器 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 /** * @Author Yuanpeng * @Description 策略模式的工厂类 加载所有的HealthCodeHandler类 * @Date 2022/1/10 */ @Component public class HealthCodeHandlerFactory implements InitializingBean, ApplicationContextAware { private static final Map<Integer, HealthCodeHandler> HEALTH_CODE_HANDLER_MAP = new HashMap<>(6); private ApplicationContext appContext; /** * 根据健康码信息类型获取对应的处理器 * * @param type 健康码信息类型 * @return 健康码信息类型对应的处理器 */ public HealthCodeHandler getHandler(Integer type) { return HEALTH_CODE_HANDLER_MAP.get(type); } @Override public void afterPropertiesSet() { // 将 Spring 容器中所有的 HealthCodeHandler 注册到 FORM_SUBMIT_HANDLER_MAP appContext.getBeansOfType(HealthCodeHandler.class) .values() .forEach(handler -> HEALTH_CODE_HANDLER_MAP.put(handler.getType(), handler)); } @Override public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException { appContext = applicationContext; } } 4. 入口处根据传参中的type进行不同类的调用 1 2 3 // 使用策略模式来实现对不同类型请求的处理,如果需要添加其它类型信息的处理 只需要实现相应的HealthCodeHandler即可 HealthCodeHandler handler = healthCodeHandlerFactory.getHandler(query.getCardNoType()); HealthCodeResult result = handler.handle(query); 至此,完成了业务上的需求,同时后期如果还有其它类型的开门方式,可以直接写实现类,不用改之前的代码,维护起来比较方便。 ...

<span title='2022-03-03 18:30:14 +0800 +0800'>March 3, 2022</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;YuanPeng11

Pg数据库常用SQL(持续更新)

普通操作 更新多参数SQL 1 update table_a a set (col_a, col_b) = (select b.col_a, b.col_b from table_b b where a.col_c = b.col_c) where exists (select 1 from table_b b where a.col_c = b.col_c) 分组排序 1 select * from (select *, row_number() over(partition by col_a order by col_b) rn from table_a) t where rn = 1; 分组排序删除 1 delete from table_a where id in (select id from (select id, row_number() over(partition by col_a order by col_b) rn from table_a) t where rn != 1); 系统类 查看当前所有连接,连接个数 1 2 3 4 5 6 select * from pg_stat_activity; select count(1) from pg_stat_activity; # 查询最大连接数 show max_connections;

<span title='2022-03-02 19:09:58 +0800 +0800'>March 2, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;YuanPeng11