自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

锐意进取,希望每天都有新收获

  • 博客(51)
  • 收藏
  • 关注

原创 程序员自由职业的第一单,我踩了哪些坑?

Hello,大家好,我是吹白,今天来聊一聊我自由职业之后接的第一个单子以及这个单子带给我的经验教训,希望对大家避坑有所帮助

2023-06-08 11:49:43 560 1

原创 程序员自由职业接单,那些平台比较靠谱?

自由职业三年的程序员,一一为你讲述这些年国内接单平台的使用体验

2023-06-06 19:15:51 1568

原创 程序员接单,那些单子需要特别注意?

众所周知,国内各行各业都在卷,程序员更是卷王里的佼佼者!所以在接单这方面也是严重的僧多粥少,其中还有很大一部分是不靠谱的单子,那么那些单子需要特别注意呢?这里给大家分享一下我这几年来总结的一些经验,希望对大家有一点帮助。

2023-06-11 09:37:43 213

原创 Android中实现类似HTML map标签的图片热区功能

在Android中实现类似HTML map标签的功能,点击不同区域执行不同的操作

2022-10-25 11:55:27 1269 1

原创 Flutter日志插件log4f:基于Android Log和iOS NSLog,封装Logan,App也可查看日志

1. 它是什么log4f是一个Flutter插件,调用了原生的日志方法。Flutter原生的日志不太友好,而且DEBUG Console输出没有颜色;现成的一些插件又多是做一些格式化的封装,这些“格式化”在我看来很多都是多余的。所以我自己写了一个非常简单的日志插件,在Android平台上调用了android.util.Log的相关方法,在iOS上调用了NSLog方法,使用平台的Native代码打印日志。2. 怎么用基本使用Log4f.log("v", "tag", "msgmsgmsgmsgmsgm

2021-10-22 12:21:50 2143

原创 Glide的基本使用及简单源码分析

1、概述Glide可以说是目前最常用的Android图片加载框架,类似的框架还有Picasso、Fresco和UniversalImageLoader等。另外volley也是有图片加载的功能的,只是volley太久没用,都忘记了。这些框架里,最推荐使用的就是Glide,因为它使用的人最多、依旧在不断地更新维护且不需要使用框架定制的View。那么Glide有哪些能力呢?且看:占位符:在加载目标图片成功之前,先展示一个默认的图片而不是一片空白,提升用户体验图片变换:在加载图片成功后,可以先对图片进行某

2021-07-07 20:30:11 1097 2

原创 Kotlin协程入门

1、概述最开始准备学习协程的时候,网上铺天盖地的文章都在宣传“Kotlin协程是一种轻量级的线程”,因为官方确实也是这么说的。我非常疑惑,因为从语文的角度分析,去掉定语之后,就是“协程是线程”。既然协程是线程,那么线程是变成协程之后,怎么就轻量级了呢,是占用的资源少了?学完之后发现,其实协程的本质是个异步框架,只是与RxJava等其他异步框架不同的是,它是语法级别的异步框架,也可以说是一个更方便的线程API集合。用不用协程对于资源开销来说是没什么区别的,与使用线程池相关API相比也没有明显的效率上的区别,

2021-07-04 20:51:25 443 2

原创 Android分区存储

1、分区存储概述分区存储是Android 10开始引进的Android系统存储管理机制,它允许App读取和写入App自身创建的文件而不需要任何存储权限。其中根据存储位置的不同,可以分为内部内部存储和外部存储。内部存储就不用多说了,而外部存储又分为私有空间和公共空间。私有存储空间位置是/sdcard/Android/data/包名,而公共空间则是相册、下载等。对我们开发者影响最大的就是对于公共存储空间的读写了,总结如下:对于9.0及以下的版本,仍然使用READ和WRITE权限,之前怎么做,现在还是怎么做

2021-06-29 17:50:12 3250 3

原创 Android屏幕适配

关于屏幕适配,比较好的文章,大佬们总结得很好了,不自己动手写了。今日头条的方案最简单粗暴,低侵入今日头条适配方案:https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwAhttps://juejin.cn/post/6844903661819133960smallestWidth限定符:https://www.jianshu.com/p/1302ad5a4b04https://juejin.cn/post/6844903681524006925

2021-06-28 18:47:23 113 2

原创 Android布局优化

布局优化主要有以下方向:减少布局层级减少inflate布局的时间,原生加载XML的方式需要IO + 反射操作减少过度绘制可以使用工具:Layout Inspector:查看当前布局层级systrace:查看每一帧的时间和方法调用Choreographer:接收vsync垂直同步信号,可以用来计算帧率LayoutInflater.Factory/LayoutInflater.Factory2: 获取每个View创建的耗时布局层级优化方式使用ConstraintLayout减少布

2021-06-27 10:58:53 1252

原创 Android内存优化

1、内存优化概述我们最常见的内存问题有以下几种:内存抖动:短时间内频繁分配和回收内存,直观表现是内存曲线呈现锯齿装内存泄漏:仍然持有实际上已经没用的对象导致它不能被回收内存溢出:可用内存不足,会导致程序崩溃我们排查内存问题,可以使用以下一些工具:Android Studio的profilerMemory Analyzer(MAT)LeakCanary开源库2、内存抖动实战模拟内存抖动class MainActivity : AppCompatActivity() {

2021-06-26 16:09:41 216 1

原创 Android启动优化

1、概述Android启动优化主要优化的是App的启动时间。App启动开始时机无疑是需要启动这个App为我们提供服务的时候(从Launcher界面点击图标打开或者从其他应用跳转等等),但是关于启动结束时机不同人有不同的理解,有的人认为第一个Activity创建完成之后就算启动完成,有的人认为View首次被渲染完成之后就算启动完成,也有的人认为只有用户关心的内容首次展现才算启动完成(比如说新闻App把新闻列表加载出来)。从用户的角度来看,以后一种比较贴合。App的启动可以分为三种类型:冷启动:从创建进

2021-06-26 12:31:09 1666

原创 选择排序算法思想及示例(C语言实现)

选择排序算法思想:找到数组中从下标0开始的最小的元素,把它和第一个元素进行交换找到数组中从下标1开始的最小的元素,把它和第二个元素进行交换依次类推示例代码:#include <stdio.h>void swap(int* i, int* j) { int temp = *i; *i = *j; *j = temp;}void sort(int* N,int n) { for (int i = 0; i < n; i++) {

2021-06-22 10:52:07 251

原创 直接插入排序算法思想及示例(C语言实现)

一、算法思想直接插入排序的主要思想是:把数列分成两部分,前面部分为有序区,后面部分为无序区,初始时有序区只有第一个元素,一个数字组成的数列当然是有序的遍历无序区,把其中每个数不断地插入有序区,形成一个更大的有序区,遍历完成时整个数列也就有序了算法步骤:假设数组N是待排序的数组,初始时认为N[0]是有序的,那么遍历N[1]到N[n-1]遍历到N[i]的时候,前面的数列已经是有序的了,那么把N[i]与N[i-1]…一直往前比较,用j来记录与其比较的元素下标,每次比较j自减,循环结束的时候可能出

2021-06-20 00:17:25 3943 4

原创 快速排序算法思想及示例(C语言实现)

一、主要思想快速排序的主要思想是分治法,也就是把问题分解成若干个小问题求解,然后把小问题的解合成问题的解。快速排序的算法步骤如下;①从数列中取出一个数作为基准数;②把所有小于基准数的全部挪到左边,把所有大于基准数的全部挪到右边;③对基准数左右两部分分别重复步骤①和②。一次基本步骤的演示过程:原始数列:①取第一个数作为基准数,用临时变量x记录下来,x=56②用i,j分别从数列头和尾遍历数列,初始化时i=start(开始位置),j=end(结束位置)(如果start >= end 直接

2021-06-19 22:47:09 4203

原创 冒泡排序算法及其改进(C语言实现)

一、经典冒泡算法假设有n个数需要排列成非递减数列。冒泡算法的主要思想是①比较第一个与第二个数,如果第二个数小于第一个数则交换,否则不交换;然后以同样的规则比较第二第三个数,以此类推,比如这样就完成了一趟排序,通过不断地交换,第一趟排序进行了n-1次比较就把最大的数交换到了最后。②遵循①中的规则进行下一趟排序,由于最后一位已经确定是最大值,则第二次只需要n-2次比较既可以把第二大的数交换到倒数第二个位置。③以此类推,第i趟排序需要经过n-i次比较其算法具体实现如下:#include <s

2021-06-19 22:01:48 5785 6

原创 RecyclerView源码分析(二):RecyclerView的缓存与复用机制

1、开篇在上一篇文章说到,LineaLayoutManager在填充布局之前会先调用detachAndScrapAttachedViews方法先暂时回收子View,然后在layoutChunk中进行子View的获取(可能会创建View)、测量、布局以及回收流程。实际上三大LayoutManager的流程都是一样的,只是细节上有所差异,感兴趣的同学可以阅读一下源码看看。本篇中涉及LayoutManager的部分依旧会以LinearLayoutManager为例。回顾一下本系列要解决的问题:既然是个Vi

2021-06-19 11:01:58 489 1

原创 RecyclerView源码分析(一):RecyclerView的三大流程

1、开篇我们都知道RecyclerView是一个具有缓存机制的列表控件,它会在适当的时机对滑出屏幕的View进行回收和重用,避免创建大量的View,从而达到高性能的目的。作为Android中使用最高频的组件之一,我们非常有必要了解一下它背后的实现原理和使用相关注意事项。通过源码分析它的流程,是了解RecyclerView的重要手段。注意的是阅读源码一定要带着问题去阅读,只关心主流程,不要被淹没在源码的汪洋大海。因为仅仅RecyclerView.java这个文件就有一万三千多行代码,不要试图搞清楚每一样代码

2021-06-18 11:07:51 321 1

原创 android四大组件之Service(二):前台服务

Android前台服务是指可以与用户交互的服务,典型示例是音乐播放器,用户可以通过开发者在通知栏设置的自定义通知来操作播放暂停上一首下一首等操作。前台服务创建示例:class ForegroundService : Service() { override fun onBind(intent: Intent) = MyBinder() override fun onCreate() { super.onCreate() setForeground()

2021-06-15 19:32:27 927 3

原创 Android 11 PackageManagerService源码分析(二):Packages.xml详解

1、开篇在上一篇文章中提到Settings类会在PackageManagerService启动过程中对packages.xml等一些列xml文件进行解析。那么有以下问题:这些文件记录了什么内容?为什么需要这些文件?让我们一起通过阅读源码解决这些问题吧。2、packages.xml文件详解要在真机上拿到packages.xml殊为不易,所以我这里是在模拟器上通过adb命令拉取了一份:adb pull /data/system/packages.xml文件内容精简后如下:<?xml

2021-06-09 10:34:29 1618

原创 Android 11 PackageManagerService源码分析(一):PMS启动的总体流程

本文并非从上帝视角来描述PMS的总体设计和运行逻辑,而是记录本人阅读源码的一个过程。分析到后面才会出总结性的文章。1、 PMS概述PMS是Android系统中负责安装包管理的服务,它的主要职责如下:管理系统安装的所有应用程序,包括升级、安装、卸载根据Intent匹配相应的Activity、Service、Provider和BroadcastReceiver等,并提供相关信息解析应用权限,在App调用系统接口的时候,检查App是否具有相应的权限这里所指的PMS包括PackageManag.

2021-06-08 12:06:51 3138 1

原创 Android网络请求框架OkHttp源码分析

1、开篇阅读源码要有目的,关于OkHttp,我们要搞清楚以下几点:OkHttp网络请求的流程;拦截器的作用及执行流程(责任链);OkHttp缓存控制;OkHttp的连接复用机制。本文基于写作时的最新的OkHttp 4.9.1版本。2、OkHttp的使用OkHttp的使用步骤如下:构建OkHttpClient对象,可以有两种方式// 方式一,直接newval client = OkHttpClient()// 方式二,Builder模式val client = OkHttp

2021-06-03 15:02:48 232

原创 EventBus源码分析

1、事件总线框架设计站在设计者的角度思考,如果我们要动手设计一个Android事件总线框架,需要注意哪些问题和实现哪些功能呢?既然是事件总线,那么所有订阅者只需要向总线注册自己需要订阅的事件,然后等待相应的事件到来即可;而发布者只需要向总线发布事件而不需要关注谁处理、怎么处理这个事件;线程调度,无论事件是由哪个线程发布的,订阅者总是可以在合适的线程处理该事件;sticky粘性事件,订阅着也许需要知道在向总线注册前被发布到总线上的事件,在订阅者向总线注册之后向其发送事件;订阅者可能会有优先级,让优

2021-05-26 09:04:17 110

原创 Android RecyclerView使用入门

1、RecyclerView关键类介绍在Android开发中,只要有列表页,基本上就是RecyclerView。RecyclerView非常强大、非常灵活且非常重要。在RecyclerView出现之前其实已经有ListView和GridView等列表控件了。但是由于它们的使用相对复杂,对实现动画等各项定制难度较大,不利于实现业务需求,RecyclerView诞生了。关于RecyclerView有以下几个关键的类:Adapter:适配器模式中的适配器,开发者需要自定义一个Adapter的子类并设置给R

2021-05-18 15:23:07 434 3

原创 Android Scroller的使用

1、scrollTo和ScrollByView类定义了两个用于滚动View内容的方法:scrollTo和scrollBy:/** * Set the scrolled position of your view. This will cause a call to * {@link #onScrollChanged(int, int, int, int)} and the view will be * invalidated. * @param x the x position to scrol

2021-05-17 15:42:11 287

原创 Android BLE开发详解

1、开篇本文将主要讲述Android应用开发中对BLE API的使用。Android 4.3(API 18)开始支持蓝牙4.0,但此时Android手机只能作为中心设备或者说主设备,不能作为从设备。Android 5.0(API 21)以后,Android开始支持从设备模式。Android 4.3和5.0以后的API会有一些差别,本文实例会使用5.0以后的API。本文会分别讲解主设备和从设备两种模式下的开发流程。2、从设备模式先从从设备模式开始,从设备的工作是发送广播,等待主设备发起连接,双方通过约定

2021-05-16 13:10:44 2090

原创 低功耗蓝牙(BLE)基础知识概述

1、开篇低功耗蓝牙的概念以及低功耗蓝牙为什么能做到低功耗,蓝牙基础知识概述经典蓝牙和低功耗蓝牙的区别中就可以看出来了,这里就不多说了。本篇文章主要介绍BLE应用层开发中常见的一些概念以及BLE广播包的格式。2、相关名词解析BLE应用开发过程中,我们常常会看到以下一些名词,很多人不知道它们是什么,这里说说我自己的理解。如果读者暂时不能理解以下概念,也没关系,可以看看后面的Android BLE开发实战相关的文章。后续的文章如果看懂了,这些不懂也问题不大。反正我的理解也不一定对~2.1 主机和从机主机

2021-05-15 08:53:17 6163 6

原创 蓝牙基础知识概述

1、经典蓝牙与低功耗蓝牙(BLE)蓝牙是一种近距离无线通信技术,现在由蓝牙技术联盟(SIG)负责制定各项规范和推广、认证等各项事宜。我们目前接触和使用的蓝牙可以笼统地划分为两种:经典蓝牙和低功耗蓝牙。简单来说,蓝牙4.0之前的版本称为经典蓝牙,4.0及以上的版本称为低功耗蓝牙。当然了,经典蓝牙和低功耗蓝牙不仅仅是单纯版本号不同,两者之间的区别还是比较大的:广播信道(射频通道):经典蓝牙使用传统蓝牙使用1632个频段进行广播,而BLE仅使用3个广播频段(3739);射频开启时间:经典蓝牙22ms,低

2021-05-14 12:00:33 4660

原创 Android 11 源码分析之View的测绘流程开始时机:如何在onCreate中获取View的宽高?

1、开篇我们在使用Activity的时候,常常会有在onCreate或者onResume方法中获取View的宽高的需求,但是如果我们直接调用View.getWidth()和View.getHeight()获取到的值是0,很明显此时View的测量工作还没有开始。那么问题来了:View的测量、布局和绘制流程是在什么时候进行的?怎么在onCreate或者onResume方法中获取View的正确宽高?注意:本文分析的是android.app.Activity类的源码,不是androidx.appcom

2021-05-13 18:03:53 318 1

原创 《深入理解Java虚拟机》读书笔记:第2章 Java内存区域与内存溢出异常

1、概述Java虚拟机在执行Java程序的过程中会把它管理的内存区域划分成不同的区域。这些区域都有各自的用途以及创建和销毁时间,有的区域随着虚拟机进程的启动而存在,有的区域以来用户线程的启动而建立和销毁。Java虚拟机内存管理划分如下图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kwzYvIbh-1620832056530)(jmm.jpeg)]2、程序计数器程序计数器是一个较小的内存区域,它是线程私有的内存,可以看作是当前线程执行的字节码的行号指示器。一个处理器

2021-05-12 23:09:17 193 3

原创 ActivityThread源码分析

1、问题Android 11 Launcher启动流程分析说过,Android App进程的入口是“android.app.ActivityThread”,那么:ActivityThread在Android App中充当一个什么样的角色?它是怎么创建Application的?Application的生命周期是怎样的?第一个Activity是怎么启动的?2、ActivityThread#mainAndroid 11 进程启动分析(一)中可以看到,Android进程创建(fork)之后都会调用入

2021-05-12 19:45:30 890 1

原创 《深入理解Java虚拟机》读书笔记:第7章 虚拟机类加载机制

1、概述我们知道,Java文件编译后会生成后缀名为“.class”的字节码文件,虚拟机把这些”.class“文件中类的描述信息加载到虚拟机并经过校验、转换解析和初始化最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。与C、C++等需要在编译时期进行连接的语言不同,在Java语言里,类的加载、连接和初始化过程都是在程序运行期间完成的。这种策略会牺牲一定的新能,但是带来了非常大的灵活性。我们既可以使用Java预定义的加载器,也可以使用自定义的加载器;可以在运行时加载网络上、本地磁盘其他目

2021-05-10 20:24:06 180 1

原创 Android任务栈和Activity四种启动模式详解

0、dumpsys命令简介dumpsys命令详情可以查看官方文档,这里只介绍本文用到的具体命令及参数。在终端以下命令可以在终端输出包含“com.sahooz”的任务栈和Activity记录adb shell dumpsys activity | grep com.sahooz其中grep是Linux或者Mac的命令,Windows下应该是adb shell dumpsys activity | findstr com.sahooz输出示例(这里节选了其中一个任务栈【TaskRecord】):

2021-05-10 10:50:51 915 2

转载 Android Context的设计思想和源码分析

原文地址:https://duanqz.github.io/2017-12-25-Android-Context做了好些年Android,终于可以聊一聊既熟悉又陌生的Context了,每个刚入门的Android开发人员都会接触到它;然而要读懂Context的设计哲学,却又要经过好多轮的认知升级。很多时候,大家是感知不到Context的存在的,笔者最开始“被迫”使用Context,是在自定义控件的时候,布局中有一个按钮,点击一次就发送一次广播,其代码片段如下所示:public class Custom.

2021-05-09 15:01:47 510

原创 Android 11进程启动分析(二):Launcher启动流程分析

上篇说到,Launcher是在ActivityManagerService#systemReady方法中启动的public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) { ... if (bootingSystemUser) { mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");

2021-05-08 16:55:02 2479 2

原创 Android Binder机制概述

一、 是什么Binder是Android系统的一个进程间通信的机制。它主要由以下几个部分组成:虚拟Binder设备(/dev/binder)、Binder驱动(内核中的binder.c)、ServiceManager、提供服务的Service、调用服务的Client。Binder设备和Binder驱动实现了进程通信的协议和数据交换的细节,ServiceManager则负责Service的统一管理、Client的鉴权等,Service提供具体的服务,Client请求服务完成自身的需求。二、与其他跨进程通

2021-05-08 08:18:47 1007 1

原创 Android 11 SystemServer源码分析

SystemServer#main上篇说过,system_server进程启动后会调用SystemServer#main方法,SystemServer#main非常的简单public static void main(String[] args) { new SystemServer().run();}我们再看SystemServer#runprivate void run() { try { ... // The system

2021-04-30 17:59:41 696 1

原创 Android 11 进程启动分析(一): Zygote进程

基于Android 11 的进程启动分析

2021-04-29 16:28:07 1884 3

原创 Android自定义view(三):Canvas绘制图片

一、drawBitmapBitmap是我们Android开发者最熟悉有陌生的老朋友了。它是很多内存问题的万恶之源,但我们又常常不用去碰它,而是把关于图片的操作交给Glide之类的框架。这里不详细讲解关于Bitmap的知识,只讲如何在Canvas里绘制它。照例看一下Canvas里关于绘制Bitmap的方法:drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)drawBitmap(Bitmap bitmap, Rect src, Rect

2021-04-14 10:20:29 3685

原创 Android自定义View(二):Canvas绘制文本

一、Canvas绘制文本相关方法Canvas里面有以下几类绘制文本的相关方法:drawText系列,此系列方法为绘制文本的常规方法drawText(String text, float x, float y, Paint paint) drawText(String text, int start, int end, float x, float y, Paint paint)drawText(CharSequence text, int start, int end, float x, fl

2021-04-11 10:25:34 836

空空如也

空空如也

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

TA关注的人

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