-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.xml
45 lines (45 loc) · 15.3 KB
/
index.xml
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
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>IO01 Blog</title><link>https://blog.io01.xyz/</link><description>Recent content on IO01 Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Sun, 15 Jan 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.io01.xyz/index.xml" rel="self" type="application/rss+xml"/><item><title>自建NAS方案选型-基建篇</title><link>https://blog.io01.xyz/posts/6op1/</link><pubDate>Sun, 15 Jan 2023 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/6op1/</guid><description><h2 id="前言">前言</h2>
<p>上一篇讲了在 2022 年底到 2023 年初一台性能还不错并且兼顾了兼容性的 NAS 硬件选型思路,算下来价格并不便宜,但是从兼容性和零件可替换性上还是不错的。本篇更多的是关心整体系统基建而非应用层软件。<strong>如果对 Linux 不够熟悉,直接无脑 Windows Server 什么都不用折腾。</strong></p></description></item><item><title>自建NAS方案选型-硬件篇</title><link>https://blog.io01.xyz/posts/0j3l/</link><pubDate>Fri, 13 Jan 2023 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/0j3l/</guid><description><h2 id="前言">前言</h2>
<p>之前使用的是多年前很火的威联通 453Bmini,2000 块钱 4 盘位的成品 NAS,性价比很高,开箱即用。虽然很多人认为可用性不如群晖,但是我个人的使用不喜欢依赖某一个品牌的生态,大多是开源组装的,所以对我来说威联通和群晖没什么本质区别。慢慢的用途越来越多,这款 NAS 选用的 J3455 性能低下和硬盘无法休眠实在太吵成了我的困扰,特别在理清了我本身不需要任何成品 NAS 生态的需求后,自己组装一台 NAS 成了唯一选择。</p></description></item><item><title>子线程更新 UI 全解</title><link>https://blog.io01.xyz/posts/9qg5/</link><pubDate>Thu, 06 Jan 2022 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/9qg5/</guid><description><h2 id="子线程更新-ui-异常设计理念及简单源码解析">子线程更新 UI 异常设计理念及简单源码解析</h2>
<p>初学者可能会犯在子线程更新 UI 的错误,例如:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-kotlin" data-lang="kotlin"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1</span><span>thread { imageView.setBackgroundColor(<span style="color:#50fa7b">Color</span>.RED) }
</span></span></code></pre></div><p>一旦运行,应用会直接崩溃并抛出异常,这也是我们 Android 开发的一条铁律:<em>在子线程中不能更新 UI</em>。</p>
<p>那么为什么 Android 不让子线程更新 UI 呢?原因在于现在屏幕刷新率最低是 60Hz,意味着最多每 16ms 就会刷新一次屏幕,所以 UI 更新要尽可能快速,否则会丢帧导致卡顿。那么 UI 更新操作就不能加锁,频繁的加锁释放锁可能会延长 UI 渲染时间,但是不加锁如果允许子线程更新 UI 会导致多个线程对 UI 同时更新,造成线程不安全而导致 UI 最终效果无法想象,所以 Android 直接限制了子线程更新 UI,实际上不只是 Android 有这种限制,常见的 UI 框架基本都是单线程模型。</p></description></item><item><title>使用阿里云效同步 Git 仓库到 Github</title><link>https://blog.io01.xyz/posts/hq29/</link><pubDate>Mon, 29 Nov 2021 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/hq29/</guid><description><h2 id="前言">前言</h2>
<p>有时 Github 网络的不稳定性实在令人头痛,push 总是失败,而且需要把主仓库放在 Github 而非 Gitee 等国内平台,虽然可以通过配置代理进行,不过也可以曲线救国,选择通过 push 到国内代码管理平台,然后通过 CI 平台自动推送到 Github。</p>
<p>阿里云效综合了代码仓库和 CI 平台,私有代码仓库免费,免费构建时间足够支撑我们这点小事,并且执行环境可以选香港保证了能 push 到 GitHub,所以选择了阿里云效。</p>
<p>理论上所有能通过 <code>git push</code> 触发 CI(CI 的基本操作了)并且基础环境存在 <code>git</code> 而且网络良好的平台都可以按照本文方法进行,甚至有更简单的比如 Gitlab 直接支持推送到 Github,至于本文为何没有选用 Gitlab,纯属个人偏好。</p></description></item><item><title>深入源码排查 FLAG_ACTIVITY_NEW_TASK 导致的 Activity 无法正常启动</title><link>https://blog.io01.xyz/posts/6fn7/</link><pubDate>Thu, 16 Sep 2021 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/6fn7/</guid><description><h2 id="引言">引言</h2>
<p>众所周知 Android 中 Activity 有四种启动模式,决定了是否创建新的 Activity 实例或复用当前实例。但是实际上 Activity 的启动十分复杂,不单单是 <code>android:launchMode</code> 就能决定的,多个 Intent Flag 都能改变启动的行为模式,除此之外还会根据 <code>android:taskAffinity</code> 的值来判断对应任务栈是否存在。</p></description></item><item><title>遵循 Google 应用指南的 Retrofit + Coroutine 封装</title><link>https://blog.io01.xyz/posts/2aa2/</link><pubDate>Fri, 18 Jun 2021 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/2aa2/</guid><description><h2 id="前言">前言</h2>
<p>Retrofit 从 2.6.0 以后对 Kotlin 协程提供了原生支持,使得异步请求从写法上更像同步调用,配合 Google 出的 Jetpack 全家桶可以使得网络请求更加优雅简单,而且可以完全遵循 Google 给出的应用架构指南。</p>
<p>另外我们有一个更加多样的需求:我们的应用使用了多套服务接口,每套接口返回的参数模板不同,baseUrl 则更多样化,因此带来了更复杂的封装逻辑。</p></description></item><item><title>时间格式化的趣事:YYYY 示年</title><link>https://blog.io01.xyz/posts/53aj/</link><pubDate>Thu, 27 Feb 2020 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/53aj/</guid><description><h2 id="引言">引言</h2>
<p>2019 年 12 月 29 到 31 日在格式化时间时出现了一个有趣的小 bug:比如 2019 年 12 月 31 日时间戳有可能会被格式化成:2020-12-31。</p></description></item><item><title>MD5 计算前导 0 丢失问题</title><link>https://blog.io01.xyz/posts/33dn/</link><pubDate>Mon, 20 Jan 2020 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/33dn/</guid><description><h2 id="现象">现象</h2>
<p>我们使用 Java 生成 MD5 时常用的写法如下:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1</span><span><span style="color:#8be9fd;font-style:italic">private</span> <span style="color:#8be9fd;font-style:italic">static</span> String <span style="color:#50fa7b">md5</span><span style="color:#ff79c6">(</span>String data<span style="color:#ff79c6">)</span> <span style="color:#8be9fd;font-style:italic">throws</span> NoSuchAlgorithmException <span style="color:#ff79c6">{</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2</span><span> MessageDigest md <span style="color:#ff79c6">=</span> MessageDigest<span style="color:#ff79c6">.</span><span style="color:#50fa7b">getInstance</span><span style="color:#ff79c6">(</span><span style="color:#f1fa8c">&#34;MD5&#34;</span><span style="color:#ff79c6">);</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3</span><span> md<span style="color:#ff79c6">.</span><span style="color:#50fa7b">update</span><span style="color:#ff79c6">(</span>data<span style="color:#ff79c6">.</span><span style="color:#50fa7b">getBytes</span><span style="color:#ff79c6">());</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4</span><span> <span style="color:#ff79c6">return</span> <span style="color:#ff79c6">new</span> BigInteger<span style="color:#ff79c6">(</span><span style="color:#bd93f9">1</span><span style="color:#ff79c6">,</span> md<span style="color:#ff79c6">.</span><span style="color:#50fa7b">digest</span><span style="color:#ff79c6">()).</span><span style="color:#50fa7b">toString</span><span style="color:#ff79c6">(</span><span style="color:#bd93f9">16</span><span style="color:#ff79c6">);</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5</span><span><span style="color:#ff79c6">}</span>
</span></span></code></pre></div><p>如果计算 <code>a</code> 的 MD5 会发现结果为 <code>cc175b9c0f1b6a831c399e269772661</code>,只有 31 位,正确的值应该是 <code>0cc175b9c0f1b6a831c399e269772661</code>,仔细观察可以发现我们的计算方法把第一位 <code>0</code> 丢失了。</p></description></item><item><title>从阿里规约谈起 - 包装类的值比较注意事项</title><link>https://blog.io01.xyz/posts/57fb/</link><pubDate>Fri, 29 Nov 2019 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/57fb/</guid><description><h2 id="前言">前言</h2>
<p><code>int</code>、<code>long</code> 等基本数据类型值比较可以直接使用 <code>==</code> 比较,其包装类型:<code>Integer</code>、<code>Long</code> 如果直接使用 <code>==</code> 比较大小我们会发现一个神奇的现象。当然,阿里规约也对此做出强制规定:</p>
<blockquote>
<p><strong>【强制】</strong> 所有的相同类型的包装类对象之间值的比较,全部使用 <code>equals</code> 方法比较。</p>
</blockquote></description></item><item><title>有趣的算法 - 布隆过滤器</title><link>https://blog.io01.xyz/posts/27fg/</link><pubDate>Wed, 30 Oct 2019 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/27fg/</guid><description><h2 id="引言">引言</h2>
<p>现在假设一个需求:设计一个 url 黑名单系统,需求是 1 亿个 url 黑名单,每个 url 平均长度 30 字节,判断当前的 url 是否在黑名单中。</p>
<p>我们最先想到的可能时 HashSet,如果少量的 url,HashSet 有着 O(1) 的查询效率是首选的方案。但是面对 1 亿个 url,单单存储 value 就需要 2861MB 内存,显然不可取。而如果放到硬盘上进行数据库查询,面对近 3GB 的数据库,每次匹配都要查询的话,IO 操作本身就是瓶颈。</p>
<p>所以这时候引入了布隆过滤器。</p></description></item><item><title>从阿里规约谈起 - Arrays.asList 三坑</title><link>https://blog.io01.xyz/posts/23af/</link><pubDate>Tue, 24 Sep 2019 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/23af/</guid><description><h2 id="前言">前言</h2>
<p>将数组转换成 List 是日常开发十分常见的操作,对此 JDK 提供了一个非常好用的工具类:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1</span><span>List list <span style="color:#ff79c6">=</span> Arrays<span style="color:#ff79c6">.</span><span style="color:#50fa7b">asList</span><span style="color:#ff79c6">(</span>array<span style="color:#ff79c6">);</span>
</span></span></code></pre></div><p>但是如果操纵 List 的内容的话,阿里规约会给出一个提示:</p>
<p>
<img alt="使用 asList 的问题" title="" src="https://static.fori.fun/blog/posts/static/p3c_aslist_error.png" /></p>
<p>于是深入看了下,发现 <code>Arrays.asList</code> 有三个日常开发中容易坑人的地方。</p></description></item><item><title>从阿里规约谈起 - HashMap 初始化和扩容相关</title><link>https://blog.io01.xyz/posts/6tf9/</link><pubDate>Fri, 30 Aug 2019 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/6tf9/</guid><description><h2 id="引言">引言</h2>
<p>日常开发中使用 HashMap 方法如下:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1</span><span>Map<span style="color:#ff79c6">&lt;</span>String<span style="color:#ff79c6">,</span> Object<span style="color:#ff79c6">&gt;</span> HashMap <span style="color:#ff79c6">=</span> <span style="color:#ff79c6">new</span> HashMap<span style="color:#ff79c6">&lt;&gt;();</span>
</span></span></code></pre></div><p>但是阿里规约会提示有问题:</p>
<p>
<img alt="未指定初始化容量" title="" src="https://static.fori.fun/blog/posts/static/p3c_hashmap_error.png" /></p>
<p>由此我们可以看一下 HashMap 初始化和扩容相关。</p>
<p>注:本文涉及了少许 HashMap 基础,由于与主线无关,不详讲。源码均加了些注释,注释无法解释清楚的地方放在源码之后论述。</p></description></item><item><title>从阿里规约谈起 - 禁用 Executors 创建线程池</title><link>https://blog.io01.xyz/posts/28aj/</link><pubDate>Fri, 30 Aug 2019 00:00:00 +0000</pubDate><guid>https://blog.io01.xyz/posts/28aj/</guid><description><h2 id="前言">前言</h2>
<p>Android 开发中耗时任务应该放在子线程中进行,否则会阻塞 UI 造成 ANR。但是如果直接创建子线程,阿里规约会提示:</p>
<p>
<img alt="直接使用子线程报错" title="" src="https://static.fori.fun/blog/posts/static/p3c_new_thread_error.png" /></p>
<p>关于禁止直接创建线程的原因如图,不再赘述。</p></description></item></channel></rss>