Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
RecyclerView.Adapter 中有个带有 payloads 参数的函数,由于这个函数不是抽象函数,被很多人忽略了。该函数定义如下: public void onBindViewHolder(VH holder, int position, List<Object> payloads) { onBindViewHolder(holder, position); } 该函数的默认实现会调用 onBindViewHolder(holder, position) 这个抽象函数。 这个 payloads 参数是一个 List 对象,该对象不是 null 但可能是 空的。通过 Adapter 的 notifyXXX 函数的带有 payload 参数的函数可以设置 payload 对象,例如通知一个条目数据变化的函数: public final void notifyItemChanged(int…
译文的GitHub地址:RecyclerView之ItemDecoration由浅入深 译者注:RecyclerView第一篇,希望后面坚持下来 RecyclerView没有像之前ListView提供divider属性,而是提供了方法 recyclerView.addItemDecoration() 其中ItemDecoration需要我们自己去定制重写,一开始可能有人会觉得麻烦不好用,最后你会发现这种可插拔设计不仅好用,而且功能强大。 ItemDecoration类主要是三个方法: public void onDraw(Canvas c, RecyclerView parent, State state) public void onDrawOver(Canvas c, RecyclerView parent, State state) public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) 官方源码虽然都写的很清楚,但还不少小伙伴不知道怎么理解,怎么用或用哪个方法,下面我画个简单的图来帮你们理解一下。 ItemDecoration 图画的丑请见谅,首先我们假设绿色区域代表的是我们的内容,红色区域代表我们自己绘制的装饰,可以看到: 图1:代表了getItemOffsets(),可以实现类似padding的效果 图2:代表了onDraw(),可以实现类似绘制背景的效果,内容在上面 图3:代表了onDrawOver(),可以绘制在内容的上面,覆盖内容 注意上面是我个人从应用角度的看法,事实上实现上面的效果可能三个方法每个方法都可以实现。只不过这种方法更好理解。 下面是我们没有添加任何ItemDecoration的界面…
免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作! 注:本教程由北方和我本人合作翻译。 教程截图: 当我检查其他开发人员的代码时,似乎最常见的错误总是围绕在以Object-C中的内存管理为中心。如果您使用的语言是java或C#,它们会自动为您处理内存管理,但这也会使你对于手工内存管理工作更加迷惑。因此,在本教程中,您将通过一些实践来学习Object-C中的内存管理是如何工作的。我们将讨论引用计数如何工作,并通过学习内存管理的所有关键点来构建一个真实世界的例子——一个关于您喜爱的寿司类型的应用程序。 本教程是针对初学者的iOS开发人员或者时关注这个主题的中级开发人员。废话就少啰嗦了,开始编码。 开始 在xcode开发环境中,打开FileNew Project,选择iOSApplicationNavigation-based Application,并将新项目命名为ProMemFun,执行BuildBuild and Run, 在模拟器中你会看到一个如下空表视图: 比方说,我们希望在这个列表中填入我们喜爱的寿司类型。最简单的方法是创建一个数组来容下每一种寿司类型的字符串名称,然后每次我们显示一行,从数组中放入合适的字符串到表格中。在rootViewController.h中为寿司类型声明一个实例变量,代码如下: #import <UIKit/UIKit.h> @interface RootViewController : UITableViewController { NSArray * _sushiTypes; } @end 通过这个声明,每个RootViewController实例对象将有空间来存储一个指向NSArray数组的指针,这是一个Object-C类,使用这个数组初始化后就不能改变它。如果你需要更改一个初始化后的数组(例如,添加一项后),你应该使用NSMutableArray替代。 也许你会奇怪,为什么我们在命名的变量前面添加一个下划线?这恰好是我喜欢做的事情,这样做有些事情会变得更容易。在后续的关于Objec-C教程中我将讨论我为什么喜欢这么做,但是现在请注意,到目前为止,我们所作的是仅仅添加了一个实例变量,没有做与属性相关的东东,我们把它命名为“以下划线开头”,这只是一个个人的喜好问题,其实它没有做特别的东西。 现在,打开RootViewController.m文件,注释viewDiaLoad,然后设置以下代码: – (void)viewDidLoad { [super viewDidLoad]; _sushiTypes = [[NSArray alloc] initWithObjects:@"California Roll", @"Tuna Roll", @"Salmon Roll", @"Unagi…
1、简述 有段时间没写博客了,写博客的习惯还是应该保持的。 写在前面,要很好的理解SP的工作机制,请一定要先看QueuedWork介绍文章,先了解QueuedWork的工作机制。 本片博客主要是对Android的一个常用组件SharedPreferences(以下简称SP)进行分析,首先分析SP日常使用步骤中,每一步的源码,看看后面发生了什么,然后对SP存在的问题进行分析和寻找解决。 首先提几个问题,如果都能给出答案的同学就可以不用看了,如果还有不知道的,看了文章之后能找出答案并会有所收获。 问题: SP是什么时候读取磁盘的数据?是打开APP的时候还是第一次使用SP的时候?从磁盘读取数据是一次全部xml文件的数据都读出来还是只读当前SP操作的xml。 对于当前SP操作的xml,每次commit/apply提交数据,只是将修改的数据写到磁盘还是将所有的都要写到磁盘。 我们提交的数据有可能还未保存,程序就退出,导致数据丢失吗? SP为什么会有可能造成 “卡顿” 呢?使用apply()的方式修改数据就不会卡顿了吗? 假设一个场景:对于当前SP操作的xml,先使用commit提交一个需要耗时10ms的任务,记为任务1,立即再使用apply提交一个需要耗时5ms的任务,记为任务2。那么任务2一定会在任务1前执行完的结论,对不对? 接下来我们就带着问题,开始源码的分析。 对于SP,我们一般是按如下步骤使用的: //获得SP SharedPreferences sp = getSharedPreferences("test", Context.MODE_PRIVATE); //获得Editor SharedPreferences.Editor editor = sp.edit(); //设置数据 editor.putString("key", "value"); //提交 editor.commit(); //or editor.apply(); 接下来会分析每一步的源码。 在分析源码之前,先看看类的组织关系: public interface SharedPreferences { //监听SP的改变…
本文将会通过具体的业务场景,由浅入深的引出Kotlin的一个bug,并告知大家这个bug的神奇之处,接着会带领大家去查找bug出现的原因,最后去规避这个bug。 现实开发中,我们经常会有将Json字符串反序列化为一个对象问题,这里,我们用Gson来写一段反序列代码,如下: fun <T> fromJson(json: String, clazz: Class<T>): T? { return try { Gson().fromJson(json, clazz) } catch (ignore: Exception) { null } } 以上代码,仅适用于不带泛型的类,对于带泛型的类,如List<T>,我们就要再改造一下,如下: fun <T> fromJson(json: String, type: Type): T? { return try { return Gson().fromJson(json, type) } catch…
前言 之前上传ipa文件到苹果商店时候遇到了好多问题,结合着问题和做的过程中查到的资料,做个总结 准备工作 ios开发者账号 苹果电脑 提交审核的软件,我这里用到的是Transporter 当然你也可以用xcode,应用商店都可以下载 硬件要求 苹果电脑 审核须知 会审核两次 第一次是机器审核几分钟就可以知道审核结果,如果很久都上次不上去那可能是需要科学上网 第二次是人工审核比较慢 但是一般24小时可以知道审核结果,审核失败会提示原因 按照要求修改即可 了解到了上面的信息,我们来看看具体的步骤吧 第一步 申请证书(这一步一般申请一次就行) 直接上链接,非常详细 iOS证书申请参考网站,写的很详细 我就不在这里废话了 第二步 提交到苹果后台(机器审核) 参考步骤如下,我之前是用的Transporter 需要下载两个软件 Transporter和xcode IPA 上传到 App Store Connect 的几种方法 如果链接失效 搜索IPA 上传到 App Store Connect 的几种方法会有很多方法 官网也有提示…
MVP 什么是MVP? 在了解MVP之前可以先观察MVC的架构模式。 MVC中三个组成部分:1. View,即视图中的各个控件;2. Controller,即Activity、Fragment;3. Model,即数据源。 但是日常开发中能够发现,对View层的控制也是在Activity中,这时引入Model层数据源的获取再与Controller层发生交互时,不难发现MVC三层互相都存在持有关系,也就产生了严重的耦合。 图片 而MVP的架构实现就是将控制层下移,View层充当Activity、Fragment的存在,Model层保持原样作为数据源的获取层存在,而View和Model层的通信通过中间人Presenter来完成数据的传递,通过这样的方式达到了解耦的目的。 通信的方式就是互相持有,但中间人对于View层的持有使用弱引用的方式实现,以保证View的及时释放。 内存泄漏 解耦的思想在上面已经有所表述,但解耦的背后还有一个我们非常关注的点 –内存泄漏。这个小模块可以分为两个问题进行阐述:1. 什么是内存泄漏?;2. 使用MVP框架能不能帮我们解决内存泄漏的问题? 什么是内存泄漏? 想来这也是老生常谈的问题了,简单了说原本该释放的东西最后竟然没有释放掉,而引起问题可能是一个变量、一个任务等等。 使用MVP框架能不能帮我们解决内存泄漏的问题? 其实这个问题我们应该这样去进行发问MVP框架能不能帮我们解决View层内存泄漏的问题?如果使用标题的问题,其实这算是一个错误的命题, 那是否能够解决这样的问题呢?可以通过一个非常简单的方法直接进行验证。下面是一段代码示例,一个简单的异步线程延迟任务。 new Thread(new Runnable() { @Override public void run() { SystemClock.sleep(200000); } }).start(); 通过Android Studio集成的Profiler能力,在运行期间就可以直接分析内存信息。 图片 图片 其中有一个打了红框的按钮,点击后可以打印出一段时间的内存分配情况。 你同样可以直接点击对某个时间点进行分析。 这是有两个信息我们去进行关注,View层、Prensenter层、Model层所占用的内存大小。…
1.前言 最近几年关于原生WebView与H5混合开发的项目越来越多,这种开发带来了很多便利,但也会有一些缺点,比如说通过WebView加载H5会有一定的卡顿现象,会影响用户体验。下面本文就此问题一一展开讨论。 2. 场景 根据日常需求一般是通过webView.loadUrl()方法加载指定的网页,其大概流程如下: image.png 创建WebView:通过Java代码创建WebView,设置相关的参数和属性 发起请求:通过底层内核会先检查缓存,然后决定是否创建对应的请求,建立对应的http请求。 页面解析:下载对应的DOM树和相关资源。 内容处理:根据上面的资源和树形结构,进行渲染展示。以上是整个网页请求的大概过程,优化也是在这几个过程中分别作出细致对应的方案。 2.1 创建WebView WebView创建的时机会对整个流程是有影响的,Webview的启动相对来说比较耗时,因此这个时候我们可以采用提前启动Webview,这样就可以在加载网页的时候已经准备好。比如我在做Browser的时候发现有Native页面点击网页icon,启动相对来说比较慢,那么采用的策略就是进入Native页面后,一段时间后提前创建Webview。一开始本以为这样就可以,但是浏览器在tab页面可以新建多个网页加载器,也就是会有多个webview。显然光是提前创建也不太好,后面采用创建一个WebView的池子来管理这些Webview /** * webview 复用池 */ public class WebViewPool { private static final String DEMO_URL = "https://www.baidu.com"; private static final String APP_CACAHE_DIRNAME = "webCache"; private static List<WebView> available…
本文同步发表于我的微信公众号,在微信搜索 OpenCV or Android 即可关注。 协变、逆变 概念 许多程序设计语言的类型系统支持子类型。例如,如果Cat是Animal的子类型,那么Cat类型的表达式可用于任何出现Animal类型表达式的地方。所谓的变型(variance)是指如何根据组成类型之间的子类型关系,来确定更复杂的类型之间(例如Cat列表之于Animal列表,回传Cat的函数之于回传Animal的函数…等等)的子类型关系。当我们用类型构造出更复杂的类型,原本类型的子类型性质可能被保持、反转、或忽略───取决于类型构造器的变型性质。 协变与逆变用来描述类型转换(type transformation)后的继承关系:A、B表示类型,f表示类型转换,A≦ B表示A为B的子类,那么则存在: 当A ≦ B时,如果有f(A) ≦ f(B),那么f叫做协变; 当A ≦ B时,如果有f(B) ≦ f(A),那么f叫做逆变; 如果上面两种关系都不成立则叫做不可变。 具象化 定义Cat、Animal两个类型,且Cat是Animal的子类,类型构造器采用数组的形式: 协变(covariant):一个Cat[]也是一个Animal[] 逆变(contravariant):一个Animal[]也是一个Cat[] 不变(invariant):以上两种均不满足。 总结:假想程序设计语言中的类型为输入,数组、列表、泛型等类型构造器为函数,当函数值与输入正相关时为协变,当函数值与输入负相关时为逆变。父子类关系代表输入的大小。 语言场景 Java Java语言中,数组支持协变,泛型类原生既不支持协变,也不支持逆变。 定义类Dog,类Animal,且Dog为Animal的子类 public static void main(String[] args) { Dog[] dogs…
本文同步发表于我的微信公众号,在微信搜索 OpenCV or Android 即可关注。 前言 微信8.0.0更新以后,大伙玩得不亦乐乎,除了会动的表情,特效的炸弹、烟花等,还有一个亮点就是微信个人状态背景,既可以挂图片,更可以挂视频,给人一种万物皆可短视频的感觉。我也很爱这个功能,但是奈何鄙人才疏学浅,没法制作炫酷的短视频。只能使用去抖音水印工具获取视频积累素材,但是目前接触的去水印工具: 小程序:没广告的不能用,能用的大堆广告 网页:速度慢且操作不便捷。 想想自己是个程序员,得尊重下自己的职业,自己动手丰衣足食。 以下内容,仅供学习娱乐使用。 思路 1. "抖音",复制链接 今年的《恭喜发财》,我唱给你听%全民恭喜发财 复zhi此链接,打开Dou音搜索,直接观看視頻! 2. 解析出视频地址 3. jsoup模拟手机请求获取重定向后链接 注意带上User-Agent的请求头:Mozilla (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit (KHTML, like Gecko) Chrome Mobile Safari https://www.iesdouyin.com/share/video/6921725900140612878/?region=CN&mid=6921726283215112974&u_code=66201706&titleType=title&did=70883212011&iid=897618492003052&utm_source=copy_link&utm_campaign=client_share&utm_medium=android&app=aweme 4. 截取出item_ids ,也就是video后的数字…