自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(87)
  • 收藏
  • 关注

原创 Kotlin协程Channel使用

一、Channel1、定义Flow是冷流,本质上可以说是一个单线程操作,只有开始收集时,上流代码才会启动;而Channel是一个并发安全的队列,可以用来连接不同的协程,实现不同协程之间的通信。 2、基本使用runBlocking { val channel = Channel<Int>() GlobalScope.launch(Dispatchers.IO) { channel.send(10) delay(1000)

2021-12-29 15:20:11 1416

原创 Java中volatile关键字理解

1、Volatile定义一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:1、保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。2、禁止进行指令重排序。先看一段代码,假如线程1先执行,线程2后执行:// 线程1boolean stop = false;while(!stop){ doSomething();}// 线程2stop = true;这段代码是很典型的一段代码

2021-12-28 15:07:38 306

原创 Kotlin协程Flow使用

一、冷流Flow1、基本概念Flow 能够返回多个异步计算的值Flow 就是 Kotlin 协程与响应式编程模型结合的产物,与Rxjava非常像,Flow 提供了很多丰富的操作符,例如 map、fliter、count 等等,相比 Rxjava ,Flow 的使用和线程切换更为简单冷数据流Flow与热数据流Channel更好相反,Flow是不消费则不生产2、创建// 方式一flow<String> { emit("Hello") delay(5000)

2021-12-01 14:53:31 3193

原创 Kotlin协程基础

1、协程基本概念协程就像非常轻量级的线程。协程让异步逻辑同步化,杜绝回调地狱,代码逻辑非常简洁易懂相对于线程切换是由操作系统进行调度的,程序员无法进行控制。而协程的调度是由程序员在代码层面上进行控制的,程序员可以通过控制suspend函数的挂起和恢复,从而控制程序运行流程 2、协程挂起与恢复挂起(suspend),用于暂停执行当前协程,并保存所有局部变量恢复(resume),用于让已暂停的协程从其暂停处继续执行挂起函数,被suspend修饰的函数称为挂起函数;挂起函数只

2021-11-18 19:33:09 2607

原创 Android屏幕刷新机制原理分析

基本概念CPU:执行应用层的measure、layout、draw等操作,绘制完成后,将数据交由GPUGPU:处理数据,将数据发送到缓冲区屏幕:由一个一个像素组成,以固定频率(1000ms,60次,即16.6ms一次)去缓冲区里读取数据填充像素点双缓冲机制看完上面的流程图,我们很容易想到一个问题,屏幕是以16.6ms的固定频率进行刷新的,但是我们应用层触发绘制的时机是完全随机的(比如我们随时都可以触摸屏幕触发绘制),如果在GPU向缓冲区写入数据的同时,屏幕也在向缓冲区读取数据,会发生什么情况呢?

2021-11-14 13:47:47 3135

原创 Kotlin高阶函数

1、高阶函数定义函数的参数接收的是另一个函数,或者返回值是另一个函数类型,我们把这类函数称为高阶函数2、函数类型字符串的类型用String表示,整型用Int表示,那么函数的类型呢?// 参数block接收的是函数类型,该函数具体是无参,返回值为Unit的函数fun start(block: () -> Unit) {}// 参数block接收的是函数类型,该函数具体是有一个String类型参数,返回值为Boolean的函数fun start(block: (String) ->

2021-11-14 08:37:15 1730

原创 EventBus源码阅读

1、使用/*** 页面A*/// 注册EventBusEventBus.getDefault().register(this);@Subscribe(threadMode = ThreadMode.MAIN)public void callBack(String s) { // 事件处理}// 注销EventBus@Overrideprotected void onDestroy() { super.onDestroy(); EventBus.getDefault

2020-08-21 13:23:14 131

原创 TreeMap实现原理及源码浅析

一、简介TreeMap是一个线程不安全,有序的键值对集合,因为TreeMap实现了SotredMap接口。底层是一个红黑树的数据结构,每个key-value都作为一个红黑树的节点。如果在调用TreeMap的构造函数时没有指定比较器,则根据key执行自然排序。这点会在接下来的代码中做说明,如果指定了比较器则按照比较器来进行排序。此外,TreeMap的Key是不能为null的,因为要实现排序。而Value是允许为null的。二、数据结构/*** TreeMap*/public class Tree

2020-08-16 10:18:32 559

原创 数据结构之树的基本概念学习

一、树的基本概念1、结点的度:一个结点拥有子树的个数称为度。比如A的度为3,C的度为2,H的度为0。度为0的结点称为叶子节点(D,F,G,H)。树的度是树中所有结点的度的最大值,此树的度为3。2、树中结点的最大层次成为树的深度或高度。此树的深度为4。3、父节点A的子结点B,C,D;B,C,D也是兄弟节点二、二叉树二叉树是每个节点最多拥有两个子节点的树。1、二叉树的遍历前序遍历(前根遍历):根——>左——>右,ABDEC中序遍历(中根遍历):左——>根——>右,DB

2020-08-15 22:11:10 391

原创 Rxjava操作符使用

一、简介Rxjava是基于事件流调用的方式来实现异步的库,它最大的特点就是哪怕逻辑很复杂,依然能保持简洁和优雅。异步操作很关键的一点是程序的简洁性,因为在调度过程比较复杂的情况下,异步代码经常会既难写也难被读懂。其原理是一种扩展的观察者模式。这里有四个角色:被观察者(Observable) ==> 产生事件观察者(Observer) ==> 接收事件,并给出响应动作订阅(Subscribe) ==> 连接被观察者和观察者事件(Event) ==> 被观察者 & 观察

2020-08-11 22:57:05 404

原创 Retrofit源码学习

老规矩,从使用的角度深入源码。一、创建Retrofit对象Retrofit retrofit = new Retrofit.Builder().baseUrl(url) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(

2020-08-09 17:51:40 163

原创 Retrofit注解使用大全

一、简介二、注解两张图片均来自简书,https://www.jianshu.com/p/a3e162261ab6GET请求使用public interface ApiService { /** * 最简单的GET请求,无参数 */ @GET("api/fetch/guesslike") Call<GuessLikeEntity> getInfo1(); /** * GET请求,带请求参数 * 请求参数用@

2020-08-09 10:13:45 930

原创 Java设计模式之行为模式

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。一、策略模式记得在中学时代,每次考完老师评讲试卷,都会说这道题有多少种解法,然后在黑板上板书第一种、第二种解法。其实这个情况就类似于今天的情况,也就是策略模式。他表示的是在遇到一种问题有多种解法的时候,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。/** * 旅行策略的抽象接口 */public interface Travel

2020-08-08 11:49:15 259

原创 Java设计模式之结构型模式

什么是代理?什么是静态代理?什么是动态代理?举个例子:车站(被代理)需要卖票,为了方便更多的客户,车站在很多地方找了第三方的合作机构进行卖票(这个角色就是代理),票卖出去之后,第三方机构会抽取一定的提成,同时也需要提供除了票以外的一些其他售后服务,在这里第三方机构就是代理。所谓的静态代理就是,全国各地除了车站外还要多设置100个售票的地方,而这100个地方就需要找100个第三方机构来管理和卖,这种形式就静态代理,成本较高。假设找一个第三方机构,让它一个去管理这100个地方的售票和售后服务,在不同的地方切

2020-08-08 11:29:17 249

原创 Java设计模式之对象创建型模式

一、建造者模式1、简介将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。和工厂模式的区别是:工厂模式一般都是创建一个产品,注重的是把这个产品创建出来就行,只要创建出来,不关心这个产品的组成部分。从代码上看,工厂模式就是一个方法,用这个方法就能生产出产品。建造者模式也是创建一个产品,但是不仅要把这个产品创建出来,还要关心这个产品的组成细节、组成过程。从代码上看,建造者模式在建造产品时,这个产品有很多方法,建造者

2020-08-07 22:33:17 658

原创 OKHttp调用流程及源码分析

从使用入手,追踪调用代码。使用如下:// 通过Builder模式创建OkHttpClient对象OkHttpClient client = new OkHttpClient.Builder().build();// 通过Builder模式创建Request对象Request request = new Request.Builder().url("").build();// 创建Call对象Call call = client.newCall(request); try { // 同步请求

2020-08-05 23:58:18 261

原创 ConcurrentHashMap源码阅读

一、ConcurrentHashMap与HashMap、HashTable的区别1.HashMap我们知道HashMap是线程不安全的,在多线程环境下,使用HashMap进行put操作有可能引起数据丢失,也有可能因为扩容而导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。2.HashTableHashtable和HashMap的实现原理几乎一样,差别无非是(1)HashTable不允许key和value为null,而HashMap可以(2)HashTable是线程安全的,Ha

2020-08-05 09:04:02 106

原创 HashMap实现原理及源码分析

一、什么是哈希表数组:采用一段连续的存储单元来存储数据。对于指定下标的查找,时间复杂度为O(1);通过给定值进行查找,需要遍历数组,逐一比对给定关键字和数组元素,时间复杂度为O(n),当然,对于有序数组,则可采用二分查找,插值查找,斐波那契查找等方式,可将查找复杂度提高为O(logn);对于一般的插入删除操作,涉及到数组元素的移动,其平均复杂度也为O(n)线性链表:对于链表的新增,删除等操作(在找到指定操作位置后),仅需处理结点间的引用即可,时间复杂度为O(1),而查找操作需要遍历链表逐一进行比对,复杂

2020-08-05 09:03:13 144

原创 Glide源码分析(下)

into方法// DrawableRequestBuilder的into方法public Target<TranscodeType> into(ImageView view) { Util.assertMainThread(); if (view == null) { throw new IllegalArgumentException("You must pass in a non null View"); } if (!isTransfo

2020-08-05 09:02:38 146

原创 Glide源码分析(上)

先来看看Glide基本使用Glide.with(mContext).load(mUrl).into(imageView);那么我们就从with方法开始入手,with方法可以传入Context,Fragment,Activity等// Glide类的with方法public static RequestManager with(Context context) { RequestManagerRetriever retriever = RequestManagerRetriever.get(

2020-08-04 09:49:12 93

原创 Android系统启动流程简析

一、系统启动过程当电源按下时,引导芯片代码从ROM开始执行。加载引导程序BootLoader到内存RAM中。BootLoader是Android系统运行前的一段小程序,主要作用是把系统OS拉起来。拉起系统后,首先启动的是Linux内核,Linux内核启动时会加载驱动,在内核完成设置后会在系统文件里寻找init.rx文件,然后启动init进程。init进程启动后,做了很多初始化工作:(1)创建和挂载启动所需要的系统文件目录,比如挂载用于保存正在运行的进程信息的proc目录。(2)初始化和启动属性服务。

2020-08-04 09:48:49 249

原创 TCP/UDP/HTTP/HTTPS

一、TCP和UDP的区别1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接(如送快递,不管你在不在,先送过去)。2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达。UDP尽最大努力交付,即不保证可靠交付。3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流。UDP是面向报文的,所谓面向报文,是指面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文,因此能够明确区分两个

2020-08-04 09:48:01 269

原创 网络OSI模型简介

一.七层?四层?[OSI模型](Open System Interconnection Reference Model,缩写为OSI),全名“开放式系统互联通信参考模型”,是一个试图使各种计算机在全世界范围内互联为网络的标准框架。1983年,国际标准组织(ISO)发布了著名的ISO/IEC 7498标准,它定义了网络互联的7层框架,也就是开放式系统互联参考模型。1.为什么需要协议?什么是协议(protocol)?通俗的来讲,协议是一种双方都明白或者必须遵守的事先约定,比如说长城上放狼烟,是因为人们已

2020-08-04 09:47:24 1304

原创 IPC、Binder及AIDL原理机制

一、IPC介绍IPC是Inter-Process Communication的缩写,含义是进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程。那么为什么需要开启多进程呢?原因有二,其一是一个应用因为某些原因需要独立运行在某个进程中。其二可能是加大一个应用可使用的内存空间,早期的一些版本,一个进程最大的内存空间是16MB。1、Android中开启多进程Android中开启多进程的方法只有一个,那就是给四大组件在Manifest中指定android:process属性,除此之外没有其他办法,也就

2020-08-04 09:46:44 317

原创 HandlerThread、IntentService基本使用

一、HandlerThread实现异步通信HandlerThread实际上就是使用了Thread+Handler进行封装而已,从使用的角度会比直接用Thread+Handler的形式刚便捷。1、子线程向主线程发送消息final Handler mainHandler = new Handler(getMainLooper()) { @Override public void handleMessage(Message msg) { // 这里处理会在主线程

2020-08-04 09:46:17 157

原创 Future及AsyncTask源码解读

一、FutureTask及Future的使用一个可取消的异步计算,FutureTask提供了对Future的基本实现,可以调用方法去开始和取消一个计算,可以查询计算是否完成,可以获取异步计算的结果。1、基本使用方式一// FutureTask需要一个Callable对象FutureTask<String> task = new FutureTask<>(new Callable<String>() { @Override public String

2020-08-04 09:44:39 143

原创 Java线程池流程及源码简析

一、为何要使用线程池// 创建并开启线程Thread t = new Thread(){ @Override public void run() { }};t.start();// 使用单线程线程池ExecutorService service = Executors.newSingleThreadExecutor();// 往线程池里添加任务service.execute(new Runnable() { @Override public voi

2020-08-04 09:44:15 110

原创 Dart语言语法基础学习

void main(){ // Dart中任何类型都是object的子类,所以默认值是null int value; print(value); // int和double都是num类型 double d = 15.367; print(d); var v = 556; print(v is int); // true // 可变类型dy,object也可以达到这个效果 dynamic dy = "222"; dy = 55; print(dy); /

2020-08-04 09:43:47 172

原创 Kotlin语言基础(下)

8、函数/** * 函数的标准写法如下,Unit表示无返回类型,相当于Java里的void */fun add(x: Int, y: Int): Int { return x + y}/** * 命名参数、默认参数、可变参数*/fun method1(name: String, age: Int, value: Int) {}fun method2(name: String, age: Int = 20, value: Int) {}fun method3(name:

2020-08-04 09:43:25 132

原创 Kotlin语言基础(上)

1、基本数据类型// Byte-8位(1个字节) Short-16位 Int-32位 Long-64位 Float-32位 Double-64位 val aInt: Int = 55 // 默认的整数是Int类型,默认的小数是Double类型val bInt: Int = 0xf250 // 十六进制表示整数,kotlin没有八进制val cInt: Int = 0b01000110 // 二进制表示整数val maxInt: Int = Int.MAX_VALUE // 2的32次方-1,21

2020-08-03 11:14:04 188

原创 View的测量、布局及绘制过程

一、Activity、Window及DecorView关系Activity:页面Window:交互窗口,是一个抽象类PhoneWindow:Window的唯一实现类DecorView:一个页面的根View,继承自FrameLayout既然我们知道整个View的Root是DecorView,那么View的绘制是从哪里开始的呢,我们知道每个Activity 均会创建一个 PhoneWindow对象,是Activity和整个View系统交互的接口,每个Window都对应着一个View和一个ViewRo

2020-08-03 11:11:03 257

原创 View事件分发源码解析

一、View的位置1、Left、Right、Top、Bottomleft = view.getLeft(); // 表示view的左边距离父控件左边的距离right= view.getRight(); // 表示view的右边距离父控件左边的距离top= view.getTop(); // 表示view的上边距离父控件顶部的距离bottom= view.getBottom(); // 表示view的下边距离父控件顶部的距离2、X、Y、TranslationX、TranslationYtran

2020-08-03 11:08:27 228

原创 线程变量ThreadLocal的使用和分析

一、ThreadLocal的基本使用 // 创建一个ThreadLocal对象 final static ThreadLocal<String> mThreadLocal = new ThreadLocal<>(); @Test public void myThread() { new Thread() { @Override public void run() {

2020-08-03 10:59:08 171

原创 乐观锁CAS的简单理解

废话不不多说,先上代码:public class Test { private static int count = 0; public static void main(String[] args) { for (int i = 0; i < 2; i++) { new Thread() { public void run() { for (int i = 0; i < 200; i++) { try { Thread.sleep(1

2020-08-03 10:57:12 354

原创 JVM模式和JMM模型

JVM模式和JMM模型1、Java虚拟机(JVM)模型结构如下(1)程序计数器(线程私有):每条线程都有一个独立的程序计数器,这类内存也称为“线程私有”的内存。记录当前线程执行字节码的位置,存储的是字节码指令地址,如果native方法,则为空。CPU同一时间只能执行一条线程中的指令,线程切换后通过程序计数器来恢复正确的执行位置。(2)虚拟机栈(线程私有):也是线程私有的。每个方法在执行的时候也会创建一个栈帧,存储了局部变量,操作数,动态链接,方法返回地址。每个方法从调用到执行完毕,对应一个栈帧在虚拟

2020-08-03 10:54:20 188

原创 AOP面向切面编程简单使用

一、AOP介绍1、AOP是什么?AOP即为面向切面编程,和Java的OOP面向对象编程一样,都是一种编程思想,一些先行者已经为面向切面编程开发了一套语言来支持。2、AOP的作用是什么?通过预编译的形式和运行期动态代理,来改变原来的执行结果。3、AOP的特点?(1)使原执行逻辑和切面逻辑进行解耦(2)对源代码侵入性低(3)容易扩展辅助功能(比如Android的埋点,跳转前的网络检查,权限检查等等,都不属于面向对象的模块内的东西,但是又是各个模块通用的东西)4、AspectJ的介绍Aspec

2020-08-03 09:12:49 672

原创 编译时和运行时注解实现,案例ButterKnife

运行时注解,反射+注解的形式实现/** * 定义了一个用在属性上的运行时注解 */@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface BindView { int value();}@Retention定义了该注解被保留的时间长短,有三种值可以选择1、SOURCE,表示注解保留在源码层面,编译的后就会被擦除2、CLASS,表示注解只保留到编译阶段3、RUNTIME,表示注

2020-08-03 09:09:56 348

原创 设计模式之单例模式(创建型)

单例模式的核心,就是全局只有一个实例。下面就每一种创建方式分析其优缺点。1.饿汉式/** * 饿汉式 */public class PersonHungry { private static PersonHungry INSTANCE = new PersonHungry(); private PersonHungry() {} public static PersonHungry getInstance() { return INSTANCE; }}饿汉式优点:饿汉式在类加载时

2020-08-03 09:06:51 163 1

原创 Handler消息机制源码简析

Android中实现Handler的两种方式1.UI线程中创建Handler // 创建Handler private Handler mHandler = new MyHandler(); private static class MyHandler extends Handler { @Override public void handleMessage(Message msg) { // 处理消息

2020-08-03 08:43:12 133

原创 Android软件卸载安装分享等

1、APP安装/** * 安装APK * * @param file */ public void installApk(File file) { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW

2014-07-15 15:20:27 622

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除