47Log

没错,就是我

  • 首页
  • 代码
  • 设计
  • 感悟
  • BUG肥猿瘦
  • 搜索

Git SubTree

发表于 2019-08-11  |  分类于 代码  |  暂无评论

Git Subtree

Subtree vs Submodule

优点

subtree 更简洁

submodule 会在项目上创建一个.gitsubmodule 文件用于管理子项目。同时在 .git 上创建 .submodule 文件。而 subtree只是在提交树上增加一个 commit,其他都没有。

subtree 操作更简单

submodule 使用上更繁琐,需要每个人都需要学会使用 submodule 命令初始化项目。
subtree 因为是直接把项目加入到当前的项目代码提交中,所以只要你 checkout 主项目就能有所有的代码。只有需要往子项目共享代码的才需要 subtree 怎么使用,不关心的人不需要知道 subtree 怎么使用

缺点

subtree 功能上没有 submodule 上丰富。对于不关心 sub 项目的人很友好,但是对于使用者来说,每次都需要加上 subtree 不是很友好,不过可以通过设置 alias来避免这个问题,不过每次都要敲 --prefix 这个也是很蛋疼。如果是 submodule 的话,我只需要进入子项目的目录,就完全好像使用 git 原本的指令即可

共同问题
都是只能把整个项目加入到当前的项目上,并不能只是加入某个目录

阅读全文 »

记一次 Debug android 编译慢的过程

发表于 2019-08-10  |  分类于 代码, 分享, 感悟  |  暂无评论

公司因为扩展业务,新建了一个 android 项目,但是这个安卓项目明明比我们的主项目代码量少那么多,但是编译时间却比我们主项目时间长非常多。让我每次编译的时候都思考人生。

项目基本情况

我们主项目是一个 80M 大小的App,dex 包都有 30M,更改一行代码的时间实际上只需要 30s 不到的时间,但是新项目 apk 大小都没有10M编译时间却要 一分多钟,有时候还需要 3分钟。

调试方法

在 gradle 4.3 版本之后,gradle 提供了一个新的方法去扫描编译过程,就是
buildScan 功能,简单一点讲就是这个东西会把task运行过程很多东西记录下来,图形化展示这些数据,让你更好的发现问题所在。

阅读全文 »

WordPress 搜索

发表于 2019-08-10  |  分类于 分享  |  暂无评论

因为自带的搜索其实不怎么样,其实最好的办法就是接入 Google 搜索,谷歌直接自定义搜索,只要把网站限定在自己站的范围,就能接入谷歌搜索。因为都是比较简单的操作,就不进行详细的记录

Google 自定义搜索

如果想点开的时候带上关键字,加上 q=xxxx 即可,和 google 是一样的

阅读全文 »

基于 GooglePlayService 的短信验证码自动填写

发表于 2019-08-10  |  分类于 分享  |  暂无评论

问题描述

如何才能不申请读取短信的权限,却又能够拿到自己发送的短信验证吗?

解决方案

在Google Play Service V2 中,谷歌提供了这样的方法。具体流程如下

  1. 获取用户电话号码
  2. 客户端启动SMS检索器(SmsRetrieverClient)
  3. 客户端将电话号码发送到您的服务器,请求下发验证码
  4. 服务端生成特定格式的短信发送给用户
  5. 手机收到短信后 GooglePlayService 使用 BroadcaseReceiver 发送给你应用
  6. 你从短信中提取 code,填写到验证码上
阅读全文 »

正则表达式教程

发表于 2019-08-05  |  分类于 分享  |  暂无评论

推荐个项目,正则表达式教程 learn-regex
个人觉得写得很不错,以下是目录,全文在这里

  • 1. 基本匹配
  • 2. 元字符
    • 2.1 点运算符 .
    • 2.2 字符集
      • 2.2.1 否定字符集
    • 2.3 重复次数
      • 2.3.1 * 号
      • 2.3.2 + 号
      • 2.3.3 ? 号
    • 2.4 {} 号
    • 2.5 (...) 特征标群
    • 2.6 | 或运算符
    • 2.7 转码特殊字符
    • 2.8 锚点
      • 2.8.1 ^ 号
      • 2.8.2 $ 号
  • 3. 简写字符集
  • 4. 零宽度断言(前后预查)
    • 4.1 ?=... 正先行断言
    • 4.2 ?!... 负先行断言
    • 4.3 ?<= ... 正后发断言
    • 4.4 ?<!... 负后发断言
  • 5. 标志
    • 5.1 忽略大小写 (Case Insensitive)
    • 5.2 全局搜索 (Global search)
    • 5.3 多行修饰符 (Multiline)
  • 额外补充
  • 贡献
  • 许可证
阅读全文 »

上传 Android aar 到 nexus 上

发表于 2019-07-27  |  分类于 代码  |  暂无评论

在新版本的Gradle 中,提供了publish这个操作,简化了整个上传的流程,详细 API在这个文档下,比如如果我需要上传 jar 到 maven上,只需要这样写

group = 'org.example'
version = '1.0'

publishing {
    publications {
        myLibrary(MavenPublication) {
            from components.java
        }
    }

    repositories {
        maven {
            name = 'myRepo'
            url = "file://${buildDir}/repo"
        }
    }
}

不过这只是Java的, Android的压根没用,所以我又找到一个插件来适配安卓的

阅读全文 »

批量下载七牛下的图片

发表于 2019-07-22  |  分类于 代码  |  暂无评论

七牛只是支持使用 qshell get 方法下载一张图片,如果想批量下载,必须配置域名。贫穷的我发了工单也没解决怎么配置域名,只能写个脚本下载所有的图片。

主要用到这两条命令

// 列出 bucket 中所有的
qshell listbucket 
// 获取单张图片
qshell get

因为我不是很熟悉shell,只能用 groovy 写个脚本,脚本如下

package com.hangox.pocketmonery

def location = new File("/Users/hangox/Downloads/qn")
def cmd = "/Users/hangox/Downloads/qn/qshell "
"$cmd listbucket wordpress".execute().text.split("\n").each { line ->
    line.split("\t")[0].find(".+(png|jpg|gif)")?.with {
        println it
        println "$cmd get wordpress $it".execute(null,location).text
    }
}

其中 location 为 qshell 的地址

阅读全文 »

NexT WP 主题修改

发表于 2019-07-21  |  分类于 代码  |  暂无评论

禁止 Markdown 编辑器

因为WP Githuber MD 已经做得足够好了,没有必要加上另外一个 MD 编辑器,固去掉。

对 functions.php 中

// Import function files
include 'functions/markdown.php';

移除
最后删除 markdown.php 就能关闭 markdown 编辑器

修复代码上换颜色的问题

原本的主题用的是 highlight.js作为代码高亮,原则上是支持 highlight.js 其他代码配置的,但是我配置之后发现应该的代码配置并没有出现,全部变成了白色,只能修改原本的 css。

首先修改

style.css

.hljs{
    background: none !important;
}
// 替换为
.hljs{

}

其实就是移除原本的颜色

然后给 pre 着色

因为 pre 实际上是加了 padding,不加 padding 的话不好看,但是加了 padding 就会多出白色出来,所以需要把 pre 设置为代码背景一样的颜色
修改 footer.php

$('pre code').each(function (i, block) {
      hljs.highlightBlock(block);
});
// 增加这个
$('pre').each(function (i, block) {
     hljs.highlightBlock(block);
});

修复有些语言着色问题

其实也不算修复,这是本来highlight.js自带的语言其实偏少,很多都需要加上,比如yaml,go,html等,我就加了以下这些

<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/groovy.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/yaml.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/dockerfile.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/dart.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/go.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/json.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/gradle.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/css.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/aspectj.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/kotlin.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/markdown.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/makefile.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/nginx.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/powershell.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/xml.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/yaml.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/swift.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/sql.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.8/languages/pgsql.min.js"></script>

在 footer.php 中 <script src="//cdn.bootcss.com/highlight.js/9.15.8/highlight.min.js"></script> 下面加入

测试环境问题

通过 docker 本地建立一个 wordpress,然后把 /var/www/html/wp-content/themes/NexT-master 映射到编辑器路径上来,最后这边每次保存都能直接看到效果。比较方便,wordpress 的启动 docker-compose 如下

version: '3.1'

services:

  wordpress:
    image: wordpress
    restart: always
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: xxxxxxx
      WORDPRESS_DB_PASSWORD: xxxxxxxxxxx
      WORDPRESS_DB_NAME: xxxxx
    volumes:
      - /Users/hangox/Desktop/MyProjects/NexT:/var/www/html/wp-content/themes/NexT-master
    networks:
      - default

networks:
  default:
    external:
      name: nginx

nginx 为本地创建的网络,wordpress 是通过 nginx 直接连接过去的

发布到服务器上

idea 有个 upload to server 功能非常好用,每次编辑完成,直接点 upload 就能直接发布过去,无需复杂的操作

配置详情


直接通过 sftp 也是 ssh 登录过去,因为我的 wordpress 是 docker 起来的,当时也没有给 /var/www/html/ 一个映射名字,所以我的路径比较长,在 var/lib/docker/volumes/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/_data/themes/NexT-master 里面,直接配置到这个里面即可

上传操作


阅读全文 »

聊聊 WordPress

发表于 2019-07-17  |  分类于 代码  |  暂无评论



为什么之前不使用 wordpress

没有找到比较好的主题,但是现在有了。其实也是 Hexo 那边迁移过来的主题,不管怎么样,反正是有了。

为什么现在又开始使用 wordpress

静态博客 hexo 等无法逃避的问题,就是需要构建才能发布。就算你配置好 gitlab runner,也要 push 上去之后才能看到。不然你就要本地配置环境了。
同样是动态博客的 ghost 也面临着一个问题,就是支持度不够,我随便一个写作软件,比如 mweb 是直接支持 wordpress 的,但是 ghost 就是不支持,要么还要自己二次开发,对于越来越少时间的自己,并不划算。

阅读全文 »

回归 WordPress

发表于 2019-07-15  |  分类于 感悟  |  暂无评论

回归 WordPress

一堆折腾之后还是回来 wordpress 了,虽然 wordpress 有很多的不好,但是也有很多的好处,支持范围广,可以直接搭建,也直接支持图片上传。
对于一个只是想写作的人来说,这些功能真的是必备够用了。

先写个占位符吧,后面更新迁移方法

阅读全文 »

设计模式之禅——6大设计原则

发表于 2017-11-08  |  分类于 分享  |  暂无评论

6个原则

  • 单一职责:有且仅有一个原因引起类的变更
  • 里氏替换:所有使用基类的地方都能无缝的使用其子类
  • 依赖倒置:所有依赖都应该依赖于抽象,细节依赖于抽象,抽象依赖于抽象,面向契约编程就是它的实现
  • 最少知识:一个对象应该对其他对象有最少了解,又名迪米特法则
  • 接口隔离:客户端不应该依赖他不需要的接口
  • 开闭原则:应该对修改关闭,对扩展开放
阅读全文 »

提速Android Gradle 构建

发表于 2017-10-31  |  分类于 代码  |  暂无评论

提速法则一览

手段 全量构建 Java增量构建 资源增量构建
升级 android gradle tools 到3.0 -15s(-25%) -10(-38%) -2.5(-16%)
避免使用遗留的Multidex -5.5s(-12%) -8(53%) same
debug 环境关闭multi-APK -4.8s(-12%) -0.5s(-6%) -3s(-26%)
设置包含最少的资源 -6s(-17%) -1.5s(-24%) -2s(21%)
关闭 png crunching -9s(-33%) same same
使用Instance Run +7s(+37%) -3s(-54%) -3s(-42%)
避免不注意的改变 - - -
不要使用动态版本号 - - -
注意分配 gradle 内存 - - -
开启 Gradle Caching -7s(-25%) same +0.5s(+12%)
使用implementation 或者 api 代替 compile - - -

以上优化方案基于android gradle tools 3.0-alpha

关于Santa Tracker Project

  • 9 个模块,包括Wear
  • 500 多个Java文件
  • 1700 个XML 文件,3500张PNG
  • Multi-dex
  • 没有 annotation processors
  • APK大小接近60MB

这个项目可以在Google Github 帐号中找到

阅读全文 »

Activity 启动模式

发表于 2017-10-25  |  分类于 代码  |  暂无评论

启动模式分为4种,分别为

  1. Standrad
  2. SingleTop
  3. SingleTask
  4. SingleIntance

Standrad

就是默认的模式,启动多少个就是多少个

SingleTop

SingleTop 需要这样理解,SingleOnTop,当栈顶是我的时候,就不再创建新的实例。
例如,ABCD,启动D,还是ABCD。如果是ABDC,启动D,最后就变成ABDCD。

SingleTask

SingleOnTask的意思,我在这个任务栈是唯一的。需要注意的是,这货启动是默认自带clearTop效果的,也就是会把在它之后的Activity都清楚掉。
例如,任务栈中有ABDC,启动D,将会变成ABD,C将会被自动推出。

SingleIntance

这个可以看做是SingleTask加强版,使用这个属性的Activity,将会被单独放在一个任务栈中,然后这个Activity在进程中都是唯一个的

阅读全文 »

Bitmap.Config 一些理解

发表于 2017-10-25  |  分类于 代码, 感悟  |  暂无评论

Bitmap Config 解析

Bitmap.Config
ALPHA_8 每个像素存储为单透明(alpha)通道。其实就是保存透明度而已
ARGB_4444 已经废弃的格式,推荐使用ARGB_8888
ARGB_8888 每个像素存储在4个Byte上,其实就是ARGB分别占用8bit的意思
HARDWARE 特殊配置,当位图只存储在图形内存中。
RGBA_F16 每个像素存储在8个Byte上,这个我不太看得懂,就是RGBA 格式保存,每一个占用16bit,F并不知道是什么意思
RGBA_F16 每个像素存储在8个Byte上,这个我不太看得懂,就是RGBA 格式保存,每一个占用16bit,F并不知道是什么意思
RGB_565 每个像素存储在2个Byte上,只有RGB通道被编码:红色以5位精度(32个可能值)存储,绿色以6位精度存储(64个可能值),蓝色存储5位精确。

位图占用内存计算

例:
选择的是ARGB_8888 分辨率为 100*100 的位图。
占用的内存应该是

100 * 100 * 4 = 40000 Byte = 39kB

总结

只要记住符号上表示的是bit就很容易计算Bitmap在内存中占用的大小了

阅读全文 »

快速配置shadowsocks主机

发表于 2017-10-23  |  分类于 代码  |  暂无评论

分为步骤

  1. 选择系统为centos7
  2. 更新kernel 为4.1 以上
  3. 开启bbr
  4. 安装docker-ce环境
  5. 使用shadowsock-docker部署ss

系统选择

各大主机提供商不太一样,这段靠自己吧

更新kernel

执行以下bash

或者直接在命令行上敲

curl -o- -L https://gist.githubusercontent.com/hangox/a9b977a9c026629101c38d5e6a2b4e76/raw/d97e16123218c068c024a12019e1a403ef47981f/update-kernel-for-centos7.sh | bash 

执行完成脚本之后将会重启系统,耐心等候重启就好了

阅读全文 »

配置 Groovy 写Android JUnit

发表于 2017-10-16  |  分类于 代码  |  暂无评论

为什么使用Groovy写JUnit

Groovy 是动态语言,动态语言干测试其实非常好用。比如,我要创建一个多种类型的数组,只要这样写def array = [12,12,'1212'] 这样我就很简单的创建了多种类型的数组了。如果是用java代码的话,你可以尝试一下需要多少行。groovy的优点不只是这些,详情请看Groovy的特性

Android中的配置方法

在Android中需要使用Groovy需要使用这个开源项目,里面有详细的配置说明。但是我按那个配置,老是编译不过,改了一下就可以了,就写下自己的办法吧。

配置buildScript


buildscript {
    
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-beta7'
        //groovy插件依赖
        classpath 'org.codehaus.groovy:groovy-android-gradle-plugin:1.2.0'

    }
}

在需要使用的项目中,加入插件

apply plugin: 'groovyx.android'


添加groovy依赖

我这里只是使用Groovy 作为测试使用,所以我是用的是testImplementation,如果要在开发中使用Groovy,请改为implementation 就可以了

dependencies {
//使用官方推荐的反而不行
//    testImplementation 'org.codehaus.groovy:groovy:2.4.11:grooid'
//我该为了java使用的Groovy就可以了
    testImplementation 'org.codehaus.groovy:groovy-all:2.4.12'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
}

开始开发

在test/groovy文件夹中建立你的Groovy 脚本,开始开发吧

示例项目

阅读全文 »

Android Studio 3.0 中支持的Java8 特性

发表于 2017-10-13  |  分类于 代码  |  暂无评论

集成方法

在Android Studio 3.0 中其实已经支持了Java8 的部分特性,其中最多人用的就是Lambda 表达式也在列。

在AS3.0中使用lambda 其实也很简单

  1. 升级Android Plugin到3.0.0-alpha1 或者以上
  2. 在build.gradle 中加入一下代码

    android {
      ...
    // Configure only for each module that uses Java 8
    // language features (either in its source code or
    // through dependencies).
    compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
    }
    }

就这样两部可以了。

如果你以前使用了jack或者me.tatarka.retrolambda,只需要移除相关的代码就可以了.

AS3.0 中java8 支持的特性和Api等级

Java 8 Language Feature 最低兼容的API等级
Lambda expressions 任意API等级。但是,只有当lambda所捕获的所有值都是可序列化的时候才支持lambda序列化。
Method References 任意API等级.
Type Annotations 任意API等级。但是,类型注释信息在编译时可用,但在运行时不可用。此外,TYPE 在API级别24及受以下,但不支持ElementType.TYPE_USE或ElementType.TYPE_PARAMETER。 
Default and static interface methods 任意API等级。
Repeating annotations 任意API等级。
Java 8 Language API 最低兼容的API等级
java.lang.annotation.Repeatable API level 24 or higher.
AnnotatedElement.getAnnotationsByType(Class) API level 24 or higher.
java.util.stream API level 24 or higher.
java.lang.FunctionalInterface API level 24 or higher.
java.lang.reflect.Method.isDefault() API level 24 or higher.
java.util.function API level 24 or higher.
阅读全文 »

清理 mac 上 docker 脚本

发表于 2017-09-30  |  分类于 小记录  |  暂无评论
#!/bin/bash


# remove exited containers:
docker ps --filter status=dead --filter status=exited -aq | xargs  docker rm -v
    
# remove unused images:
docker images --no-trunc  | awk '{ print $3 }' | xargs  docker rmi

# remove unused volumes:
find '/var/lib/docker/volumes/' -mindepth 1 -maxdepth 1 -type d | grep -vFf <(
  docker ps -aq | xargs docker inspect | jq -r '.[] | .Mounts | .[] | .Name | select(.)'
) | xargs  rm -fr

阅读全文 »

MetaWeblogApi for Hexo 开发纪录

发表于 2017-09-23  |  分类于 代码  |  暂无评论

为什么要开发MetaWeblogApi for hexo

  1. 讨厌每次都要敲命令行
  2. 想在任何地方编写文章并可以提交
  3. 喜欢编辑器沉浸式的编写体验

实现原理

participant 编辑器 as B
participant MetaWeblogApi as M
participant 博客Git地址 as A
participant 博客 as E

B->M: 发送Mardown格式的文本
note left of M: git pull 
M->B: 返回BlogId确认提交成功 
note right of M: 生成Hexo 的Markdown
M->A: 提交到
note right of M: 调用Hexo 生成
M->E: deploy 到博客地址

具体实现

外部访问Api实现部分

使用SpringBoot

  1. SpringMVC是目前Java最流行的框架
  2. Java是我本来的开发语言,趁手的才是最好的
  3. SpringBoot相对于原始的SpringMVC 更简单的配置

Metaweblog 的格式

Metaweblog的实现主要是参考这个开源项目,这个源码写得很直白,非常好懂。简单一点解释Metaweblog Api(后面简称M),和M对接的url其实只有一个,然后把访问不同的方法名封装在一个XML里面,通过解析这个xml,我们就能够知道这个请求到底需要访问什么方法。这个和我们一般的Api都不太一样,我在这个地方迷茫了好久。知道这个之后剩下的就是xml解析的问题了

使用Groovy XMLParser 解析xml

需要解析的xml

<?xml version="1.0"?>
<methodCall>
    <methodName>blogger.getUsersBlogs</methodName>
    <params>
        <param>
            <value>
                <string></string>
            </value>
        </param>
        <param>
            <value>
                <string>12</string>
            </value>
        </param>
        <param>
            <value>
                <string>12</string>
            </value>
        </param>
    </params>
</methodCall>

解析使用的groovy代码

methodCall = new XmlParser().parseText(text)
methodName = methodCall.methodName.text()
params = methodCall.params.param
mUserAccount = params[1].text()
mUserPassword = params[2].text()

使用groovy 解析的话就好像使用js一样,直接使用xml字段名就能获取到值,非常方便

Git的提交部分

JGit 是个Java实现的Git操作库,可以很方便的操作各种Git操作,我主要使用到以下几个方法

clone
mGit = Git.cloneRepository()
            .setURI(url)
            .setDirectory(new File(mGitConfig.repositoryLocation))
            .setTransportConfigCallback(mTransportConfigCallback)
            .setBranch('master')
            .setCloneSubmodules(true)
            .setTimeout(30000)
            .call()
update
def git = git()
git.pull().setTransportConfigCallback(mTransportConfigCallback).call()
git.submoduleUpdate().call()
 //如果不是干净的就合并
if (!git.status().call().clean) {
git.add().addFilepattern('.').call()          
git.commit().setMessage(buildCommitMessage(git.status().call())).call()
push
def pushResult = git().push()
                .setPushAll()
                .setTransportConfigCallback(mTransportConfigCallback)
                .call()

因为使用的giturl 提交,需要sshkey ,需要在~/.ssh/生成密钥

调用Hexo 部分

我重新拓展了groovy String 中的execute,使得每次执行命令都在博客的目录下

 String.metaClass.execute {
            if (new File(mConfigBean.repositoryLocation).exists()){
                delegate.execute(null,new File(mConfigBean.repositoryLocation))
            }else{
                delegate.execute(null,new File('/'))
            }

        }

但是我不建议这样做,这样写是方便了,但是会造成在别的地方执行execute会失败。建议是重新拓展一个方法。

因为使用groovy,我就可以这样执行hexo的命令了

初始化hexo

'npm install '.execute().text

生成和推送

'hexo generate -d'.execute()

docker封装

Docker 这个过程最蛋疼!!

  1. nodejs 要安装6版本
  2. npm不需要安装了,安装node的时候附带了

贴出构建Docker的Dockerfile

FROM java:8u111-jdk

MAINTAINER <Hangox,liang.hanguang93@gmail.com>

RUN apt-get update -y --no-install-recommends
RUN apt-get install -y --no-install-recommends git-core curl
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
RUN apt-get install -y  --no-install-recommends nodejs
RUN npm install hexo-cli -g

COPY . /app
WORKDIR /app
RUN ./gradlew assemble
RUN mv build/libs/MetaweblogApi-1.0.jar app.jar

ENV GIT_NAME HexoMetaApi
ENV GIT_EMAIL your@email.com
ENV ACCOUNT account
ENV PASSWORD password
ENV REPOSITORY ''
#
#VOLUME ["root/.ssh", "/hexo"]
#EXPOSE 9000

CMD java -jar app.jar \
        --blog.account=$ACCOUNT \
        --blog.password=$PASSWORD \
        --git.repository=$REPOSITORY \
        --git.name=$GIT_NAME \
        --git.email=$GIT_EMAIL

总结

SpringBoot 这个框架简化了很多SpringMVC的配置,搭配Groovy开发非常舒服。
Metaweblog api 的实现还在于很粗糙的程度,目前也只是实现了,newPost和editPost两个简单的操作,争取实现更多的操作。Docker构建的话,还是希望自己以后不要在智商掉线了。Docker的相关信息也是时候要总结一下了。

阅读全文 »

算法,两数之和

发表于 2017-08-12  |  分类于 代码  |  暂无评论

问题来源:two sum

问题描述

给定一个整数数组,返回两个数字的索引,使它们相加到一个特定的目标。 您可以假设每个输入都只有一个解决方案, 而您可能不会使用相同的元素两次。

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

解

正向思维解法

直接遍历所有的组合,求出问题的解

public int[] twoSum(int[] nums, int target) {
     for (int i = 0; i < nums.length; i++) {
           for (int j = i + 1; j < nums.length; j++) {
                    if (target == nums[j] + nums[i]) {
                        return new int[] { i, j };
                    }
         }
    }
    throw new IllegalArgumentException("No two sum solution");
}

分析:
这是最简单的解法。两个嵌套循环,时间复杂度为O(n2)。空间复杂度为O(1)

逆向思维解法

用目标减去加数1,得到加数2,再在数组中寻找。

实现1

public int[] twoSum(int[] nums, int target) {
        for (int i = 0; i < nums.length; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                if (target - nums[i] == nums[i]) {
                    return new int[] { i, j };
                }
            }
        }
        throw new IllegalArgumentException("No two sum solution");
    }

分析
没错,就是和第一解法时间空间复杂度都是一样的😂。没事,我们可以优化一下的。

实现2

在实现一中,我们的瓶颈主要是在如何根据值去找到索引的问题上,所以这里我们使用Map去优化根据值去寻找位置的瓶颈

public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        map.put(nums[i], i);
    }
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement) && map.get(complement) != i) {
            return new int[] { i, map.get(complement) };
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}

分析:
我们使用一个循环把数据与位置建立索引,然后获取的时候直接从map中直接获取,这样就可以避免了两个嵌套的循环了,是的时间复杂度为O(n) ,空间复杂度为O(1).

note: 在算法中,我们不考虑map这些数据结构具体实现使用的时间

实现3

实现2中使用了两个循环,能不能把第一个循环也去掉呢?答案是可以的。一边循环,一边插入map,然后获取这个差值是否已经加入到map中。

public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement)) {
            return new int[] { map.get(complement), i };
        }
        map.put(nums[i], i);
    }
    throw new IllegalArgumentException("No two sum solution");
}

分析:
这个复杂度和实现2是一样的,时间为O(n),空间为O(n),但细看还是有差别的,这个算法的实际上比实现2的快了1倍

阅读全文 »

Android Studio 3.0 Beta1 更新日志

发表于 2017-08-10  |  分类于 代码  |  暂无评论

翻译自谷歌博客

2017年8月9日,星期三

Android Studio 3.0 Beta 1现在可以在金丝雀和开发渠道中使用。

已知问题

如果您现有的Android Studio项目使用的是Android插件3.0.0的Alpha版本(如3.0.0-alpha9),则迁移到Android 3.0.0-beta1后sync your project将会遇到: Gradle project refresh failed。

解决此问题的办法就是从菜单栏中选择 Build> Clean Project - 您只需对每个项目执行一次此操作。然后,您可以通过从工具栏中单击“ Sync Project ” ,将其与Gradle对应。

此版本包含各种错误修复,包括以下内容:

修复了使用Kotlin插件崩溃的类加载问题。
修复了菜单栏不再显示的问题。(问题#63743086)

阅读全文 »

如何合法的修改Git子模块远端

发表于 2017-08-10  |  分类于 代码  |  暂无评论

首先直接修改根目录下的.gitmoudule 文件

[submodule "libraries/GaiaLibrary4BLE"]
    path = libraries/GaiaLibrary4BLE
    url = http://yousumodule_remote

然后同步设置

使用一下命令把设置同步到.git/config 文件中

git submodule synca

最后更新远端信息

使用以下命令更新远端信息

git submodule update --init --recursive --remote

其实就是从远端递归式的初始化的意思

阅读全文 »

JobScheduler 使用指南

发表于 2017-08-01  |  分类于 代码  |  暂无评论

什么是JobScheduler?

JobScheduler 是Android 5.0之后提供的后台执行操作的API。简单点描述就是可以根据一系列条件,目前包括,时间,是否在充电,ContentProvider 是否改变等条件触发工作。这是和AlarmManager最大的区别,AlarmManager 只能在一个时间启动,不能根据机子时间启动。

会在什么情况下使用呢?

  • 用户拍了一张照片的时候需要触发相应的操作,这个时候就可以监听照片的ContentProvider ,发生改变就能触发我的操作。当然,这个同样适用于所有ContentProvider
  • 固定时间唤醒进行响应的操作
  • 需要设备空闲的时候进行图片的OCR识别保存信息
  • 需要设备空闲而且在充电的时候并且连接着WIFI的时候才能图片上传到服务器
阅读全文 »

Android SpringAnimator初探

发表于 2017-07-13  |  分类于 代码  |  暂无评论

介绍

Android 官方发布了SpringAnimator ,这个动画效果其实和Facebook的rebound是一样的,但是API的设计不一样,总体来说功能更多,设计也友好。推荐使用

实现的效果

实现一个很简单的拖拽放开回弹的效果

2017-07-13-14999572451387

使用

添加依赖

新的动画库是在26.0.0 这个版本的API包上的,所以需要target 和 compileVersion 都为26 的才能使用,下面是我的项目依赖配置

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "com.hangox.springanimatortest"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    dataBinding{
        enabled true
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:26.0.0-beta2'
    compile "com.android.support:support-dynamic-animation:26.0.0-beta2"
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.hangox:xLog:1.0'
    testCompile 'junit:junit:4.12'
}

主要代码实现

 mainBinding.icon.setOnTouchListener(new View.OnTouchListener() {

            PointF mPoint = new PointF();
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                XLog.v(motionEvent);
                switch (motionEvent.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        mPoint.set(motionEvent.getRawX(),motionEvent.getRawY());
                        return true;

                    case MotionEvent.ACTION_MOVE:
                        view.setTranslationX(motionEvent.getRawX() - mPoint.x+ view.getTranslationX());
                        view.setTranslationY(motionEvent.getRawY() - mPoint.y + view.getTranslationY());
                        mPoint.set(motionEvent.getRawX(),motionEvent.getRawY());
                        return true;

                    case MotionEvent.ACTION_UP:
                        SpringAnimation springAnimationY  = new SpringAnimation(view, DynamicAnimation.TRANSLATION_Y,0);
                        SpringAnimation springAnimationX = new SpringAnimation(view,DynamicAnimation.TRANSLATION_X,0);
                        springAnimationX.start();
                        springAnimationY.start();
                        return true;

                }
                return false;
            }
        });

总结

SpringAnimator的API设计要rebound的要简洁的多,很容易写成反弹的动画。但是也和rebound 有一样的问题,代码中我是先后start两个动画。并不能像普通的Animator 那样提供一个AnimatorSet 来管理开始和结束。

阅读全文 »

材料设计之表面

发表于 2017-06-08  |  分类于 设计  |  暂无评论

可供性(affordances)

有些东西我们只需要看到就能够感受到这些东西是干嘛的。举个例子,纸张,我们无需触摸就能够知道纸张可以轻易的拿起来,可以折叠,甚至可以撕掉。苹果,我们可以扔出去,也可以咬一口。这种感觉我们称之为 可供性。这些示例帮助我们更快的了解和各种对象交互的办法。但是,在UI中模拟现实生活中的对象是非常复杂的(参考苹果拟物设计)。但是,我们仍然可以使用现实中一部分的特性来帮助我们实现可供性。

表面

在Material Design 中我们想象表面都是由一张一张的纸张组成,我们称之为平面(surface)。我们通过纸张的特性来提供可供性,表面具有一部分的纸张特性,足够我们表达组件间的关系。

/

阅读全文 »

nexus7的长宽分别是多少dp?

发表于 2017-05-31  |  分类于 代码  |  暂无评论

看看dp定义

密度无关像素 (dp)

在定义 UI 布局时应使用的虚拟像素单位,用于以密度无关方式表示布局维度 或位置。
密度无关像素等于 160 dpi 屏幕上的一个物理像素,这是 系统为“中”密度屏幕假设的基线密度。在运行时,系统 根据使用中屏幕的实际密度按需要以透明方式处理 dp 单位的任何缩放 。dp 单位转换为屏幕像素很简单: px = dp * (dpi / 160)。 例如,在 240 dpi 屏幕上,1 dp 等于 1.5 物理像素。在定义应用的 UI 时应始终使用 dp 单位 ,以确保在不同密度的屏幕上正常显示 UI

注意细节

定义中提到一个公式
\[\cfrac{px}{dp}=\cfrac{dpi}{160}\]
(命名为公式一)

我们可以理解成这样
\[\cfrac{1px}{1dp}=\cfrac{160dpi}{160}\]

阅读全文 »

setElevation 无效

发表于 2017-05-31  |  分类于 代码  |  暂无评论

检查父布局是否开启clipChildren

阴影需要把东西绘制到子布局空间以外,不开启这个无法绘制

检查background是否为透明

透明的background 哪里来的阴影不是吗

note:以下的xml表示是一个透明的布局,因为mask表示只有点击的时候才出现这个drawable

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="#FF666666">

    <item
        android:id="@android:id/mask"
        android:drawable="@drawable/bg_item_click_normal">
    </item>
</ripple>
阅读全文 »

Android Studio 3.0 新特性

发表于 2017-05-18  |  分类于 代码  |  暂无评论

Kotlin 集成

创建工程界面多了 include Kotlin Support


勾选之后后面的这个界面创建的Activity直接就是以Kotlin创建



在后续创建Activity的窗口里还能选择activity的语言



当然少不了直接把java类转换为Kotlin的这个插件啦



阅读全文 »

简化包上传到JCenter的步骤

发表于 2017-04-18  |  分类于 代码  |  暂无评论

编辑gradle.properties 文件

gradle.properties 文件有两个地方,一个在项目本身里,一个在系统里。我建议这种每次都一样的配置直接放在系统里面

#在Mac上,打开终端输入(把用户名替换成自己的)
vi /Users/用户名/.gradle/gradle.properties 

加入

#jcenter 上的用户名和api key
BINTRAY_USER=userName
BINTRAY_KEY=apikey

#开发者信息
DEVELOPER_ID=HANGOX
DEVELOPER_NAME=hangox
DEVELOPER_EMAIL=liang.hanguang93@gmail.com

退出保存即可。

编辑项目的build.gradle

加入两个插件的引用

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0'
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7'
        classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'

    }
}

编辑library 的build.gradle

在想要上传的module的build.gradle加入

ext{
    eGroup = 'com.hangox'
    eArtifactId = 'polygon-imageview'
    eName = "polygonImageView"
    eDescription = ''
    eVersion = '1.0'
    eVcsUrl = 'https://github.com/hangox/PolygonImageView.git'
    eVcsTag = 'v1.0' //git tag的名字,可以为空
    eWebsiteUrl = 'https://github.com/hangox/PolygonImageView'

}

//这一行不用的时候建议注释掉,因为国外DNS的原因,有时候会找不到dns的,导致编译失败
apply from : "https://raw.githubusercontent.com/hangox/bintray-push/v1.0/upload.gradle"

最后的项目引用将会是这样:eGroup:eArtifactId:eVersion
对于我这个项目,也就是 com.hangox:polygon-imageview:1.0

开始上传

在项目根目录下运行

#本地有安装gradle
gradle bintrayUpload

#使用项目自带的gradle

#mac
./gradlew  bintrayUpload

#win
gradlew.bat bintrayUpload

去jcenter 上点开申请

这个很多教程都有,就不说明了

感谢

gradle-publish

阅读全文 »

ownCloud部署之docker实现

发表于 2017-04-05  |  分类于 代码  |  暂无评论

ownCloud简介

ownCloud 是一个开源的云盘解决方案,用的是PHP(还不支持PHP7),性能一般也就够。支持3个数据库,本地的SQLite ,MySQL和PostgreSQL。本次部署中,将会使用MySQL。

镜像选取

ownCloud 这个解决方案比较成熟,已经有官方的docker镜像了,我们只是需要在官方的docker镜像上修改就好了。

加入Microsoft Office 文档支持

由于我的老大要求必须要支持在线预览MS文档,所以我们还需要对官方的镜像加入一些东西。具体内容就是安装libreOffice 以支持在线预览。

具体Dockerfile如下

FROM owncloud
MAINTAINER <HangoX liang.hanguang93@gmail.com>
RUN apt-get update && apt-get install -y libreoffice

由于使用的是Daocloud的stack,不支持在docker-compose 中build镜像,所以需要自己把owncloud的镜像先构建好才能在docker-compose使用

编写docker-compose.yml

带MYSQL版本:

version: '3.0'
services:
  owncloud:
    image: daocloud.io/hangox/owncloud:v9.1.4-2
    privileged: false
    restart: always
    ports:
    - 9999:80
    volumes:
    - /data/owncloud:/var/www/html
    links:
    - mysql:db

  mysql:
    image: library/mysql:5.6.35
    privileged: false
    restart: always
    ports:
    - 3306:3306
    volumes:
    - /data/mysql:/var/lib/mysql
    environment:
    - MYSQL_ROOT_PASSWORD=heygears-admin
    - MYSQL_USER=owncloud
    - MYSQL_PASSWORD=heygears-owncloud
    - MYSQL_DATABASE=owncloud


owncloud 中的镜像是我自己构建的,不公开的,需要填上自己的owncloud 镜像。
mysql 中的 端口不公开是最好的,这里公开只是为了方便外部调试而已。
mysql:db 中的db名字可以随便起,但是要记得,这个东西有大用

已有MySQL Docker容器

version: '3.0'
services:
  owncloud:
    image: daocloud.io/hangox/owncloud:v9.1.4-2
    privileged: false
    restart: always
    ports:
    - 9999:80
    volumes:
    - /data/owncloud:/var/www/html
  external_links:
    - <mysql容器名>:db


测试与访问

打开<主机ip>:9999 将会看到以下界面


这个时候mysql的网址就是刚才起的别名db了(其实在env里面是大写的,只是域名不分大小写而已😂)

阅读全文 »

文章导航

1 … 3 4 5 6
avatar

hangox

155 文章
6 分类
48 标签
RSS
友情链接
© 2019 - 2024 hangox
Powered by WordPress
Theme NexT WP