三流码奴的自我救赎

0%

Composer是Compose框架的核心组件。顾名思义,它是用来执行Compose函数维护底层数据结构的工具

Compose所使用的数据结构不同于传统View系统使用的树,而是一种基于连续List的数据结构 - Gap Buffer

Gap Buffer

先来看看Gap Buffer的结构是什么样的,举个例子:

  1. [ ]
  2. 这是一种数据结构[ ]
  3. 这是一种[ ]数据结构
  4. 这是一种基于列表的[ ]数据结构
  5. 这是一种基于[ ]列表的数据结构
  6. 这是一种基于[ ]列表的数据结构
  7. 这是一种基于连续[ ]列表的数据结构

这就是Gap Buffer的基本操作,这种数据结构被广泛用在文本编辑中。

其中[ ]代表gap,具有如下特点:

阅读全文 »

代理模式

说动态代理肯定就得先弄明白什么是代理模式。

现在思考这样一个场景:

买一台电脑,直接去官网买是原价,去并夕夕买可以便宜500同时积分,请问你是选择官网还是并夕夕?

在这个场景中,官网就是被代理类,并夕夕就是代理类,代理的行为是卖电脑,可以看出经过了并夕夕的代理同样的商品变得更便宜了。在这个买卖过程中,用户并不需要关心电脑是如何打折的,只是花了钱同时达到了目的。这就是代理模式的应用场景:

代理模式可以在完成主要任务的同时完成一些前置或后置的工作,这个过程对用户透明,用户只需要关心主要任务

代理模式在很多中场景下都发挥了很大的作用,比如Windows中的快捷方式就是一个代理模式的应用,通过将启动程序的操作代理给快捷方式,可以在启动时直接加载快捷方式带有的参数。

两种代理实现方式

代理模式一般分为静态代理动态代理

举个例子,我们现在有一个工作叫卖电脑:

阅读全文 »

Property(属性)

在说BackingProperty之前要先知道什么Property

先考虑一个问题,我们经常说的FieldPropertyVariable到底各自指代什么?

Glossary of Terms (oracle.com)

其实是可以在Oracle官网上找到答案的:

  • Field :类的数据元素,除非特别指明,否则field是非静态的
  • Property : 可设置的一个对象的特点(feature)
  • Variable : 不特别与实例相关的数据元素

通过上面的描述可以看出,其实根据与类实例的相关性,可以将Variable单独考虑。

其余两种则可以通过是对外提供操作来区分Field(不对外提供操作)Property(对外提供操作)

阅读全文 »

什么是 Handler

先来看看文档中是怎么说的:

A Handler allows you to send and process Message and Runnable objects associated with a thread’s MessageQueue. Each Handler instance is associated with a single thread and that thread’s message queue. When you create a new Handler it is bound to a Looper. It will deliver messages and runnables to that Looper’s message queue and execute them on that Looper’s thread.

意思是说Handler是一个用于处理Message和执行Runnable的工具。每个Thread都通过Looper维护一个MessageQueue。每实例化一个Handler都需要绑定一个LooperHandler主要功能就是向MessageQueue中发送MessageRunnable,并在Message被处理的时候执行其中的Runnable

可以看到Handler的背后是一整套的消息流水线机制,而Handler只是我们利用这套机制的入口。

阅读全文 »

Quistion

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例:

给你这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

说明:

你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

阅读全文 »

池化

如果一个对象需要多次使用,并且会同时存在很多个的情况下,如果每个都去重新创建会浪费非常多的性能。
这个时候就需要池化技术来帮助减小多次重新创建的负担。
池化技术的主要目的就是为了减少大量的创建操作导致性能损耗,通过一个对象池来提供复用对象。

为什么需要线程池

线程池是经常使用的线程池化工具。
如果不使用线程池的话,每发生一个请求都需要创建一个新的线程,但如果并发请求的量非常大

阅读全文 »

ThreadLocal

ThreadLocal<T>可以认为是一个绑定到当前Thread的标签。
可以将一个value绑定到这个标签,形成一个Entry存储到由Thread维护的ThreadLocalMap中。

阅读全文 »

什么是内存泄漏

内存泄漏顾名思义,就是本应该被回收的无用资源并没有被正确的回收而导致内存的浪费。想搞清楚到底是什么原因导致这些资源没有被回收就需要对JVM的内存模型,以及JVM的垃圾回收机制有一定的了解。

JVM内存模型

在JVM中主要分为类加载器内存区域(运行时数据区)执行引擎本地库接口本地方法库。我们探究JVM的内存模型以及内存泄漏,这一部分的原理基本都在内存区域中
我们先来看一下这个运行时数据区长什么样:

阅读全文 »

作为Android四大组件中最为基础的组件,Ativity承担着应用和用户交互的基本任务。

Activity是应用与用户进行交互的单一焦点,基本所有Activity都与用户进行交互。所以Activity负责创建一个Window,可以通过setContentView方法加载UI。
Activity经常以全屏窗口向用户展示用户界面,或者可以通过在theme中设置windowIsFloatingflag使之变为一个悬浮窗口,还可以启用多窗口模式,或将窗口嵌入其他窗口中。

Activity在系统中以activity stack的形式进行管理。当一个新的activity启动的时候,一般情况下会被放入当前activity stack的栈顶,成为running activity。一般情况下前一个activity依旧会存于与栈中,但是只要栈顶activity还存在就不会回到前台。
注意在屏幕上看到的Activity可能属于不同的activity stack

阅读全文 »

bit(比特)&byte(字节)

bit叫做或者比特,在计算机中数据都是以01存储的,一个bit就对应一位数字
byte叫做字节,是比bit更高位的计量单位

  • 1byte = 8bits

java中的基本数据类型

catagory bytes bits 范围($2^n$)
boolean 1 8 $(-2)^7$ ~ $2^7-1$
char 2 16 $(-2)^{15}$ ~ $2^{15}-1$
—- —- —- —-
byte 1 8 $(-2)^7$ ~ $2^7-1$
short 2 16 $(-2)^{15}$ ~ $2^{15}-1$
int 4 32 $(-2)^{31}$ ~ $2^{31}-1$
float 4 32 $(-2)^{31}$ ~ $2^{31}-1$
long 8 64 $(-2)^{63}$ ~ $2^{63}-1$
double 8 64 $(-2)^{63}$ ~ $2^{63}-1$

仔细观察可以发现除了较为特殊的booleanchar之外,其余的类型按占空间从小到大排列,占用控件为:

$2^8$ -> $2^{16}$ -> $2^{32}$ -> $2^{64}$

对于char,在java中无论要表示哪种字符,一个char一定占用2bytes,因为在java中使用Unicode字符集进行utf-16可变长编码,而utf-16形如:u\8D63,可以看到一个utf-16字符占用了4个十六进制数,所以一个char只会占用2bytes的空间

阅读全文 »