<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[hexiaosa91的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/hexiaosa91</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; hexiaosa91]]></copyright><item><title><![CDATA[Retrofit（OkHttp）源码分享]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/98987560</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/98987560</guid><author>hexiaosa91</author><pubDate>Fri, 09 Aug 2019 20:28:29 +0800</pubDate><description><![CDATA[Retrofit（OkHttp）源码分享
一、使用
1.创建接口
public interface CountTryApi {
    @GET("/api/location/country")
    Call&lt;ResponseBody&gt;  getCall(@Query("id") String id);
}

2.发起请求
Retrofit retrofit = new Retro...]]></description><category></category></item><item><title><![CDATA[从源头分析 Android 中 View 的绘制流程]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/89156982</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/89156982</guid><author>hexiaosa91</author><pubDate>Tue, 09 Apr 2019 18:02:36 +0800</pubDate><description><![CDATA[View 的绘制流程 layout,measure,draw，追溯到源头，就是 Activity 创建时 View 的绘制。
从源码来看，大概会涉及到 Activity 的 attach, create, resume 这三个过程
Activity 的 attach 过程
启动 Activity 时，ActivityThread 的 performLaunchActivity 方法中先调用了 ac...]]></description><category></category></item><item><title><![CDATA[事件分发 ———— 从源码详细分析事件分发流程]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/86718132</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/86718132</guid><author>hexiaosa91</author><pubDate>Thu, 31 Jan 2019 17:23:30 +0800</pubDate><description><![CDATA[从源码分析事件分发, https://blog.youkuaiyun.com/lmj623565791/article/details/39102591 这篇博客和 《Android开发艺术探索》 已经讲的很清晰了，我按从正常事件分发流程（返回结果都是 super），从源码角度分析事件分发的流程为什么是这样的。
假设现在 DecoreView 里包含一个 ViewGourp(V1), ViewGroup 中包...]]></description><category></category></item><item><title><![CDATA[View  坐标体系和 View 的滑动]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/86169820</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/86169820</guid><author>hexiaosa91</author><pubDate>Wed, 09 Jan 2019 18:36:33 +0800</pubDate><description><![CDATA[View 坐标介绍
View 坐标表示有以下几种， getLeft, getTranstationX, getScrollX, getRawX, getX. 那么这几种表示有什么区别呢

getLeft 表示 View  的实际坐标，View 的实际左上角距离父 View 左上角的水平距离。
getTranslationX 表示 View 与父 View 的水平偏移量，可以通过设置 view.se...]]></description><category></category></item><item><title><![CDATA[进程间通信 —— Binder 深入理解]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/84632711</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/84632711</guid><author>hexiaosa91</author><pubDate>Thu, 29 Nov 2018 14:49:04 +0800</pubDate><description><![CDATA[简介
在可以使用 AIDL 进行进程间通信后，AIDL 是基于 Binder 的，来通过 AIDL 分析一下 Binder。
使用 AIDL 的过程中会有这样的疑问：
Server onBind 方法返回的是一个 IMyInterface.Stub 对象，为什么客户端接收到的是 BinderProxy 对象呢
首先对过程中出现的类进行解释
IMyInterface : 自定义的 AIDL 接口，实...]]></description><category></category></item><item><title><![CDATA[并发编程 —— 线程池简介和源码分析]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/84205260</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/84205260</guid><author>hexiaosa91</author><pubDate>Sun, 18 Nov 2018 21:36:56 +0800</pubDate><description><![CDATA[线程池简介
线程池的优点：提高性能，提高线程的利用率，可控制线程的最大并发数，方便线程管理。
线程池的核心类是 ThreadPoolExecutor, 可通过 Executors 中的几个方法创建线程池，分别是：


CachedThreadPool
核心线程数为 0, 线程数量无上限


FixedThreadPool
核心线程数由使用者自己指定，无非核心线程，线程空闲时不会被回收，除非线程池被...]]></description><category></category></item><item><title><![CDATA[并发编程 —— CyclicBarrier 讲解]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/83444512</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/83444512</guid><author>hexiaosa91</author><pubDate>Sat, 27 Oct 2018 11:13:44 +0800</pubDate><description><![CDATA[CyclicBarrier 介绍
CyclicBarrier 是用于阻塞固定数量的线程，数量达到时就继续这些线程的执行，并可以指定继续执行这些线程之前执行 Runnable, 这个 Runnable 是在到达临界数量的那个线程执行的。
例子如下：
private static CyclicBarrier caBarrier = new CyclicBarrier(3, new Runnable()...]]></description><category></category></item><item><title><![CDATA[并发编程 —— CountDownLatch 讲解]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/83444503</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/83444503</guid><author>hexiaosa91</author><pubDate>Sat, 27 Oct 2018 11:12:56 +0800</pubDate><description><![CDATA[CountDownLatch 介绍
CountDownLatch 是用于等待线程的执行，等待线程数量为 0 后，则结束等待，执行该线程等待后所要执行的代码。
例子如下：
private static CountDownLatch caDownLatch = new CountDownLatch(2);

public static void main(String[] args) {
	new T...]]></description><category></category></item><item><title><![CDATA[自定义View —— 可删除 item 的 ListView (事件分发)]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/83444486</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/83444486</guid><author>hexiaosa91</author><pubDate>Sat, 27 Oct 2018 11:11:50 +0800</pubDate><description><![CDATA[
本文所用源码：https://github.com/HeXiaosa/ItemDeletableListView
本文由看这篇文章 https://blog.youkuaiyun.com/lmj623565791/article/details/22961279 以及结合 Andorid 开发艺术探索而来。

事件分发概述
Android 中触摸事件主要由 dispatchTouchEvent, onInt...]]></description><category></category></item><item><title><![CDATA[Android 性能优化]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/82853236</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/82853236</guid><author>hexiaosa91</author><pubDate>Wed, 26 Sep 2018 14:46:19 +0800</pubDate><description><![CDATA[本文将从布局优化、Bitmap、内存泄漏几个方面讲解 Android 性能优化。
Android 中布局优化

加载可能性小的布局使用 ViewStub, 在需要使用的时候再动态加载，因为 ViewStub 默认是 VISIBLE_GONE, 不去加载布局，在主动调用 inflate() 或 setVisible() 方法时才会渲染布局。
尽可能减少布局的层级，比如一般情况下使用 Relative...]]></description><category></category></item><item><title><![CDATA[Android 图片处理]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/82632784</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/82632784</guid><author>hexiaosa91</author><pubDate>Tue, 11 Sep 2018 21:08:13 +0800</pubDate><description><![CDATA[1. Bitmap 性能相关



使用 inSampleSize 来缩放

使用方式：



BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 设为 true 不会分配内存，用来获取图片宽高
BitmapFactory.decodeResource(...]]></description><category></category></item><item><title><![CDATA[Java 类的加载]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/82432488</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/82432488</guid><author>hexiaosa91</author><pubDate>Wed, 05 Sep 2018 23:16:10 +0800</pubDate><description><![CDATA[类的加载过程

加载


将 .java 文件转成二进制流
将类信息存入方法区
在方法区中生成一个 Class 对象，用于访问该类的接口


PS： 
读取到二进制流的来源，常见的有：ZAR包，运行中动态计算（动态代理），其它文件生成（JSP）



验证

验证过程是为了防止恶意代码破坏虚拟机而进行验证的过程。 
1. 文件格式验证：该过程是针对二进制流进行的，只有通过了该验证，二进制流才可以进...]]></description><category></category></item><item><title><![CDATA[RecycleView 缓存机制]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/82291859</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/82291859</guid><author>hexiaosa91</author><pubDate>Sat, 01 Sep 2018 23:13:10 +0800</pubDate><description><![CDATA[RecyclerView 的使用：

RecyclerView lv = (RecyclerView) findViewById(R.id.lv);
lv.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));
lv.setAdapter(new...]]></description><category></category></item><item><title><![CDATA[从 ListView 源码简单描述缓存复用流程]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/82194722</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/82194722</guid><author>hexiaosa91</author><pubDate>Wed, 29 Aug 2018 23:58:57 +0800</pubDate><description><![CDATA[ListView 中缓使用了 RecycleBin(AbsListView 的内部类), 它内部有几个重要的成员变量： 
mScrapViews : 多种 viewType 时，缓存 viewType 个 view 
mCurrentScrap : 一种 viewType 时，缓存一个 view 
mActiveViews : 缓存屏幕上显示的 view, 用于在 layout 过程中复用 vie...]]></description><category></category></item><item><title><![CDATA[AsyncTask 详解与思考]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/81948767</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/81948767</guid><author>hexiaosa91</author><pubDate>Wed, 22 Aug 2018 18:08:58 +0800</pubDate><description><![CDATA[使用

先上一段熟悉的代码，AsyncTask 的使用

MyAsyncTask task = new MyAsyncTask();
task.execute(&amp;quot;1&amp;quot;);

private class MyAsyncTask extends AsyncTask&amp;amp;lt;String, Void, String&amp;amp;gt; {

    @Override
    protected void onPre...]]></description><category></category></item><item><title><![CDATA[并发编程 —— ReentrantLock 原理]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/81915652</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/81915652</guid><author>hexiaosa91</author><pubDate>Tue, 21 Aug 2018 22:17:35 +0800</pubDate><description><![CDATA[ReentrantReadWriteLock 是通过加锁来保证线程安全的，它是 Java 源码中内置的加锁的类

ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
try {
    lock.writeLock().lock();
} finally {
    lock.writeLock().unlock();
}

那么...]]></description><category></category></item><item><title><![CDATA[RxJava 从源码分析流程]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/81915624</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/81915624</guid><author>hexiaosa91</author><pubDate>Tue, 21 Aug 2018 22:15:22 +0800</pubDate><description><![CDATA[以下面这段代码为示例

public void run(final ThreadListener&amp;lt;T&amp;gt; listener) {
    Observable.create(new ObservableOnSubscribe&amp;lt;T&amp;gt;() {
        @Override
        public void subscribe(ObservableEmitter&amp;lt;...]]></description><category></category></item><item><title><![CDATA[Retrofit 源码分析]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/81714171</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/81714171</guid><author>hexiaosa91</author><pubDate>Thu, 16 Aug 2018 01:17:57 +0800</pubDate><description><![CDATA[Retrofit 使用例子

下面只展示了异步请求示例



Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(&quot;https://api.github.com&quot;)
        .build();

GitHubService service = retrofit.create(GitHubService.class);
se...]]></description><category></category></item><item><title><![CDATA[自定义 View ———— 折线图（重写 onDraw方法）]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/81714157</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/81714157</guid><author>hexiaosa91</author><pubDate>Thu, 16 Aug 2018 01:14:52 +0800</pubDate><description><![CDATA[实现一个如下效果的折线图 
 
这样的效果实现的方式很容易想到的就是重写 onDraw 方法，给定一组 float 值，分别画点、线，那么下面有颜色的阴影部分是用什么画呢，就用到了 Path, 一个点一个点相连成一个封闭的图形，便可画出这个图形。如果先画点，再画阴影部分，是会把点遮住一部分的，所以实现的时候先画完了阴影部分，再画线和点。不过这样子在 onDraw 方法里就有两个 for 循环，如果...]]></description><category></category></item><item><title><![CDATA[Toast 源码分析]]></title><link>https://blog.youkuaiyun.com/hexiaosa91/article/details/81675098</link><guid>https://blog.youkuaiyun.com/hexiaosa91/article/details/81675098</guid><author>hexiaosa91</author><pubDate>Tue, 14 Aug 2018 21:37:42 +0800</pubDate><description><![CDATA[思考

在分析源码之前有两个问题


子线程直接使用 Toast 时会抛出异常 “Can’t create handler inside thread that has not called Looper.prepare()”, 在 Toast 类里搜 “Looper” 并搜不到。是哪里抛出的这个异常呢？
在子线程中这样使用 Toast:




Looper.prepare();
Toast.m...]]></description><category></category></item></channel></rss>