-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
229 lines (207 loc) · 29 KB
/
index.html
File metadata and controls
229 lines (207 loc) · 29 KB
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
<!DOCTYPE html><html lang="zh-Hans" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>昆明鱼 - 一条走在技术路上的小鱼儿</title><meta name="author" content="kmfish"><meta name="copyright" content="kmfish"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="记录我的技术与生活">
<meta property="og:type" content="website">
<meta property="og:title" content="昆明鱼">
<meta property="og:url" content="http://kmfish.github.io/index.html">
<meta property="og:site_name" content="昆明鱼">
<meta property="og:description" content="记录我的技术与生活">
<meta property="og:locale">
<meta property="og:image" content="http://kmfish.github.io/img/butterfly-icon.png">
<meta property="article:author" content="kmfish">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://kmfish.github.io/img/butterfly-icon.png"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://kmfish.github.io/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css"><script>
(() => {
const saveToLocal = {
set: (key, value, ttl) => {
if (!ttl) return
const expiry = Date.now() + ttl * 86400000
localStorage.setItem(key, JSON.stringify({ value, expiry }))
},
get: key => {
const itemStr = localStorage.getItem(key)
if (!itemStr) return undefined
const { value, expiry } = JSON.parse(itemStr)
if (Date.now() > expiry) {
localStorage.removeItem(key)
return undefined
}
return value
}
}
window.btf = {
saveToLocal,
getScript: (url, attr = {}) => new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
Object.entries(attr).forEach(([key, val]) => script.setAttribute(key, val))
script.onload = script.onreadystatechange = () => {
if (!script.readyState || /loaded|complete/.test(script.readyState)) resolve()
}
script.onerror = reject
document.head.appendChild(script)
}),
getCSS: (url, id) => new Promise((resolve, reject) => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = url
if (id) link.id = id
link.onload = link.onreadystatechange = () => {
if (!link.readyState || /loaded|complete/.test(link.readyState)) resolve()
}
link.onerror = reject
document.head.appendChild(link)
}),
addGlobalFn: (key, fn, name = false, parent = window) => {
if (!false && key.startsWith('pjax')) return
const globalFn = parent.globalFn || {}
globalFn[key] = globalFn[key] || {}
globalFn[key][name || Object.keys(globalFn[key]).length] = fn
parent.globalFn = globalFn
}
}
const activateDarkMode = () => {
document.documentElement.setAttribute('data-theme', 'dark')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
}
}
const activateLightMode = () => {
document.documentElement.setAttribute('data-theme', 'light')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
}
}
btf.activateDarkMode = activateDarkMode
btf.activateLightMode = activateLightMode
const theme = saveToLocal.get('theme')
theme === 'dark' ? activateDarkMode() : theme === 'light' ? activateLightMode() : null
const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
document.documentElement.classList.toggle('hide-aside', asideStatus === 'hide')
}
const detectApple = () => {
if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)) {
document.documentElement.classList.add('apple')
}
}
detectApple()
})()
</script><script>const GLOBAL_CONFIG = {
root: '/',
algolia: undefined,
localSearch: undefined,
translate: undefined,
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false,"highlightFullpage":false,"highlightMacStyle":false},
copy: {
success: 'Copy Successful',
error: 'Copy Failed',
noSupport: 'Browser Not Supported'
},
relativeDate: {
homepage: false,
post: false
},
runtime: '',
dateSuffix: {
just: 'Just now',
min: 'minutes ago',
hour: 'hours ago',
day: 'days ago',
month: 'months ago'
},
copyright: undefined,
lightbox: 'null',
Snackbar: undefined,
infinitegrid: {
js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid/dist/infinitegrid.min.js',
buttonText: 'Load More'
},
isPhotoFigcaption: false,
islazyloadPlugin: false,
isAnchor: false,
percent: {
toc: true,
rightside: false,
},
autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
title: '昆明鱼',
isHighlightShrink: false,
isToc: false,
pageType: 'home'
}</script><meta name="generator" content="Hexo 6.3.0"></head><body><div class="page" id="body-wrap"><header class="full_page" id="page-header"><nav id="nav"><span id="blog-info"><a class="nav-site-title" href="/"><span class="site-name">昆明鱼</span></a></span><div id="menus"></div></nav><div id="site-info"><h1 id="site-title">昆明鱼</h1></div><div id="scroll-down"><i class="fas fa-angle-down scroll-down-effects"></i></div></header><main class="layout" id="content-inner"><div class="recent-posts nc" id="recent-posts"><div class="recent-post-items"><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2019/07/28/clean-architecture-business-logic/" title="《Clean Architecture》读书笔记 - 业务逻辑">《Clean Architecture》读书笔记 - 业务逻辑</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2019-07-28T15:45:46.000Z" title="Created 2019-07-28 23:45:46">2019-07-28</time></span></div><div class="content">背景读了 Martin大叔的 《Clean Architecture》,对其中第20章 业务逻辑 ,记录下自己的理解。 业务逻辑 业务逻辑就是程序中那些真正用于赚钱或省钱的业务逻辑与过程。 如我做的直播类应用,用户送礼给主播,然后直播间播放礼物特效。这就是业务赚钱的一个核心逻辑。这就叫“关键业务逻辑”。这个过程中处理的一些数据,如礼物id,数量,价格,收礼对象等,就是“关键业务数据”。这两者是紧密相关的,很适合放在同一个对象中处理,这种对象就称为“业务实体(Entity)”。 业务实体 业务实体这种对象中包含了一系列用于操作关键数据的业务逻辑。这些实体对象要么直接包含关键数据,要么可以很容易地访问这些数据。业务实体的接口层则是由那些实现关键业务逻辑、操作关键数据的函数组成的。 如 频道...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2017/08/29/livedata-lifecycle/" title="LifyCycle 的思考">LifyCycle 的思考</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2017-08-28T16:46:56.000Z" title="Created 2017-08-29 00:46:56">2017-08-29</time></span></div><div class="content">LifyCycle 的思考 大纲google 的LifeCycle、 livedataglide里的 lifeCycleListener 也是一样的实现分析下原理,对比下两者。自己的组件怎么使用这个东西 Android architecture components在包 android.arch.lifecycle 包下新增了一些组件,几个核心的包括 LifeCycle, LiveData, ViewModel我们先重点关注下 LifeCycle开头的这几个。Interfaces:LifecycleObserverLifecycleOwnerLifecycleRegistryOwner Classes: 处理生命周期LifecycleLifecycle is a class that holds the information about the lifecycle state of a component (like an activity or a fragment) and allows other objects to observe this...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2017/02/25/faceclipper/" title="一个有趣的需求实现过程:人脸表情包制作">一个有趣的需求实现过程:人脸表情包制作</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2017-02-24T16:48:12.000Z" title="Created 2017-02-25 00:48:12">2017-02-25</time></span></div><div class="content">需求产品有个需求是使用用户上传的照片,自动生成目前比较火的表情包,如下图: 技术点 人脸识别,这是购买别人的SDK实现的啦 。 图像的处理,抠图、图像变换、裁剪、叠加到背景等。 实现过程简单分析了下,要实现这个效果,也有几个关键点要处理好: 图像灰度、亮度、对比度的调整 脸部区域扣取和边缘模糊 当然,如果要进一步优化下去,也有很多的细节了: 人脸方向和背景不一致,则需要调整 人脸背景色和表情背景色不一致的情况,要调整; 人脸图像大小和位置也需要调整。。。先从基础的这几个点介绍下吧。 图像效果处理这里我使用了GPUImage的滤镜,可以很方便的对原图进行处理。GPUImageGrayscaleFilter GPUImageContrastFilter GPUImageBrightnessFilter 组合使用这三个滤镜,完成灰度、对比度、亮度的调整即可。 脸部区域扣取和边缘模糊 计算脸部区域合适的Path根据识别SDK给出的人脸五官部位的特征点,来构造一个脸部五官区域的Path。这个Path的计算也经历了几个尝试,主要以两眉和嘴的坐标点来计算,最后的方案是...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2016/12/21/SqlBrite-flatMap-multiple-queryObservable-cause-duplicates/" title="通过flatmap组合多个SqlBrite的QueryObservable 使用的问题">通过flatmap组合多个SqlBrite的QueryObservable 使用的问题</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2016-12-21T11:16:18.000Z" title="Created 2016-12-21 19:16:18">2016-12-21</time></span></div><div class="content">阅读背景SqlBrite 是Square公司提供的一个数据库轻量级的封装框架。提供了RxJava的Observable风格的DB操作接口,其中一个特性是 其query操作得到的QueryObservable会一直保持对该次查询的表后续变更的事件的订阅,后续针对同一张(或多张)表的变更,均会再次发射数据给它的Subcriber,从而可以方便的实现界面的更新。 自定义的词汇含义: 订阅链、事件流: 这是指任意个Observable组合后,最终被某个Subscriber订阅时,所确定的一条订阅关系链。如: 12345 ObservableA.flatMap(ObservableB) .flatMap(ObservableC) .subscribe(new Subscriber<T>() {...} 问题背景我们最近的一个项目中使用了SqlBrite + SqlDelight框架...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2016/05/26/fix-while-loop-cpu-use-problem-md/" title="修复一例 BlockingQueue.poll 导致的线程While循环无限执行占用cpu的bug">修复一例 BlockingQueue.poll 导致的线程While循环无限执行占用cpu的bug</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2016-05-26T08:19:27.000Z" title="Created 2016-05-26 16:19:27">2016-05-26</time></span></div><div class="content">起因基于部分用户反馈使用我们的app时,玩游戏过程中会有卡顿现象出现,从而进行cpu使用率排查。 发现问题今天先操作进入一个房间后,使用android的traceview跟踪了一段2s左右的cpu使用数据,然后通过traceview对其进行分析。 如图一所示,左边列出了该时间段内的线程,右边则图形化的显示了它们的cpu使用情况。很直观的能够发现,”GroupMsgTransport”这个线程几乎一直在占用cpu,比main线程还多的多。所以首先引起怀疑。 再进一步查看详细的cpu使用情况,发现占用cpu time最多的几项都是在对一个BlockingQueue的操作,选择这些行之后,也定位到了 “GroupMsgTransport”线程。说明这条线程一直在对Queue执行poll操作。通过在代码中搜索关键字,查找到了这个罪魁祸首。 定位原因最终定位到这段问题代码: 123456789101112131415@Override public void run() { ...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2016/01/17/change-to-hexo/" title="切换到Hexo + GithubPages">切换到Hexo + GithubPages</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2016-01-17T07:02:55.000Z" title="Created 2016-01-17 15:02:55">2016-01-17</time></span></div><div class="content">博客之前用的是sina的SAE + press,也一直还不错。其实最早一开始用的是AWS的EC2,但连接速度实在太慢,才换到SAE的。然后参加活动获得了一些云豆,本以为够用蛮久的,结果最近一两个月,突然的访问把云豆都用光了。于是,就打算切换到githubpages上,昨晚在网上看了下hexo来搭建博客,看上去蛮不错的,于是就切换过来了。这次应该就不怕流量用完了,而且hexo的使用也蛮方便的,网上的各种资料也挺多,感谢这些作者,给大家带来了便利。 </div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2016/01/16/MultiTypeListViewAdapter/" title="MultiTypeListViewAdapter Android ListView 多type的Adapter封装">MultiTypeListViewAdapter Android ListView 多type的Adapter封装</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2016-01-15T16:00:00.000Z" title="Created 2016-01-16 00:00:00">2016-01-16</time></span></div><div class="content">MultiTypeListViewAdapter 是什么?MultiTypeListViewAdapter,顾名思义。其封装了多type下的Adapter的编程模式,通过对每种type统一接口,利用多态的方式,将type的实现从Adapter中抽离出来。Adapter只需面向统一接口,所以可以提供一个通用实现,实现代码不再变动。而会变动的每个type对应的item实现,则由使用者自己去实现。对扩展开放,对修改封闭。 同时,由于每个type的item均被抽离出来了。相当于复用的粒度为每个type item,可以根据需要,动态地选择合适的item去添加到adapter中。提高了代码复用,每个人编写维护好自己的item即可,避免了多人合作时都去修改Adapter,容易造成冲突。 另外,由于ViewHolder 模式的规范,MultiTypeListViewAdapter也同时封装了ViewHolder模式。常见的ListView Adapter 实现先看一下常见的ListAdapter...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2015/09/22/Can-update-view-in-background-thread/" title="android 子线程中更新界面?被ProgressBar给迷惑了">android 子线程中更新界面?被ProgressBar给迷惑了</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2015-09-22T06:51:37.000Z" title="Created 2015-09-22 14:51:37">2015-09-22</time></span></div><div class="content">在看apidemos的例子RetainedFragement时,看到在Thread中执行了 这么一句 1mProgressBar.setProgress(progress); 且执行正常,progressbar确实一直在更新。顿觉疑惑,View在更新时,会检查当前线程是否是创建view所在的线程(即UI线程),若不一致,则会抛出异常的。 in ViewRootImpl.java 中: 123456void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); ...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2015/08/31/Get-gopro-video-stream/" title="如何获取 Gopro 视频流">如何获取 Gopro 视频流</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2015-08-31T07:28:34.000Z" title="Created 2015-08-31 15:28:34">2015-08-31</time></span></div><div class="content">前言:最近的工作在研究gopro的视频流如何获取,通过搜索资料,以及对gopro app的抓包分析,得出了以下经验。这次的分析过程也体会到抓包分析的好处,以后还应进一步学习如何用好抓包工具。 如何获取Gopro的视频流以下的这些url会随gopro的型号版本而有所不同,需要自己抓包分析确定。 gopro提供了wifi和hdmi的视频输出,目前研究的是wifi输出。通过对gopro app抓包分析,和网上搜索的资料,整理出以下方法: 先通过gopro app完成和gopro的蓝牙配对,配置好wifi热点,并开启wifi热点; 手机切换至gopro的热点网络,在 udp://:8554 上开启监听。 发送http get request( http://10.5.5.9/gp/gpExec?p1=gpStreamA9&c1=restart),gopro即开始向手机的 8554 端口发送数据。手机即可在udp 8554端口收到数据。 通过抓包分析,gopro app会定期(1次/s)发送心跳请求,维持连接。udp...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2015/08/08/%E7%BB%84%E5%90%88%E8%BF%98%E6%98%AF%E7%BB%A7%E6%89%BF/" title="组合还是继承">组合还是继承</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2015-08-08T13:59:37.000Z" title="Created 2015-08-08 21:59:37">2015-08-08</time></span></div><div class="content">如题,每天在“面向对象”的我们,也常常遇到这个选择吧。刚好看书书读到这个话题,就记录下阅读的理解。 继承要慎用,其使用场合仅限于你确信使用该技术有效的情况。一个判断方法是,问一问自己是否需要从新类向基类进行向上转型。如果是必须的,则继承是必要的。反之则应该好好考虑是否需要继承。——《java编程思想 第四版》 p140 复合优于继承 与方法调用不同的是,继承打破了封装性。换句话说,子类依赖于其超类中特定功能的实现细节。 只有当子类真正是超类的子类型时,才适合用继承。换句话说,对于两个类A和B,只有当两者之间确实存在“is-a”关系的时候,类B才应该继续类A。 为了避免这种脆弱性,可以用复合和转发机制来代替继承,尤其是当存在适当的接口可以实现包装类的时候。包装类不仅比子类更健壮,而且功能也更加强大。 ——《Effective Java》 item.16 在平时工作过程中,我自己也是更多选择组合而不是继承。但也没有个明确清晰的判断标准。和同事交流时,虽然也推荐多用组合,但也说不出个具体的缘由。平时主要是开发android...</div></div></div></div><nav id="pagination"><div class="pagination"><span class="page-number current">1</span><a class="page-number" href="/page/2/#content-inner">2</a><a class="extend next" rel="next" href="/page/2/#content-inner"><i class="fas fa-chevron-right fa-fw"></i></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info text-center"><div class="avatar-img"><img src="/img/butterfly-icon.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info-name">kmfish</div><div class="author-info-description">记录我的技术与生活</div><div class="site-data"><a href="/archives/"><div class="headline">Articles</div><div class="length-num">12</div></a><a href="/tags/"><div class="headline">Tags</div><div class="length-num">7</div></a><a href="/categories/"><div class="headline">Categories</div><div class="length-num">0</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>Announcement</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>Recent Posts</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2019/07/28/clean-architecture-business-logic/" title="《Clean Architecture》读书笔记 - 业务逻辑">《Clean Architecture》读书笔记 - 业务逻辑</a><time datetime="2019-07-28T15:45:46.000Z" title="Created 2019-07-28 23:45:46">2019-07-28</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2017/08/29/livedata-lifecycle/" title="LifyCycle 的思考">LifyCycle 的思考</a><time datetime="2017-08-28T16:46:56.000Z" title="Created 2017-08-29 00:46:56">2017-08-29</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2017/02/25/faceclipper/" title="一个有趣的需求实现过程:人脸表情包制作">一个有趣的需求实现过程:人脸表情包制作</a><time datetime="2017-02-24T16:48:12.000Z" title="Created 2017-02-25 00:48:12">2017-02-25</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2016/12/21/SqlBrite-flatMap-multiple-queryObservable-cause-duplicates/" title="通过flatmap组合多个SqlBrite的QueryObservable 使用的问题">通过flatmap组合多个SqlBrite的QueryObservable 使用的问题</a><time datetime="2016-12-21T11:16:18.000Z" title="Created 2016-12-21 19:16:18">2016-12-21</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2016/05/26/fix-while-loop-cpu-use-problem-md/" title="修复一例 BlockingQueue.poll 导致的线程While循环无限执行占用cpu的bug">修复一例 BlockingQueue.poll 导致的线程While循环无限执行占用cpu的bug</a><time datetime="2016-05-26T08:19:27.000Z" title="Created 2016-05-26 16:19:27">2016-05-26</time></div></div></div></div><div class="card-widget card-tags"><div class="item-headline"><i class="fas fa-tags"></i><span>Tags</span></div><div class="card-tag-cloud"><a href="/tags/architecture/" style="font-size: 1.1em; color: #999">architecture</a> <a href="/tags/SqlBrite/" style="font-size: 1.1em; color: #999">SqlBrite</a> <a href="/tags/android/" style="font-size: 1.1em; color: #999">android</a> <a href="/tags/ListView/" style="font-size: 1.1em; color: #999">ListView</a> <a href="/tags/Android/" style="font-size: 1.1em; color: #999">Android</a> <a href="/tags/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/" style="font-size: 1.1em; color: #999">性能优化</a> <a href="/tags/RxJava/" style="font-size: 1.1em; color: #999">RxJava</a></div></div><div class="card-widget card-archives">
<div class="item-headline">
<i class="fas fa-archive"></i>
<span>Archives</span>
<a class="card-more-btn" href="/archives/"
title="View More">
<i class="fas fa-angle-right"></i>
</a>
</div>
<ul class="card-archive-list">
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2019/07/">
<span class="card-archive-list-date">
July 2019
</span>
<span class="card-archive-list-count">1</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2017/08/">
<span class="card-archive-list-date">
August 2017
</span>
<span class="card-archive-list-count">1</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2017/02/">
<span class="card-archive-list-date">
February 2017
</span>
<span class="card-archive-list-count">1</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2016/12/">
<span class="card-archive-list-date">
December 2016
</span>
<span class="card-archive-list-count">1</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2016/05/">
<span class="card-archive-list-date">
May 2016
</span>
<span class="card-archive-list-count">1</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2016/01/">
<span class="card-archive-list-date">
January 2016
</span>
<span class="card-archive-list-count">2</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2015/09/">
<span class="card-archive-list-date">
September 2015
</span>
<span class="card-archive-list-count">1</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2015/08/">
<span class="card-archive-list-date">
August 2015
</span>
<span class="card-archive-list-count">2</span>
</a>
</li>
</ul>
</div><div class="card-widget card-webinfo"><div class="item-headline"><i class="fas fa-chart-line"></i><span>Website Info</span></div><div class="webinfo"><div class="webinfo-item"><div class="item-name">Article Count :</div><div class="item-count">12</div></div><div class="webinfo-item"><div class="item-name">Unique Visitors :</div><div class="item-count" id="busuanzi_value_site_uv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">Page Views :</div><div class="item-count" id="busuanzi_value_site_pv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">Last Update :</div><div class="item-count" id="last-push-date" data-lastPushDate="2025-05-20T06:58:42.371Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">©2019 - 2025 By kmfish</div><div class="framework-info"><span>Framework </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo 6.3.0</a><span class="footer-separator">|</span><span>Theme </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly 5.3.5</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="darkmode" type="button" title="Toggle Between Light and Dark Mode"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="Toggle Between Single-column and Double-column"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="Settings"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="Back to Top"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><div class="js-pjax"></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>