<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[知识需要细嚼慢咽]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/woohyman</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; woohyman]]></copyright><item><title><![CDATA[Android动画学习]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/118558308</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/118558308</guid><author>woohyman</author><pubDate>Wed, 07 Jul 2021 21:53:12 +0800</pubDate><description><![CDATA[1. 补间动画
补间动画具体有四种如下图所示：

有两种实现方式：XML和java
//xml实现方式：

//1.定义一个xml
 &lt;?xml version="1.0" encoding="utf-8"?&gt;
 &lt;translate
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:fromXDelta="0"
     android:fromYDelta="0"
     andr]]></description><category></category></item><item><title><![CDATA[View体系学习之绘制流程]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/117794396</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/117794396</guid><author>woohyman</author><pubDate>Fri, 11 Jun 2021 00:43:36 +0800</pubDate><description><![CDATA[1. onMeasure过程
1.1 View
首先介绍的是View的Measeure过程.从measure方法说起,他是View内部的一个方法,并且用final修饰.他是View对象Measure过程的起始点:
public final void measure(int widthMeasureSpec, int heightMeasureSpec){
    ...
    // 如果强制执行layout或者需要layout的情况
    if (forceLayout || needsLayout) ]]></description><category></category></item><item><title><![CDATA[View体系学习之事件传递]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/117640206</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/117640206</guid><author>woohyman</author><pubDate>Mon, 07 Jun 2021 01:13:16 +0800</pubDate><description><![CDATA[1 源码分析
1.1 事件分发所要经过的对象
首先从三个常见的对象开始分析：
Activity ==&gt; Window  ==&gt; ViewGroudp ==&gt; View
手指触摸屏幕首先碰到的是Activity，然后再一步步传下去。每一步都有可能被拦截并且返回。
有个比较形象的比喻就是Activity是老板，Window是技术经理（本身也是技术能手），ViewGroup像是组长（本身也是技术能手），View是具体的员工。
老板发布任务，技术经理查看并交给组长，组长查看再交给员工。中间随时都有]]></description><category></category></item><item><title><![CDATA[View体系学习之Activity构成]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/117458576</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/117458576</guid><author>woohyman</author><pubDate>Wed, 02 Jun 2021 01:39:29 +0800</pubDate><description><![CDATA[前言
鉴于最近接触UI会比较多。先对次做一个初步的了解，以便能快速融入项目。学一个东西我比较喜欢从熟悉的入手，那Activity应该是Android开发中最熟悉的东西了。无论是对于View学习还是Dialog等的理解，Activity的结构熟悉都极有好处。本文只是做一个初步的了解。
源码分析
先从Activity最常用的setContentView入手：
@Override
public void setContentView(@LayoutRes int layoutResID) {
    getDel]]></description><category></category></item><item><title><![CDATA[组件化学习之初识组件化]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/111189468</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/111189468</guid><author>woohyman</author><pubDate>Tue, 15 Dec 2020 00:52:23 +0800</pubDate><description><![CDATA[1 背景
随着项目的增加，弊端也随之而来：

不同的App之间有大量的重复功能
代码之间耦合太严重，改了一部分代码却影响到了其他不相关的代码
第三方开源框架版本不统一而且不同的app要开启不同的工程，开发起来极其麻烦
项目编译起来时间越来越长

2 整体框架
针对以上问题对项目进行了重构。将通用功能封装起来、根据不同业务分为不同的组件以及用gradle统一进行项目构建。如下所示：
整体的架构分为三层，越底层变动的频度越低：
基础层：主要是开源的第三方开源框架或者第三方SDK。这些基本是不会改动的，除非有特殊]]></description><category></category></item><item><title><![CDATA[OkHttp源码解析之重试重定向、桥、缓存]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/109733930</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/109733930</guid><author>woohyman</author><pubDate>Tue, 17 Nov 2020 00:54:51 +0800</pubDate><description><![CDATA[1.重试/重定向拦截器
RetryAndFollowUpInterceptor 作用是连接失败后重试或者进行重定向。代码如下：
@Override public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Transmitter ]]></description><category></category></item><item><title><![CDATA[OkHttp源码解析之网络连接与请求]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/109708957</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/109708957</guid><author>woohyman</author><pubDate>Sun, 15 Nov 2020 20:21:09 +0800</pubDate><description><![CDATA[1 网络的建立
1.1 获取可用的连接
网络的建立由ConnectInterceptor拦截器完成，那么先看下该拦截器的实现：
// We need the network to satisfy this request. Possibly for validating a conditional GET.
// 顾名思义。如果不是GET的时候，那么就用doExtensiveHealthChecks来判断是否要进行额外的检查。
boolean doExtensiveHealthChecks = !reque]]></description><category></category></item><item><title><![CDATA[OkHttp源码解析之请求数据与回调]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/108971703</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/108971703</guid><author>woohyman</author><pubDate>Fri, 09 Oct 2020 02:13:36 +0800</pubDate><description><![CDATA[1 使用
首先从一个简单使用例子开始入手，下面的是源码中的一个例子：
 OkHttpClient client = new OkHttpClient();//步骤1

    // Create request for remote resource.
    Request request = new Request.Builder()
        .url(ENDPOINT)
        .build();//步骤2

    // Execute the request and retriev]]></description><category></category></item><item><title><![CDATA[Retrofit源码解析之网络请求]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/108878713</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/108878713</guid><author>woohyman</author><pubDate>Wed, 30 Sep 2020 01:44:47 +0800</pubDate><description><![CDATA[1 解析注释并生成ServiceMethod对象
首先从Retrofit的create动态代理开始分析
ServiceMethod&lt;?&gt; loadServiceMethod(Method method) {
    ServiceMethod&lt;?&gt; result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) ]]></description><category></category></item><item><title><![CDATA[Retrofit源码解析之整体流程解析]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/108819431</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/108819431</guid><author>woohyman</author><pubDate>Sat, 26 Sep 2020 23:56:35 +0800</pubDate><description><![CDATA[1 前言
本文从流程的角度分析了Rtrofit的请求以及回调过程，对代码结构会有一个比较清晰的认知，具体的功能并没有跟进去。这样子的好处是不至于由于某个或者某几个具体功能的解析而使得整个思绪变得混乱。下一篇会对各个具体的功能各个击破，比如说注解解析等。
2 构建Retrofit对象
Rtrofit的一大特色就是可以配置各种工厂。比如说RxJavaCallAdapterFactory那么结果便可以生成Observer对象，你就可以方便的使用Rxjava来处理数据了。再比如说你也可以用protobuf或者gso]]></description><category></category></item><item><title><![CDATA[Retrofit源码解析之概括总览]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/108763676</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/108763676</guid><author>woohyman</author><pubDate>Wed, 23 Sep 2020 22:46:31 +0800</pubDate><description><![CDATA[1 前言
首先，Retrofit是对OkHttp作了进一步的封装，网络请求的本质还是通过OkHttp来完成。

其次，Retrofit运用了大量的设计模式，使得整体框架显得整洁明了。其中通过适配器模式甚至可以直接兼容Rxjava。
2 注解
Retrofi的一大特色就是应用了大量的注解。这些注解可分为三大部分：
2.1 网络请求方法的注解

从get到options对应着HTTP中的网络请求方式，其中最常用的应该是@GET以及@POST这两个注解了。可以这样子比喻。TCP相当于高速公路，GET相当于送急件的]]></description><category></category></item><item><title><![CDATA[Kotlin学习笔记之剩余部分]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/107754533</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/107754533</guid><author>woohyman</author><pubDate>Mon, 03 Aug 2020 00:17:25 +0800</pubDate><description><![CDATA[1. 解构声明
首先看下写法：val (name, age) = person。其中name以及age可以单独使用。
println(name)
println(age)

解构声明也可以用在for循环中：
for ((a, b) in collection) { …… }

如果解构出来的变量如果有某个参数不会使用，那么可以使用_来替换。
val (_, status) = getResult()

解构也可以用在lambda中的参数：
map.mapValues { entry -&gt; "${ent]]></description><category></category></item><item><title><![CDATA[Kotlin学习笔记之集合]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/107734208</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/107734208</guid><author>woohyman</author><pubDate>Sat, 01 Aug 2020 17:44:42 +0800</pubDate><description><![CDATA[1.集合概述
kotlin集合主要有三类

List 是一个有序集合，可通过索引（反映元素位置的整数）访问元素。
Set 集合中的元素是唯一的，不可重复。
Map（或者字典）是一组键值对。

1.1 集合类型
集合结构可以用以下两种归纳来区分：


一个 只读 接口，提供访问集合元素的操作。


一个 可变 （可读可写）接口，通过写操作扩展相应的只读接口：添加、删除和更新其元素。


而集合的只读并不是通过val来修饰，也就是说并不能使得该集合只读。他只是保障了该集合的引用是不可变的，如下所示：
val n]]></description><category></category></item><item><title><![CDATA[kotlin读书笔记之类与对象]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/106894580</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/106894580</guid><author>woohyman</author><pubDate>Mon, 22 Jun 2020 02:46:13 +0800</pubDate><description><![CDATA[1. 类与继承
1.1 类的用法
与java一样使用class声明类，后面可以跟着大括号：
class Invoice { /*……*/ }
class Empty

1.2 构造函数
kotlin可以有一个构造函数以及多个次构造函数。主构造函数是类头的一部分，跟在类头后面：
class Person constructor(firstName: String) { /*……*/ }

如果主构造函数没有任何注解或者可见性修饰符，那么可以省略constructor。
class Person(firstNa]]></description><category></category></item><item><title><![CDATA[kotlin读书笔记之基础语法]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/106845312</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/106845312</guid><author>woohyman</author><pubDate>Thu, 18 Jun 2020 23:10:01 +0800</pubDate><description><![CDATA[1.初识Kotlin
1.1 变量
变量的定义写法上和java差别挺大的。变量分为可读以及可读可写，而且kotlin会自动推测出变量的类型，可推测的情况下。
val a: Int = 1  // 立即赋值
val b = 2   // 自动推断出 `Int` 类型
val c: Int  // 如果没有初始值类型不能省略
c = 3       // 明确赋值
var x = 5 // 自动推断出 `Int` 类型
x += 1

1.2 字符串模板
这个有点向shell脚本，比java更加的直观方便。
v]]></description><category></category></item><item><title><![CDATA[Kotlin读书笔记之内联函数、扩展函数、匿名函数、lambda]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/106798631</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/106798631</guid><author>woohyman</author><pubDate>Wed, 17 Jun 2020 00:12:48 +0800</pubDate><description><![CDATA[本文主要涉及内联函数、扩展函数、lambada以及匿名函数等。作为读书笔记对于细节深入没有过多的扩展，后续将对于各个知识点作进一步的研度。本文的内容主要是参考官方教程以及博客内容，作为读书笔记以及后续知识点扩展的一个大纲。学海无涯，希望能在Android这条路上越走越远！

1.内联函数
1.1 内联函数的使用
首先看个例子，一个是用了inline修饰，另一个没有：
    init{
        functionWithInline()
        functionWithoutInline().]]></description><category></category></item><item><title><![CDATA[kotlin读书笔记之函数基本知识以及泛型]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/106416946</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/106416946</guid><author>woohyman</author><pubDate>Fri, 29 May 2020 00:29:40 +0800</pubDate><description><![CDATA[1.函数内容
1.1 函数的声明与用法
kotlin的函数使用fun关键字声明，如下所示：
fun double(x: Int): Int {
    return 2 * x
}
double(2).tostring()

1.2 函数参数
和java不一样，kotlin的函数参数采用pascal表示法定义，即 name: type。
fun powerOf(number: Int, exponent: Int) { /*……*/ }

kotlin可以设置默认参数：
fun read(b: Array&]]></description><category></category></item><item><title><![CDATA[学习开源播放器代码解析之参数设置]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/104721948</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/104721948</guid><author>woohyman</author><pubDate>Sat, 07 Mar 2020 21:11:15 +0800</pubDate><description><![CDATA[1.前言

  出于学习音视频的目的，在Github找了个基于FFMPEG的播放器代码，代码量比较小。地址：fflayer。于是乎下载编译了下，运行结果良好。So，出于学习的目的，写写学习笔记，归纳归纳。该开源代码使用的ffmpeg函数有些被标记成过时的换成最新的会出现闪屏以及看直播时视频声音不同步等各种问题。在后续解析完再慢慢琢磨怎么解决这些问题以及自己可以尝试写个简易播放器加深理解。

2.源...]]></description><category></category></item><item><title><![CDATA[设计模式之单例模式]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/102924164</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/102924164</guid><author>woohyman</author><pubDate>Wed, 06 Nov 2019 22:54:46 +0800</pubDate><description><![CDATA[前言

单例模式是设计模式中最常用的一种，也可以说是最基本的。最常见的可以分为7种，涉及到JVM以及并发编程的特性。

饿汉式


public class Singleton{
    private Singleton(){
        
    }
    private static Singleton instance = new Singleton();
    public st...]]></description><category></category></item><item><title><![CDATA[读书笔记之AfinalBitmap源码分析]]></title><link>https://blog.youkuaiyun.com/woohyman/article/details/86747030</link><guid>https://blog.youkuaiyun.com/woohyman/article/details/86747030</guid><author>woohyman</author><pubDate>Sat, 02 Feb 2019 02:53:30 +0800</pubDate><description><![CDATA[前言
在项目中会用到Afinal框架，感觉很方便也挺稳定的。他有四部分功能：FinalActivity、FinalBitmap、FinalDb、FinalHttp。本篇分析FinalBitmap原理，如有错误欢迎指出！
源码分析
1.FinalBitmap的用法
先是新建一个对象，然后做一些配置。
mFinalBitmap = FinalBitmap.create(RadioApplication...]]></description><category></category></item></channel></rss>