<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[JW的博客]]></title><description><![CDATA[hold on]]></description><link>https://blog.youkuaiyun.com/qq_21612413</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; qq_21612413]]></copyright><item><title><![CDATA[使用注解替代枚举]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/109216616</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/109216616</guid><author>qq_21612413</author><pubDate>Thu, 22 Oct 2020 11:53:06 +0800</pubDate><description><![CDATA[概述
使用枚举Enum能确保类型安全，但往往会加大内存消耗，因为Enum中的枚举值是静态成员对象，相对于静态常量占用更多的内存空间。google官方在很早以前就提醒尽量少的使用枚举，并提供了注解的方式来检查类型安全，目前提供了@IntDef和@StringDef这两种注解方式。
注解
一、@IntDef
定义注解，添加常量
@IntDef(value = {AnnotationStatus.TYPE_ONE, AnnotationStatus.TYPE_TWO})
@Retention(RetentionP]]></description><category></category></item><item><title><![CDATA[TCP三次握手和四次挥手]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/108253926</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/108253926</guid><author>qq_21612413</author><pubDate>Thu, 27 Aug 2020 13:54:25 +0800</pubDate><description><![CDATA[TCP三次握手

三次握手（Three-way Handshake）其实就是指建立一个TCP连接时，需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。实质上其实就是连接服务器指定端口，建立TCP连接，并同步连接双方的序列号和确认号，交换TCP窗口大小信息。

一、握手过程


刚开始客户端处于 Closed 的状态，服务端处于 Listen 状态。


第一次握手：客户端向服务器发送SYN报文请求连接，报文中]]></description><category></category></item><item><title><![CDATA[Android 使用Visualizer获取播放音频的频率]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/107489030</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/107489030</guid><author>qq_21612413</author><pubDate>Tue, 21 Jul 2020 18:28:04 +0800</pubDate><description><![CDATA[最近项目中需要实时获取播放音频的频率，并绘制波形图，用到了Visualizer这个类，记录下其使用方法：
Visualizer.OnDataCaptureListener有两个回调方法，分别是onFftDataCapture和onWaveFormDataCapture，onFftDataCapture返回的是经过傅里叶变换处理后的音频数据，onWaveFormDataCapture返回的是声音的波形数据。
计算声音分贝部分代码：
val readyData = readyData(fft)
val inte]]></description><category></category></item><item><title><![CDATA[记录RecyclerView聊天页下拉加载页面闪烁问题]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/107469320</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/107469320</guid><author>qq_21612413</author><pubDate>Mon, 20 Jul 2020 18:40:11 +0800</pubDate><description><![CDATA[在使用RecyclerView做聊天页面时下拉时，使用addAll(0, tempDatas)加载数据后页面会出现闪烁，一开始以为是动画问题，所以加了(itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false处理后，发现还是出现闪烁问题。
测试发现，如果直接在数据集尾部添加数据，并不会有闪烁问题，最终定位到getItemId这个方法，该方法我在基类默认的处理是返回position作为id。而当在数据头部添加数据时，导致所有数据]]></description><category></category></item><item><title><![CDATA[Android 圆环进度条（带渐变）控件]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/105951051</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/105951051</guid><author>qq_21612413</author><pubDate>Wed, 06 May 2020 15:28:30 +0800</pubDate><description><![CDATA[效果图：


核心代码
package com.jw.gradualprogressdemo

import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.u...]]></description><category></category></item><item><title><![CDATA[Glide源码分析（一）]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/102520732</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/102520732</guid><author>qq_21612413</author><pubDate>Sat, 12 Oct 2019 16:00:42 +0800</pubDate><description><![CDATA[Glide源码分析（一）一、基本使用二、Glide.with方法Glide实例化RequestManagerRetriever#get:三、load方法四、into方法buildRequest方法构建请求requestManager.track(target, request)总结
一、基本使用
implementation 'com.github.bumptech.glide:glide:4.9...]]></description><category></category></item><item><title><![CDATA[Android 多语言处理]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/98491105</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/98491105</guid><author>qq_21612413</author><pubDate>Mon, 05 Aug 2019 16:14:56 +0800</pubDate><description><![CDATA[Android 多语言处理

由于公司最近在扩展海外市场，所以新项目不可避免的要用到多语言。多语言处理也就是针对用户选择的语言环境来切换并使用不同的string资源。
这次项目的具体的业务是当用户首次进入App，默认获取系统语言，如果在语言列表内，则使用该语言，否则，默认使用美式英语。

UI界面类似下面，选择不同语言后，当退出页面后才去切换语言环境：

一、配置不同环境的资源文件
在res目录下...]]></description><category></category></item><item><title><![CDATA[NestedScrollView与EditText滑动冲突处理]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/98486871</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/98486871</guid><author>qq_21612413</author><pubDate>Mon, 05 Aug 2019 14:50:59 +0800</pubDate><description><![CDATA[监听EditText的触摸事件，判断当前EditText是否可以是上下滚动，如果可以滑动，则请求父控件不拦截子事件，在up事件触发时，将requestDisallowInterceptTouchEvent设置回false。
etNote.setOnTouchListener { v, event -&gt;

	// 控件id
    if (v.id == R.id.etNote &amp;&a...]]></description><category></category></item><item><title><![CDATA[Retrofit2源码分析]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/89634201</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/89634201</guid><author>qq_21612413</author><pubDate>Fri, 24 May 2019 14:12:10 +0800</pubDate><description><![CDATA[严格来说，Retrofit并不是一个对网络请求进行封装的框架，因为它的网络请求是通过OkHttp实现的，而实际上它是对网络请求接口的封装。

]]></description><category></category></item><item><title><![CDATA[理解ClassLoader]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/88938081</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/88938081</guid><author>qq_21612413</author><pubDate>Tue, 09 Apr 2019 17:04:39 +0800</pubDate><description><![CDATA[ClassLoader是什么？
ClassLoader叫做类加载器，具体作用是在类加载阶段将.class文件加载到jvm虚拟机中，
然后转成内存形式的Class对象供程序使用。还有就是jvm在运行时并不会立即加载所有的.class文件，而是按需加载的，
当执行到未加载过的类时，才对该类进行加载，不然一次性加载，估计内存都炸了。
ClassLoader加载原理
jvm在运行中会存在很多个ClassL...]]></description><category></category></item><item><title><![CDATA[CallServerInterceptor拦截器分析]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/88356726</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/88356726</guid><author>qq_21612413</author><pubDate>Fri, 08 Mar 2019 18:47:58 +0800</pubDate><description><![CDATA[在分析完ConnectInterceptor拦截器后，终于来到了最后一个拦截器CallServerInterceptor，其主要作用就是向服务器发送请求，最终返回response。
还是先看下它的intercept方法：
public Response intercept(Chain chain) throws IOException {
        final RealInterceptor...]]></description><category></category></item><item><title><![CDATA[ConnectInterceptor拦截器分析]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/88120384</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/88120384</guid><author>qq_21612413</author><pubDate>Mon, 04 Mar 2019 15:49:19 +0800</pubDate><description><![CDATA[在分析完CacheInterceptor拦截器后，我们再来看下ConnectInterceptor这个拦截器，其主要作用就是与服务器建立连接。
直接看它的intercept方法：
public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealIntercep...]]></description><category></category></item><item><title><![CDATA[CacheInterceptor拦截器分析]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/87783202</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/87783202</guid><author>qq_21612413</author><pubDate>Mon, 25 Feb 2019 14:02:28 +0800</pubDate><description><![CDATA[在分析完BridgeInterceptor拦截器之后，接下来我们看下CacheInterceptor（缓存处理）拦截器，还是从它的intercept方法看起：
public Response intercept(Chain chain) throws IOException {
    // 如果配置了缓存，则通过request获取缓存，默认cache为空
    Response cacheCa...]]></description><category></category></item><item><title><![CDATA[BridgeInterceptor拦截器分析]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/87781981</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/87781981</guid><author>qq_21612413</author><pubDate>Wed, 20 Feb 2019 11:05:46 +0800</pubDate><description><![CDATA[在分析完RetryAndFollowUpInterceptor拦截器后，我们看下BridgeInterceptor(连接桥拦截器)这个拦截器，它的主要作用是在request阶段配置请求头信息，cookie信息等，在response阶段，处理并保存返回的cookie信息，判断是否需要进行gzip解压等。
我们直接来看它的 intercept方法中的处理：
public Response interc...]]></description><category></category></item><item><title><![CDATA[RetryAndFollowUpInterceptor拦截器分析]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/87624821</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/87624821</guid><author>qq_21612413</author><pubDate>Mon, 18 Feb 2019 15:49:54 +0800</pubDate><description><![CDATA[RetryAndFollowUpInterceptor拦截器分析
在上篇文章讲解了OKHttp的基本流程后，我们来看下RetryAndFollowUpInterceptor（错误重试和重定向拦截器）的实现。
不多说，我们直接看下该拦截器的intercept方法：
 public Response intercept(Chain chain) throws IOException {
    Req...]]></description><category></category></item><item><title><![CDATA[OKHttp源码分析]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/87358000</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/87358000</guid><author>qq_21612413</author><pubDate>Fri, 15 Feb 2019 14:17:40 +0800</pubDate><description><![CDATA[OkHttp源码分析
OkHttp是个目前比较流行的网络请求框架，现在大部分的应用都有在用它，看了很多大佬们写的OKHttp相关的博客，在这里记录下自己的分析过程。由于OkHttp内容比较多，这篇文章主要先简单分析下OkHttp请求的基本流程。
首先，在分析源码之前先看下使用OkHttp请求的示例代码：
val okHttpClient = OkHttpClient.Builder()
    ....]]></description><category></category></item><item><title><![CDATA[EventBus中的SubscriberInfoIndex]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/86711641</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/86711641</guid><author>qq_21612413</author><pubDate>Thu, 31 Jan 2019 10:23:53 +0800</pubDate><description><![CDATA[EventBus中的注解处理器生成的索引类（SubscriberInfoIndex）
在EventBus源码解析中的findUsingInfo方法中有说到如果没有配置索引类，那么就会调用findUsingReflectionInSingleClass方法，在运行时利用反射来获取所有被@Subscribe注解标注的订阅方法，但这种做法对应用性能会有一定的损耗，所以在3.0后EventBus提供了索引...]]></description><category></category></item><item><title><![CDATA[EventBus粘性事件]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/86707341</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/86707341</guid><author>qq_21612413</author><pubDate>Wed, 30 Jan 2019 18:47:54 +0800</pubDate><description><![CDATA[EventBus粘性事件
普通事件都是在订阅后才可以接收到事件，如果事件的发送在订阅事件之前，则收不到事件。而粘性事件指的是在发送事件之后再订阅该事件也能收到该事件。
1、发送粘性事件

// 存储粘性事件的Map
private final Map&amp;amp;lt;Class&amp;amp;lt;?&amp;amp;gt;, Object&amp;amp;gt; stickyEvents;

// 发送粘性事件
public void postSti...]]></description><category></category></item><item><title><![CDATA[EvenBus源码分析]]></title><link>https://blog.youkuaiyun.com/qq_21612413/article/details/86701134</link><guid>https://blog.youkuaiyun.com/qq_21612413/article/details/86701134</guid><author>qq_21612413</author><pubDate>Wed, 30 Jan 2019 11:53:14 +0800</pubDate><description><![CDATA[EventBus分析源码分析1、获取实例2、注册（register）3、反注册（unregister）4、发送事件（post）总结
源码分析
EventBus 是一款在 Android 开发中使用的发布/订阅事件总线框架，基于观察者模式，将事件的接收者和发送者分开，简化了组件之间的通信，使用简单、效率高、体积小！
分析它的源码，我们先从获取实例入手，然后分析下它的register方法，unregi...]]></description><category></category></item></channel></rss>