老爹,我要上京考武状元。
儿子,我们苏察哈尔家等你这句话等了整整20年了!
错,我是为一个女人。
好!为女死为女亡,为女去考状元郎!英雄!敢问是谁家女子?
怡红院如霜姑娘。
啊?!妓!!
有何不妥?
敢爱人之所不敢爱,品味与众不同,老爹我佩服你!
我自横刀向天笑
Android 2.2
Android 4.4
Android 5.0
Android 7.0
Bitmap 的发小氛围 Bitmap 对象大小和像素大小
Fresco
Glide
AsyncTask 内部由两个线程和一个 Handler 实现的,Handler 用于将信息切换到主线程,两个线程池一个用于排队,一个用于执行。AsyncTask.execute(),传入一个 FutureTask 的对象。Android 3.0 之前是并行,3.0以后是串行
继承于 Thread,在 run 函数中,创建了 Looper 对象
内部实现了 HandlerThread 和 Handler,可以执行性耗时操作,因为它是一个 Service,所以它的优先级比其他 Thread 要高很多
项目需要添加文件下载的功能,一开始想要用 FileDownLoader,后来再 github 上看到作者基于 FileDownloader 改版了一个 FileDownloader2,即 OkDownload 。看作者的意思 OKDownLoad 的存在是因为 FileDownloader 不方便进行单元测试,另一个原因是核心代码过于臃肿复杂,基于这些原因,才有了 OKDownload。OkDownload是一款多线程断点续传下载引擎,它的功能完整,性能高,可配置性高,可以注入自定义组件来修改下载策略、替换网络请求框架等等。
原文地址:https://blog.csdn.net/qq_21138819/article/details/89025776
MaterialEditText 智能提醒输入框
android-edittext-validator 输入效验、提醒
ClearEditText 带删除的输入框
PasswordEditText 显示/隐藏密码
MaterialSearchView 一个基于Material design 规范的Android 搜索控件。MaterialSearchView显示在Toolbar 或者 ActionBar 上面,并为用户显示一个最近搜索或者搜索提示的列表。
CircleImageView 圆形图片
android-gif-drawable 展示gif
android-shape-imageview 自定义形状的ImageView
PaletteImageView 懂得智能配色的ImageView,还能给自己设置多彩的阴影哦。
PhotoView 支持双击或双指缩放的 ImageView
subsampling-scale-image-view 支持放大、缩小
ShadowImageView 可以根据图片内容变阴影颜色,更加细腻的阴影效果(2019-04-02)
android-floating-action-button FloatingActionButton
SwitchButton 开关按钮
ShineButton 点赞效果
LikeButton 点赞效果
android-flat-button 自定义按钮,支持圆角等
android-process-button 带进度条的botton
circular-progress-button 带完成动画的botton
FABProgressCircle 带进度条的fabotton
ProgressRoundButton 带进度条的botton
FontSliderBar 仿微信设置字体
DoubleSeekBar 带进度的seekbar
UltimateRecyclerView 能强大的Recyclerview,包括了下拉刷新,加载更多,多种动画,空数据提示,拖动排序,视差处理,工具栏渐变,滑动删除,自定义floating button,多种刷新效果,scrollbar等等元素,而且使用起来跟recyclerview一样的方便。
epoxy Epoxy采用可组合的方式来创建列表。列表中的每个item由一个model代表,model定义了item的布局,id以及span。model还负责处理数据到视图的绑定,在视图被回收的时候释放资源。如果要显示这些model则把它们添加到Epoxy的adapter中,adapter为你处理复杂的显示问题。
Android-PickerView iOS的PickerView控件,有时间选择和选项选择,并支持一二三级联动,支持自定义样式。
停止维护
} ImagePicker 图片选择停止维护
} okhttputils okhttp的辅助类parceler 序列化(2019-03-29)
tray 替代SharedPreferences (2019-04-02)
smartTable 自动生成表格框架(2019-03-27)
k-9 邮箱(2019-03-29)
在布局中定义
1 | <TextView |
直接设置 TextView 的文本
1 | tv_content.text = "改变文本" |
1 | tv_content.setOnClickListener(View.OnClickListener( |
可以写成下面
1 | tv_content.setOnClickListener { v -> v.visibility = View.GONE } |
在 kotlin 语法中函数是可以作为变量进行传递的
1 | var result = fun(number1 : Int, number2 : Int) : Int { |
使用这个函数变量
1 | println(result(1, 2)) |
在 Java 不用强制我们处理空对象,所以常常会导致 NullPointerException 空指针出现,现在 Kotlin 对空对象进行了限定,必须在编译时处理对象是否为空的情况,不然会编译不通过.
在对象不可空的情况下,可以直接使用这个对象.
1 | fun getText() : String { |
在对象可空的情况下,必须要判断对象是否为空
1 | fun getText() : String? { |
如果不想判断是否为空,可以直接这样,如果 text 对象为空,则会报空指针异常,一般情况下不推荐这样使用
1 | val text = getText() |
还有一种更好的处理方式,如果 text 对象为空则不会报错,但是 text.length 的结果会等于 null
1 | val text = getText() |
在 Java 上,我们可能会为了扩展某个方法而进行多次重载
1 | public void toast(String text) { |
1 | toast("弹个吐司"); |
但是在 Kotlin 上面,我们无需进行重载,可以直接在方法上面直接定义参数的默认值
1 | fun toast(context : Context = this, text : String, time : Int = Toast.LENGTH_SHORT) { |
可以在不用继承的情况下对扩展原有类的方法,例如对 String 类进行扩展方法
1 | fun String.handle() : String { |
在 Kotlin 中使用运算符最终也会调用对象对应的方法,我们可以通过重写这些方法使得这个对象支持运算符,这里不再演示代码
运算符 | 调用方法 |
---|---|
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not() |
运算符 | 调用方法 |
---|---|
a++ | a.inc() |
a– | a.dec() |
运算符 | 调用方法 |
---|---|
a + b | a.plus(b) |
a - b | a.minus(b) |
a * b | a.times(b) |
a / b | a.div(b) |
a % b | a.rem(b), a.mod(b) (deprecated) |
a..b | a.rangeTo(b) |
运算符 | 调用方法 |
---|---|
a in b | b.contains(a) |
a !in b | !b.contains(a) |
运算符 | 调用方法 |
---|---|
a[i] | a.get(i) |
a[i, j] | a.get(i, j) |
a[i_1, …, i_n] | a.get(i_1, …, i_n) |
a[i] = b | a.set(i, b) |
a[i, j] = b | a.set(i, j, b) |
a[i_1, …, i_n] = b | a.set(i_1, …, i_n, b) |
运算符 | 调用方法 |
---|---|
a() | a.invoke() |
a(i) | a.invoke(i) |
a(i, j) | a.invoke(i, j) |
a(i_1, …, i_n) | a.invoke(i_1, …, i_n) |
运算符 | 调用方法 |
---|---|
a += b | a.plusAssign(b) |
a -= b | a.minusAssign(b) |
a *= b | a.timesAssign(b) |
a /= b | a.divAssign(b) |
a %= b | a.remAssign(b), a.modAssign(b) (deprecated) |
运算符 | 调用方法 |
---|---|
a == b | a?.equals(b) ?: (b === null) |
a != b | !(a?.equals(b) ?: (b === null)) |
运算符 | 调用方法 |
---|---|
a > b | a.compareTo(b) > 0 |
a < b | a.compareTo(b) < 0 |
a >= b | a.compareTo(b) >= 0 |
a <= b | a.compareTo(b) <= 0 |
扩展函数是 kotlin 用于简化一些代码的书写产生的,其中有 let、with、run、apply、also 五个函数。
在函数块内可以通过 it 指代该对象。返回值为函数块的最后一行或指定return表达式。
一般写法
1 | fun main() { |
let 写法
1 | fun main() { |
最常用的场景就是使用let函数处理需要针对一个可null的对象统一做判空处理
1 | mVideoPlayer?.setVideoView(activity.course_video_view) |
又或者是需要去明确一个变量所处特定的作用域范围内可以使用。
前面的几个函数使用方式略有不同,因为它不是以扩展的形式存在的。它是将某对象作为函数的参数,在函数块内可以通过 this 指代该对象。返回值为函数块的最后一行或指定return表达式
定义 Person 类
1 | class Person(var name : String, var age : Int) |
一般写法
1 | fun main() { |
with 写法
1 | fun main() { |
适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可,经常用于Android中RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上
1 | override fun onBindViewHolder(holder: ViewHolder, position: Int){ |
1 | override fun onBindViewHolder(holder: ViewHolder, position: Int){ |
实际上可以说是let和with两个函数的结合体,run函数只接收一个lambda函数为参数,以闭包形式返回,返回值为最后一行的值或者指定的return的表达式
一般写法
1 | var person = Person("Android轮子哥", 100) |
run 写法
1 | var person = Person("Android轮子哥", 100) |
适用于let,with函数任何场景。因为run函数是let,with两个函数结合体,准确来说它弥补了let函数在函数体内必须使用it参数替代对象,在run函数中可以像with函数一样可以省略,直接访问实例的公有属性和方法,另一方面它弥补了with函数传入对象判空问题,在run函数中可以像let函数一样做判空处理,这里还是借助 onBindViewHolder 案例进行简化。
1 | override fun onBindViewHolder(holder: ViewHolder, position: Int){ |
从结构上来看apply函数和run函数很像,唯一不同点就是它们各自返回的值不一样,run函数是以闭包形式返回最后一行代码的值,而apply函数的返回的是传入对象的本身
一般写法
1 | val person = Person("Android轮子哥", 100) |
apply 写法
1 | val person = Person("Android轮子哥", 100).apply { |
整体作用功能和run函数很像,唯一不同点就是它返回的值是对象本身,而run函数是一个闭包形式返回,返回的是最后一行的值。正是基于这一点差异它的适用场景稍微与run函数有点不一样。apply一般用于一个对象实例初始化的时候,需要对对象中的属性进行赋值。
或者动态inflate出一个XML的View的时候需要给View绑定数据也会用到,这种情景非常常见。特别是在我们开发中会有一些数据model向View model转化实例化的过程中需要用到。
1 | mRootView = View.inflate(activity, R.layout.example_view, null) |
使用 apply 函数后的代码是这样的
1 | mRootView = View.inflate(activity, R.layout.example_view, null).apply { |
多层级判空问题
1 | if (mSectionMetaData == null || mSectionMetaData.questionnaire == null || mSectionMetaData.section == null) { |
kotlin的apply函数优化
1 | mSectionMetaData?.apply { |
also函数的结构实际上和let很像唯一的区别就是返回值的不一样,let是以闭包的形式返回,返回函数体内最后一行的值,如果最后一行为空就返回一个Unit类型的默认值。而also函数返回的则是传入对象的本身
1 | fun main() { |
适用于let函数的任何场景,also函数和let很像,只是唯一的不同点就是let函数最后的返回值是最后一行的返回值而also函数的返回值是返回当前的这个对象。一般可用于多个扩展函数链式调用
通过以上几种函数的介绍,可以很方便优化kotlin中代码编写,整体看起来几个函数的作用很相似,但是各自又存在着不同。使用的场景有相同的地方比如run函数就是let和with的结合体
子任务协作运行,优雅的处理异步问题解决方案。
协程实际上就是极大程度的复用线程,通过让线程满载运行,达到最大程度的利用CPU,进而提升应用性能。
https://www.kotlincn.net/docs/reference/coroutines/coroutines-guide.html
Okhttp3
以 post 为例,请求过程大致分四步:
调度器。内部维护者最大请求数,每个主机最大请求数,还有三个最重要的队列,分别是 “将要执行的异步请求队列”、”正在执行的异步请求队列”、”正在执行的同步请求队列”。
在这个方法中,将用户自定义的一些拦截器和默认的拦截器封装到一个 list 中,然后创建 RealInterceptorChain
对象并执行 proceed(originalRequest)
方法。在 proceed
中,会遍历调用拦截器列表中的拦截器,并调用每一个拦截器的 intercept 方法。
例如第一个拦截器 RetryAndFollowUpInterceptor
中的 intercept
方法,有 while 循环,在重连次数 followUpCount
超过 20 次的时候,停止重连。循环中,会执行 RealInterceptorChain.proceed()
,会去除下一个拦截器并执行 intercept 方法,以此种方法遍历拦截器列表中的拦截器。
最后一个拦截器是 CallServerInterceptor
。HttpCodec 这个接口用来编码 http 请求并解码 http 返回结果,也就是说真正的处理请求和结果在这个接口中,它有两个实现类分别是Http1Codec
和Http2Codec
分别对应Http/1.x和Http/2.x。
图片相关,主要想记录一下 Fresco 跟Glide 相关的一些内容。
Glide
- 多种图片格式的缓存,适用于更多的内容表现形式 (如 Gif、WebP、缩略图、Video)
- 生命周期集成 (根据 Activity 或者 Fragment 生命周期管理图片加载请求)
- 高效处理 Bitmap (bitmap 的复用和主动回收,减少系统回收压力)
- 高效的缓存策略,灵活 (Picasso 只会缓存原始尺寸的图片,Glide 缓存的事多种规格),加载速度快且内存开销小 (默认 Bitmap 格式的不同,是的内存开销是 Picasso 的一般)
Fresco
- 最大的优势在于5.0以下(最低2.3)的bitmap加载。在5.0以下系统,Fresco将图片放到一个特别的内存区域(Ashmem区)
- 大大减少OOM(在更底层的Native层对OOM进行处理,图片将不再占用App的内存)
- 适用于需要高性能加载大量图片的场景
Glide
- 没有文件缓存
- Java heap 比 Fresco 高
Fresco
- 包较大(2~3M)
- 用法复杂
- 底层涉及c++领域,阅读源码深入学习难度大
Glide 源码基本用法分为三步:with()、load()、into()。
在 with 中传入一个 Application 类型的对象或者非 Application 类型的参数,会向当前的 Activity 添加一个隐藏的 Fragment,用来监听当前的生命周期。
如果在非主线程中使用 Glide,不管传入的是 Activity 还是 Fragment,都会被强制当成 Application 来处理。
with 方法主要作用是得到一个 RequestManager 对象,监听生命周期。
最后会返回一个 RequestBuilder 对象。RequestBuilder 中包含了 Glide 绝大多数的 API。
资料https://blog.csdn.net/guolin_blog/article/details/53939176
本来想简单记录一下 Handler 的,但是发现其主要作用就是在 Android 上的消息传递,那就大概记录一下 Android 上的消息机制吧。
Handler 是 Android 消息机制的上层接口,用来将一个任务切换到 Handler 所在的线程中执行。
Android 的消息机制主要是指 Handler 的运行机制,Handler 的运行需要底层的 MessageQueue 和 Looper 的支撑。MessageQueue 内部存储了一组采用单链表的数据结构来存储的消息队列,以消息队列的形式对外提供插入和删除的工作。Looper 以无限循环的形式去查看 MessageQueue 中是否又新消息并处理,没有的话则一直等待。
Looper 中的 ThreadLocal 可以在不同的线程中互不干扰的存储并提供数据。线程默认没有 Looper,需要创建。
系统不允许在子线程访问 UI 线程是因为 Android 的 UI 控件不是线程安全的,多线程兵法访问会造成不可预期的结果。
消息队列工作流程
设计模式说起来总是那么抽象,自己也没做过总结,今天就来记录一下吧。
先记录下浴缸主席的几个心得,慢慢去领会一下:
3、4的意思大概是要经历九九八十一难,才能到达西天取得真经,修成正果吧。
再记录下主席关于评价一个设计好坏的几个要素,还是实践中慢慢去领会:
范围 | 创建型 | 结构型 | 行为型 |
---|---|---|---|
类 | Factory Method (工厂方法) | Adapter (类) | Interpreter (解释器) Template Method (模板方法) |
对象 | Abstract Factory (抽象工厂) Builder (建造者) Prototype (原型) Singleton (单例) |
Adapter(对象) Bridge(桥接) Composite(组合) Decorator(装饰者) Facade(外观) Flyweight(享元) Proxy(代理) |
Chain of Responsibility (职责链) Command (命令) Iterator (迭代器) Mediator (中介者) Memento (备忘录) Observer (观察者) State (状体) Strategy (策略) Visitor (访问者) |
更详细的分类可以看这里。
在安卓开发中,接触到的设计模式有:
参考资料在这里,留着慢慢看,慢慢补充吧
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true