如何正确设置阿里云 Maven 代理
之前我是这样设置的
initscript {
repositories {
maven{ url "https://maven.aliyun.com/repository/public"}
}
}
allprojects {
repositories {
maven{ url "https://maven.aliyun.com/repository/public"}
}
}
后来看了官网描述,public
只是包含 central
和 jcenter
, google
是不包含的,所以 Google
相关的我总是下载失败,我改为了下面这样
initscript {
repositories {
maven{ url "https://maven.aliyun.com/repository/public"}
maven{ url "https://maven.aliyun.com/repository/google"}
maven{ url "https://maven.aliyun.com/repository/gradle-plugin"}
}
}
allprojects {
repositories {
maven{ url "https://maven.aliyun.com/repository/public"}
maven{ url "https://maven.aliyun.com/repository/google"}
}
}
这个文件为 init.gradle
需要放在 用户/.gradle
目录下,linux
就是 ~/.gradle
Android Studio 的编译增加参数
有时候要调试一下 Android Studio 使用 Gradle
时候运行报错,需要增加调试参数,这个时候就可以在下图中
越秀配镜之旅
-
使用相机自拍而而不是使用镜子
大致挑选的时候可以使用镜子,当要实际对比的时候使用相机自拍对比。
由于我近视程度比较深,带上样式眼镜没法看清自己的样子,只能模糊看到,不能精细的对比,最好就是来个正面角度的自拍,然后带上眼镜查看。同时这样非常方便不同店铺留档查看 -
朋友要选对
带个审美要靠得住的朋友,最好是女生,主要是因为女生的一般都比较在线,同时在一个异性的角度看会好很多。 -
多选择
去不同的店多尝试,如果没有找到非常合适的,千万不能将就,眼镜算是一个大头商品,而且换的周期非常长,基本决定了你一年的样子 -
价格选择
去货源地,也就是越秀区,可以找到比较便宜的眼镜,外面几千的镜片和镜架可以做到一千多。我这个钛合金镜架加上最薄的明xxx镜片,外面不上千下不来。
Docker 网络调试工具
7. swift & kotlin 的字符串常用操作
值类型
swift
的字符串是值类型,这点和 kotlin
是不一样的,kotlin 来自于 java,所以和java 一样,是对象类型。
swift 并不是每次赋值字符串都会发生拷贝,只有新的对象发生改变的时候才会发生值拷贝
可变与不可变
swift 的 String
类型可变与不可变取决于是否可以定义的字段
let str = "test" // 不可变
var str2 = "test" // 可变
感觉很完美的继承了 swift
定义的风格
kotlin 是 Jvm 语言,所以所有的字符串都是不可变的
val str1 = "test" // str1 指向的对象不可变
var str2 = "test" // str2 指向的对象可变
因此, Swift 的 字符串可以这样操作
var str = "test"
str.append("test")
而 kotlin
是没有这样方法的,只能生成一个新的字符串赋值给新的对象
var str = "test"
str = str + "test"
当然,kotlin 直接使用 StringBuilder
就能或者一致的体验了
var str = StringBuilder("test")
str.append("test")
总得来说,swift 这个地方定义要更高一筹
6. swift & kotlin之字符串
它们字符串定义和实现都是一样的
swift 定义
let str = "我是一个串"
let str = String("我是一个串")
kotlin 定义
val str = "我是一个串"
val str = String("我是一个串")
但是其他扩展用法来说 swift 更强大,我也觉得更好用
替换字符
swift
let number = 1
let str = "我是 \(number)条狗"
kotlin
var number = 1
var str = "我是 $number 条狗"
Groovy
def number = 1
def str = "我是 $number 条狗"
typescript
const number = 1
const str = `我是 ${number} 条狗`
通过对比可以发现,天下语言大同,唯独 typescript
搞特殊。
但是这里面的使用方法我更喜欢 kotlin
和 groovy
的写法
3. swift & kotlin 的 Optional
swift
swift 中的 Optional 定义是这样的
let str : String? = nil
拆开就是这样拆开
print(str!)
同时语言级别提供几个语法糖,比如可以这样
if let myStr = str {
// 这里就不用解开了,相当于 let 给你解开了
print(myStr.count)
}
实际上的实现呢是通过系统官方的一个 Optional
类来实现的,加上 ?
号只是方便定义而已,比如一开始的代码也可以这样写
let str : Optional<String> = "112"
有没有发现这个和 Java 的 Optional 巨相识
后面的操作其实也就是隐式调用这个类的方法而已,不展开了,具体自己看源码。
kotlin
回到 kotlin
这里,kotlin 其实也有类似的定义,也不能说类似,几乎差不多,但是更强大
定义:
val str: String? = "11"
if (str != null){
// 注意这里是不需要像swift那么麻烦的,需要赋值,这里kt会自动推断,不需要自己拆包
print(str.lenght)
}
拆包:
// 嗯,kt 的拆包是两个叹号,比 swift 多一个
println(str!!.length)
高级组合拳:
kotlin 可以使用各种作用域函数进行快速的操作,这点比 swift 要强很多
根据 kotlin 的源码实现,其实 swift 其实也是可以实现这样的方法的,但是官方就是没有,我觉得很诡异
// 通过这个方式,就能直接把一个可选的值变成非空的it,然后进行操作,这边要比 swfit 强
str?.let{ println(it) }
而且这样的快速操作方法,kotlin 有五个,分别是 let
,run
,with
,apply
和 also
。
takeIf
和takeUnless
不属于这个类别
typescript
作为前端的希望,不好意思,它没有这个东西😀
9月是个好月份
原版
- 9.2 Nvidia RX30x0 显卡发布,4k游戏可及
- 9.3 Intel正式发布了代号Tiger Lake的第11代低功耗酷睿处理器,牙膏挤爆
- 9.9 Galaxy Z Fold2 5G 国内发布
- 9.9 android 11 正式发布,同月各大国内厂商将会推送,所以要适配了
- 9.15 苹果秋季发布会
- 9.26 楼下喜茶要开了[狗头]
苹果版本
- ✅ 9.2 Nvidia RX30x0 显卡发布,4k游戏可及
- ✅ 9.3 Intel正式发布了代号Tiger Lake的第11代低功耗酷睿处理器,牙膏挤爆
- ✅ 9.9 Galaxy Z Fold2 5G 国内发布
- ✅ 9.9 android 11 正式发布,同月各大国内厂商将会推送
- ☑️ 9.15 苹果秋季发布会
- ☑️ 9.26 楼下喜茶要开了[狗头]
欢迎补充[狗头]
4. swift & kotlin 元组
对于 swift 来说,这就是个系统帮你快速创建的类,主要你想打包几个字段的时候非常好用,也用不着为了打包定义几个类。
定义代码如下
let error = (1,"你就是错了",1,1,22,3,3,3,3,3)
print(error)
这个元祖里面是不限制数量,同时也支持给字段命名
let error = (code: 1, message: "错了就是错了")
print(error)
//output (code: 1, message: "你的名字")
支持打包当然也直接拆包
let error = (code: 1, message: "错了就是错了")
let (code , message) = error
print("code : \(code),message \(message)")
//out code : 1, message 错了就是错了
这货在 kotlin 里面也有,但是没有那么强大
val error = Pair(1,"错了就是错了")
val error2 = Triple(1, "错了就是错了","我是第三个")
println("first : ${error.first}, second : ${error.second}")
println(error)
// output
// first : 1, second : 错了就是错了
// (1, 错了就是错了)
kotlin 是通过 Pair
和 Triple
这两个类实现的,是需要手动调用,而且目前最多支持 3 个,不支持命名字段,在我看来就是有语言加成的类,当然它也支持解包
val (code,message) = error
println("code : $code, message : $message")
但是和 swift 不同的是,kotlin 中元组的值是一定不可变的,比如 swfit 中
var error = (code: 1, message: "错了就是错了")
error.code = 1
这样是没问题的,但是 kotlin 因为本质就是个类,它的定义决定了是不能变的
public data class Pair<out A, out B>(
public val first: A,
public val second: B
)
所以这样操作是不行
var error = Pair(1, "错了就是错了")
error.first = 1
总结就是,苹果爸爸技高一筹,kotlin 因为要兼容 Java 语言做了很多妥协
5. swift & kotlin Optional 的用途
用了 optional 是不是不会为空呢?
这个显然不用问的,肯定是能够为空的,难道程序还能拦住人不成?
比如这样的代码
func jump(str : String){}
jump(nil!) // 我这样写你能奈我何?
那么这个东西的用处是什么?
声明不为空
为了明确各自的边界
比如 Java 的一个方法
void jump(String name){
if(name.lenght != 0){
// do
}
}
如果外部传入空值怎么办?
第一波尝试,增加 NouNull
注解
void jump(@NouNull String name){
if(name.lenght != 0){
// do
}
}
但是注解只是编译提醒,人家不看编译提醒还是传了空怎么办?
那就第二波修改,null 检查
void jump(@NouNull String name){
if (name == null){
throw new IllegalArgumentException("参数不能为空");
}
if (name.lenght != 0){
// do
}
}
第二波修改明显就能够防止问题的,但是如果让你每个方法都这样写一遍,是不是感觉很累?
kotlin 简化了这种写法
fun jump(name: String) {
if(name.isNotEmpty()){
//do
}
}
当你尝试这样调用的时候 jump(null)
会编译直接报错,因为这里声明的不是可选类型,不能为空。
如果你这样写 jump(null!!)
那就会运行时候报错,自动检查空
swift 也是一样
func jump(name: String) {
if ( name.lenght != 0){
//do
}
}
减少判空的噪音
同样的java代码,要判空需要这样写
void jump(String name){
if(name != null && name.lenght != 0){
// do
}
}
但是 kotlin 只需要这样
fun jump(name: String?){
if(name?.lenght != 0){
// do
}
}
swift 也是这样
func jump(name: String?){
if(name?.lenght != 0){
// do
}
}
其实我觉得最方便的时候是有个类需要接受一个 callback
。
这个 callback
是可以为空的,然后你就需要每个使用的地方都加个空判断,就比如下面这样的代码
class PushManager{
private PushCallback pushCallback;
private void onPush(){
if(pushCallback != null){
pushCallback.onGetPushData();
}
}
}
但是如果换成 kotlin 编写的话就非常愉悦了
class PushManager{
private var pushCallback : PushCallback?;
private onPush() {
pushCallback?.onGetPushData();
}
}
简直和不用写判空一样,这样减少了很多代码噪音,让开发人员更加专注于编写代码本身
2. swift & kotlin 变量可变与不可变
两边都有可变和和不可变的定义就是名字不太一样
swift 是这样
let 不变 = 1
var 可变 = 1
kotlin 是这样
val 不可变 = 1
var 可变 = 1
其实就是对应 Java 的
final int 不可变 = 1;
int 可变 = 1;
因为平常开发中不可变用的其实比较多,java 这个天天敲 final
的确让人受不了,kotlin 简写这个还是挺好的
这里插一下别的语言
typescript
是这样
const 不可变 = 1
var 可变 = 1
就你不一样?作为现代语言能不能统一一下????
1. swift & kotlin数据类型
基本数据类型
类型 | 大小(字节数) | 区间值(自己算,不写) |
---|---|---|
Int8 | 1 | |
UInt8 | 1 | |
Int32 | 4 | |
Int64 | 8 | |
UInt32 | 4 | |
UInt64 | 8 | |
Float | 4 | |
Double | 8 |
无符号类型 kt 其实也有,只不过在1.4版本的实验特性上
Int 类型和 Kotlin 不一样的,Int类型 Swift 是根据平台来的,这点和 C 倒是挺像的,Kotlin 是JVM语言,就是表示这货不同平台都是那么多位的,我觉得这个设计比Swift更好
Bool 类型
其实就是 true
or false
,别说 kt,java 都用几百年了
let isMy: bool = false
if(isMy){
print("你的")
}else{
print("我的")
}
kotlin 实现其实也差不多,就是名字不太一样,人家是boolean
val isMy: Boolean = false
if (isMy) {
print("你的")
} else {
print("我的")
}
类型别名
typealias AudioSimple = Int
let b : AudioSimple = 1
kotlin 是把这个代码把 let
改为 val
放到 kotlin 直接就可以运行,毫无违和感
typealias AudioSimple = Int
val b : AudioSimple = 1
如何移除 gradle 远程依赖中多余的 package
The exclude method of the configuration closure for a dependency excludes transitive dependencies. So, if your module dependency depends on other modules, you can exclude them from your build. You can check out the transitive dependencies of the 'com.facebook.android:facebook-android-sdk:4.14.0' module on its Maven repository info page.
If the BundleJSONConverter class exists in a transitive dependency, you can exclude the specific module in the same way you are trying now. Just specify the group, the module and the version, like you do for dependencies.
If you just want to exclude one class for a dependency jar, take a look at the jar jar links tool and its Gradle plugin. It allows you to alter included jars, e.g. to change packages or remove classes.
The following (shortened) example shows the usage of the plugin and some methods to alter the dependency jar:
apply plugin: 'org.anarres.jarjar'
compile jarjar.repackage {
from 'org.apache.hive:hive-exec:0.13.0.2.1.5.0-695'
archiveBypass "commons*.jar"
archiveExclude "slf4j*.jar"
classDelete "org.apache.thrift.**"
classRename 'org.json.**', 'org.anarres.hive.json.@1'
}
找不到androidx.databinding.DataBindingComponent的类文件
databinding 新的特性导致的,需要在 gradle.properties 手动关闭增量编译
android.enableExperimentalFeatureDatabinding=false
禁止 macOS 的更新提示
终端中敲入
sudo softwareupdate --ignore "macOS Catalina"
如果需要开启则通过这个
sudo softwareupdate --reset-ignored
本地搭建代理代理 v2ray 协议猜想
用途
因为每个人配置v2ray 其实比较麻烦,如果每个人直接使用 proxy-switchyomega
这个插件就会简单很多。目标是实现所有人简单的上网。
部署条件
- 需要有公网IP
- 内网需要有一台机器跑 v2ray 和 nginx
拓扑图
描述
- 用户通过
proxy-switchyomega
设置https
代理 - 本地由
caddy
或者nginx
接受到代理,直接代理到本地的v2ray
上的 http 协议
一定是要 https 代理,这样才能保护数据和账号密码
本地代理可以增加路径认证,因为https是抓不到路径的,所以路径上加账号密码即可
发现一个官方的布局异步加载
Gitlab Ci 的 CI_DEBUG_TRACE
这个东西的作用是在 GitlabCi
的日志输出界面输出更多用于方便调试的日志。
官方建议是写在 .gitlab.yml
上, 如下
variable:
CI_DEBUG_TRACE: true
这样就会导致一个问题,每次当你想要调试的时候,你都要提交一个代码把这个东西打开,这样有点蛋疼。
后面我发现https://gitlab.com/{namespace}/{project}/-/settings/ci_cd
这个地方的也是可以设置Variable
的。实验了以下,这个地方也是有效的,只要在这里
填上这个 CI_DEBUG_TRACE
就能直接显示所有调试内容了,这样做就不需要每次都提交代码才能显示调试的内容。
这货有个小缺点,就是所有的
ci/cd
都会生效
Groovy 输出命令信息到控制台
如果直接用以下这个
pngquantCmd.consumeProcessOutput(System.out, System.err)
会创建一个线程执行命令,命令行会跳过。
如果使用下面这个
pngquantCmd.waitForProcessOutput(System.out, System.err)
就会等到执行完成执行下一句,平常应该使用下面这个
mac 中快速使用 Android Studio 打开某个目录
效果图
升级到 AngularCli9 后 ngx/cache 不能运行问题
关键字
"Can't resolve all parameters for MemoryCacheService"
"Can't resolve all parameters for LocalStorageService"
问题描述
升级到 AngularCli 9 之后 ngx-cache
模块加入后,运行会出现上述问题
解决方案
注入方式由
{ provide: CACHE, useClass: (MemoryCacheService) }
改为
{ provide: CACHE, useClass: (MemoryCacheService), deps: [PLATFORM_ID] }
其实就是增加了 PLATFORM_ID
作为参数
Portainer 添加 endPoint
portainer 添加 endpoint 有两种方式
- 直接连接到对应的 portainer agent
- 使用 edge agent 代理连接
直连模式
使用这个模式,需要机器有公开的 9000
端口(非9000也可以,自己改),然后 portainer 会直接尝试连接机器上的 portainer agent
。
这个模式下,可以获得 portainer 所有功能
代理模式
这个模式下,是在机器上部署一个 edge 代理,然后这个代理自己连接到 portainer
上。这个模式就不需要机器公开任何接口,会方便不少。
但是目前发现一个功能不能使用,就是下图中的 ServiceHook
这个功能对于 ci/cd
继承自动化发布来说很好用,要是用不到可以无视。
注意点
建议都使用 swarm 模式,不然 stack 只能支持到 version 2 版本,conf 和 serect 功能也不能使用。
小结
优先使用 agent
模式,如果不能暴露端口,比如家里网络,就要使用 edge agent
模式
使用 Docker Swarm 搭建 WordPress
起因
我曾经把 wordpress 搭建在 Vultr
上,但是因为众所周知的原因,这个地方访问越来越慢。再后来我选择了新浪云,新浪云的确够便宜,也很不错,但是要备案,还有评论功能估计要阉割,想想还是算了,找个香港的主机搭建 wordpress 即可。
购买主机
我这里选择的是阿里云的轻量应用服务器,这个主机的好处就是便宜,够用。
比如我选择的香港的主机,一个月只需要 24 块钱,一核心一G内存,网速为 30Mbps,磁盘空间 25GB,月流量 1TB。
配置如下图
初始化 docker 环境
虽然上面有一件安装
wordpress
的功能,但是我不推荐,因为配置都太老了
最终我选择的是 ubuntu18.04
系统,直接用下面的命令即可完成安装 docker 并且初始化 docker swarm
curl -o- -L https://gist.githubusercontent.com/hangox/e679464f35dc2a78920e6249a21d7958/raw/c5541e38979dca1e3e1e9704ad171ed2f0556fa1/ubunut-install-docker.sh | bash
发现搭建一个暗网其实很简单
- 搭建一个或者云服务商买租用一个 discuz 论坛
- 增加一个 robot.txt 协议,写上 "Disallow: /"
- 然后改为邀请码才能注册
- 然后把主题改为黑色😊
大部分认为暗网其实就是这样,不能被搜索引擎搜录,一般人不能进入,主题还是黑色的,完美
Homebrew 安装软件后路径配置
所有 Homebrew
安装的软件其实都会在 /usr/local/opt/
这个地方创建一个软应用,指向的都是当前命令使用的软件版本,比如我虽然安装了两个 git
,一个24版本,一个26版本,命令行可以使用的是26版本 ,所以这个路径 /usr/local/opt/git/bin/git
的版本就是 26 版本。
这种目录最常见用于配置 IDE 各种环境的路径,比如说 git
相较于以前直接配置到具体版本的路径上,每次升级都要改,这个要方便不少。
Docker Swarm Volume 问题记录
Docker Swarm 或者 Docker Compose 部署的容器有个问题,如果你使用的是 Docker 自动创建的 Volume ,也就是这种方式
version: '3'
services:
caddy:
image: jayfong/caddy-dnspod
environment:
volumes:
# Caddy 自动生成的 SSL 证书
- certs:/caddy/certs
ports:
- 2015:2015
restart: unless-stopped
volumes:
certs:
这个 Volume 最终的名字是 caddy-home_cert
,因为我指定的 docker stack 名字为 caddy-home, 如果你下次更新,就必须要指定一样的名字,不然是不能到达一样的文件目录的。如果确实不能弄成一样的名字,又不想挪动文件,其实还是有办法的,可以尝试这样写
volumes:
certs:
external: true
这样 docker
就不会尝试创建 certs
了 ,但是注意的是,这个东西需要提前创建好,不然是会服务部署失败的
禁止通知mac dock弹跳
# 不弹跳开启
defaults write com.apple.dock no-bouncing -bool TRUE
# 不弹跳关闭
defaults write com.apple.dock no-bouncing -bool FALSE
ubuntu 机器快速配置 Docker
这个脚本会安装 docker 并开启 docker swarm
curl -o- -L https://gist.githubusercontent.com/hangox/e679464f35dc2a78920e6249a21d7958/raw/c5541e38979dca1e3e1e9704ad171ed2f0556fa1/ubunut-install-docker.sh | bash
电脑升级到i9-9900K感受
今年年初,我把我电脑从 i5-7400 升级到 i9-9900K,也就是从 4 核心 4 线程最高 3.6 主频的 U 升级到 8 核心 16 线程最高主频 5.0 主频的U。
我把 i9 超频到全核心 5.0G
在工作中也用了一个多月了,说说我在使用的过程中感受到的提升吧,我其实经常进行 App 的打包去验证问题,我就以这个场景说明一下问题
运行命令
/gradlew clean
/gradlew :cc-start:assembleDebug --no-build-cache
新电脑用时
旧电脑用时
差了 42秒,别看这 42秒不重要,有时候验证一个问题,都是需要清洁构建,我曾经试过验证一个问题一天需要构建十几次,能省下不少时间。同时,因为打包并不能把新U所有的性能压榨出来,这个时候我是可以做别的工作的,但是旧的U是已经完全卡死了
接着我运行了更吃 CPU 的打包场景