自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

黎程雨的博客

粉丝交流群:872206502

  • 博客(406)
  • 资源 (17)
  • 收藏
  • 关注

原创 网易云--手机QQ的换肤是怎么做到的,你对换肤有了解吗?看过换肤的原理没?
原力计划

面试官: 网易云QQ的换肤是怎么做到的,你对换肤有了解吗?看过换肤的原理没?心理分析:没有接触过换肤技术 第一次听到该名词肯定会很茫然。面试官考的是对资源加载,监听布局,有没有了解.本文从换肤实战一对一讲解。告诉你如何做以及实现。文章末尾带换肤项目源码求职者:从监听布局开始到 换肤原理,详细给面试官讲解换肤的原理接下来我们一起分享这篇干货。 Android的主题换肤 ,可插件化提供皮肤包,无需Activity的重启直接实现无缝切换,可高仿网易云音乐的主题换肤。这个链接是本次的D..

2020-06-20 22:46:08 1854 4

原创 Android项目中gradle文件里面的productFlavors一些常用配置

productFlavors的用处1.增加包环境种类项目里面常常会用到很多环境,拿打包来说,一个项目,从开发到正式上线,可能要经过很多阶段.那么,在这些不同的阶段内,要验证Android应用,不可避免的需要打出很多不同环境的包,例如开发环境(dev),测试环境(tes),正式环境(pro). 在这么多的环境中,假如需要配合测试API接口,那么不同环境项目中的API地址会一样吗,肯定不会吧,如果在需要有其他的一些配置信息,每个环境不一样,那每次打包要去手动修改会很麻烦.这时候可以用到productFlav

2021-01-26 22:33:25 7

转载 你应该知道的kotlin实用技巧

好文推荐:作者:RicardoMJiang前言众所周知,kotlin是google力推的用以取代java的android开发语言kotlin使用起来比较方便,同时有许多语法糖本文主要讲解了一些比较实用的kotlin技巧自定义圆角矩形在项目中,我们常常要定义圆角矩形背景,一般是用自定义drawable实现的但是圆角矩形的背景与圆角常常会有细微的变化,而一旦变化我们又要新创建一个drawable文件这样就会导致文件爆炸的问题我们可以利用kotlin的扩展函数,来实现简单方便的圆角矩形背景.

2021-01-25 22:30:56 8

转载 Android组件化跨进程通信框架Andromeda解析

好文推荐:作者:wanderingguy关于组件化随着项目结构越来越庞大,模块与模块间的边界逐渐变得不清晰,代码维护越来越困难,甚至编译速度都成为影响开发效率的瓶颈。组件化拆分是比较常见的解决方案,一方面解决模块间的耦合关系、将通用模块下沉,另一方面做到各模块代码和资源文件的隔离,这样便可以放心进行模块按需编译、单独测试等等。但随之而来的问题也愈加突出,模块的精细化拆分不可避免的增加了模块间的通信成本。通信的两侧是一个C/S架构,如果服务端与客户端同属一个进程我们称之为本地服务,如果分属不同进.

2021-01-22 22:35:49 30

原创 字节瞧不上大龄程序员,我开始慌了……

前段时间,字节的朋友有个新项目,要我推荐靠谱的朋友,然后我就推荐了一个88年的同事老贾。一面的时候,老贾各方面都挺好,问啥都会,后来聊到性能优化问题,答得也还行,至少勉强进了二面。可好巧不巧,二面的时候问了个内存回收机制与GC算法,然后他就答不上来了,据说走的时候几乎落泪…唉!后来跟字节的朋友聊起这件事,他告诉我其实老贾并不是个例,他提醒了我以后面试的几个点,在这里我也分享给大家:当面试官向你问图片的三级缓存中,图片加载到内存中,如果内存快爆了,会发生什么?怎么处理?内存中如果加载一张5

2021-01-20 22:23:21 36 2

原创 Android 进阶延伸技术点,你能答出几个?

1、如何进行单元测试,如何保证 App 稳定 ?参考回答:要测试 Android 应用程序,通常会创建以下类型自动单元测试本地测试:只在本地机器 JVM 上运行,以最小化执行时间,这种单元测试不依赖于 Android 框架,或者即使有依赖,也很方便使用模拟框架来模拟依赖,以达到隔离 Android 依赖的目的,模拟框架如Google 推荐的 Mockito;检测测试:真机或模拟器上运行的单元测试,由于需要跑到设备上,比较慢,这些测试可以访问仪器(Android 系统)信息,比如被测应用程序的上下

2021-01-15 18:50:56 143

转载 丢弃LayoutInspector,换个方式看UI

好文推荐:作者:YvesCheung自从AS升级到4.x后,你的LayoutInspector会不会经常和我一样明明连着设备,却检测不到对应的进程?检阅速度非常慢,直到超时都没有出画面?勾选Live Update后,画面延迟成了PPT,最后放弃Live Update?终于,我放弃了LayoutInspector,选用更轻量的UinspectorUinsepctor是什么?Uinspector 是一个集成在Android应用内的ui检阅工具。开启 Uinspector 后,通过点击屏幕.

2021-01-14 21:06:16 28

原创 面试官:现在还有不会组件化的Android开发?

在正文之前,我们先来看一张电商项目的真实结构图。从上图中,大家能找到什么问题吗?接下来给大家好好分析分析从这个项目结构来看,典型的单一模块、MVC混搭,其实很多架构师都知道,这样的项目随着到了开发后期,会面临着以下几个问题:项目耦合非常严重,类与类之间的关系太杂乱每次修改代码重新编译等待时间过长项目太过于臃肿功能重用异常麻烦不适合多人开发正是因为这些问题的存在,才会让人开发起来越来越累。问题来了,项目已经这样了,怎么才能扭转乾坤呢,其实很简单没错,就是减肥,问题是功能不

2021-01-14 16:08:18 20

原创 字节面试官浅谈:Android面试细节,分分钟变身“offer”收割机!

一 . 前言前段时间,因为我们团队极度缺人,连续面了不少同学,正好借此分享一下自己对面试的一些浅见。谨代表个人观点,如果您觉得哪里说的不好,欢迎指教和批评~二 . 细节杂谈之所以是细节杂谈,说实话,是因为真的不知道可以写什么,网上关于Android面试的文章很多,大概看了几篇之后,更不知道写什么了。而根据自己这么多年来的面人和被面经验来看,发现其实有很多细节,在面试的时候都没有被好好重视起来。所以,这里针对这些细节做个总结,也希望可以对你们有所帮助。1. 准备一个良好的开场白首.

2021-01-12 22:30:33 40

转载 Android 组件化最佳实践 ARetrofit 原理

好文推荐作者:朱壹飞组件化Android组件化已经不是一个新鲜的概念了,出来了已经有很长一段时间了,大家可以自行Google,可以看到一堆相关的文章。简单的来说,所谓的组件就是Android Studio中的Module,每一个Module都遵循高内聚的原则,通过ARetrofit 来实现无耦合的代码结构,如下图:每一个 Module 可单独作为一个 project 运行,而打包到整体时 Module 之间的通信通过 ARetrofit 完成。ARetrofit 原理讲原理之前,我想先说.

2021-01-11 21:29:27 23

转载 Flutter&Android 启动页(闪屏页)的加载流程和优化方案

好文推荐:作者:哈吉达前言现在应用的普遍启动方式为:静态页面 -> 动图 -> 应用首页之所以这样设计的原因,大致如下:1、产品需求,如广告2、品牌展示3、应用规模较大时启动时间较长,相较于白屏,一张图片的过渡效果更好等等…。而Flutter由于引擎的创建和初始化需要一定时间,所以也提供了一个过渡方案(默认是白屏),位置在:AndroidManifest.xml下的<meta-data android:name="io.flutter.em.

2021-01-10 22:43:14 61

转载 Android网络优化攻略,简单了解一下?

作者:究极逮虾户转载地址:https://juejin.cn/post/6896302142542315533面试官:小虾啊,我好想你啊,你都好久没来找我面试了呀。小虾:emmmmmmm,这不是怕被你打击吗。面试官:ok,看来是有备而来,那么我们今天聊聊网络优化咋做吧。小虾:我大意了,没有闪。老头子,你不讲武德,我奉劝你耗子尾汁。1. 如何优化一个网络请求呢?相信大家在面试的时候可能会被问到这个问题。今天我其实就是讲述下我知道的一些简单的优化方式,可以帮助大家在面试的过程中得到点基础分数。.

2021-01-06 22:42:37 31

原创 23岁程序员,毕业一年月薪9000,却焦虑的睡不着?劝你别这么干!

前言最近在网上看到一条帖子,“本人23岁是一名程序员,毕业也有两年了,目前薪资在9K多,在一家不知名的互联网公司任职,每天的工作量不是很多,工作的压力也不是很大”。但是自己非常的焦虑,因为看见很多人在做副业赚钱。自己每天却只能老老实实的敲代码,而且自己感觉做的事情的前景能一眼看得到头,自己也想去寻求副业,但又不知道该如何下手,所以导致自己比较焦虑。在这里小编想跟大家说的是:“千万不要被一些市面上教你如何做副业的人所迷惑”。之所以有许多人去拓展自己的副业,是因为他们的本职工作中已经没有太的升职空间了

2021-01-05 22:54:04 145 1

原创 2021年之Android面经分享(已获头条、顺丰、OPPO等大厂Offer)

作者:莫少侠前言本人水平有限,此文针对于自认为技术实力对标阿里P6,百度T5或者以下的读者,如果是大佬不小心点进来了,可以自行点x略过。文内并不会出现每一家公司的面试过程细节,主要目的在于帮助大家怎么在像我一样菜的情况下在这寒冬拿下offer或者说有复习准备方向。背景介绍11月因公司团队解散而离职,突闻互联网最寒冬又双叒叕来了,什么小厂大量倒闭,大厂裁员或锁HC,慌得一批,惶惶不安准备了一个多星期后,开始踏上面试求职之路,截止最终确定入职单位总计用了二十多天(期间有一半时间在做颈椎康复治疗)。.

2021-01-04 22:40:19 61

原创 赶在2020最后一天,特此奉上一份Android 面经!

前言2020年的最后一份Offer,特此赶在2020的最后一天补上这份面经。本人是某渣院二本毕业,之前在学校学的专业是电商,毕业没两年就开始转行学编程,转眼间在Android 开发行业已经做了5年了。原本自己是在一家中型的互联网公司做Android开发,但自己一直有个想进大厂的梦,于是在2020下半年大胆的开始一些互联网大厂投简历,我投过简历的公司有:华为、Oppo、拼夕夕、字节跳动、腾讯等。但通知我去面试的公司只有3家,其中有两家以失败而告终。第三家本也没有报太大的希望,因为第三家是字节跳动,在面试中

2020-12-31 22:24:07 34

原创 Android事件分发机制

开始的开始当我手指触摸到手机屏幕后,给我所见即所得的触控体验,它的背后发生了什么?出于对它的好奇,就有了这篇文章。因为本人不喜欢大段大段的源码分析,所以本文尽量从设计的角度去把把事件分发机制的脉络,少贴源码是我的目标之一,虽然这么说,但当我把文章写完后最后发现依然贴了不少代码,想删减却没法减少,都是很核心的部分。本博客的主要内容如下:事件分发的整体设计ViewRootImpl的创建应用层级的事件分发流程为了后面更容易的理解事件分发机制,在介绍核心内容前,准备了一些前置知识。前置知识:View

2020-12-30 17:30:47 34

转载 致敬Glide-借用其思想设计一个拍照选图控件

好文推荐:作者:思忆_GeorgeQin内容提要本文内容较长,包含一个功能整个重构从想法到设计以及落地的完整过程,通过阅读本文你可以收获:Glide 几个关键特性的设计原理以及对它们的思考(面试可用)编码从拓展性层面的考虑到面向对象编程的实践类似于RxJava的工作流的设计思想以及实践一些kotlin和Java 互相调用的小技巧一个功能强大的调用系统相机、系统相册的库以及它是如何被设计出来的背景鉴于最近对原有项目进行了老的代码的重构,其中的调用系统拍照选图模块就是我们日常遇到一个.

2020-12-29 22:56:11 30

转载 深入RecyclerView学习—缓存机制

好文推荐:作者:Codeing_ls前言RecyclerView作为替代ListView的组件,得益于RecyclerView的灵活性和可定制程度高的特性。除此之外RecyclerView的预取机制以及缓存机制也是RecyckerView的一大亮点。RecyclerView的灵活性是通过几个不同的组件协同实现的。LayoutManager:是布局管理器,用来决定视图如何填充RecyclerView。RecyclerView.Adapter:适配器是负责提供视图所需要的数据集以及管理视图的创建.

2020-12-28 22:48:32 26

原创 2020Android 开发年度总结:“这一年里我到底做了些啥,掌握了哪些技术?”

前言眼看2020年还有两天就要结束了,即将迎来2021新的一年。感觉今年比起往年要过稍稍的快一些,因为2020的开年工作时间比以往是晚了许多,基本都是在3月份左右开始投入工作。而以往基本都是大年初八左右,人们都开始投入工作了。小编把自己这一年的一些事件进行了总结,请看下方本人是一名Android 开发者,毕业3年,年龄到了人们常说的中年危机的年纪。30岁之前就常常在各大社交博客平台上看到一些程序员中年危机和Android 不行了等相关帖子,刚开始我还是有点慌,在想当初选择走开发这条道路是不是错的?.

2020-12-28 15:07:34 99

原创 程序员年底失业,到底是该年前找工作好还是年后找工作好?

最近在网上看见大家讨论的比较多的话题:“2020年快结束了,如果年底失业,到底是该年前找工作好还是年后找工作好?”其实我对于这个话题的观点是年前找工作比较好。为什么呢?首先因为人都是有种惰性的,一旦我们习惯于某种生活状态,我们其实是很难改变,尤其像我们程序员这种上班族来讲,你如果每天上班加班,习惯于这种状态了,你也就不会觉得怎么累了。其实这就是人的本性,当我们一直处于某一种状态的时候,你想要再去改变是比较困难。所以建议年前失业的朋友,一定要在年前把工作找好。另外从这个从机会的角度来看,年前的机

2020-12-25 22:10:17 246

原创 Android开发这些知识点还没掌握?如何踏上高薪之路!

我所接触的Android开发者,百分之九十五以上都遇到了以下几点致命弱点!如果这些问题也是阻止你升职加薪,跳槽大厂的阻碍。那么我确信可以帮你突破瓶颈!作者2013年java转到Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。被人面试过,也面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!我整理了一份腾讯T3级别的Android...

2020-12-23 17:17:24 29

原创 2020至2021年Android开发面试习题整理,持续更新中

设计模式面试题1.请列举出在 JDK 中几个常用的设计模式?单例模式(Singleton pattern)用于 Runtime,Calendar 和其他的一些类中。工厂模式 (Factory pattern)被用于各种不可变的类如 Boolean,像 Boolean.valueOf,观察者模式 (Observer pattern)被用于 Swing 和很多的事件监听中。装饰器设计模式(Decorator design pattern)被用于多个 Java IO 类中。2.什么是设计模式?你是否在你的代

2020-12-22 21:28:07 201

原创 Android最傻瓜式的AOP框架

前景我们对Android的AOP有了初步的了解,但是其高门槛和学习成本还是让很多人望而却步。今天这里就给大家一个傻瓜式的AOP框架,这可能是Android最傻瓜式的AOP框架了。butcherknife 介绍乍看上去是不是有点眼熟,对我就是为了蹭JakeWharton大神的butterknife框架的热度,哈哈。这里 butcherknife我翻译成“屠刀”,意思是希望用最简单的方式能达到屠刀式的代码织入,能够完美处理Lambda表达式butcherknife 使用butcherknife是通过注

2020-12-22 16:25:44 32

转载 Jetpack架构组件库-LiveData实战与应用-总有适合你的方案

好文推荐:作者:heiyulong原文链接:https://juejin.cn/post/6907121024932773901前言先前针对LiveData 组件从使用到原理都做了充分的解析,可以参考链接:Jetpack架构组件库-LiveData只一篇你就会用Jetpack架构组件库-LiveData工作原理只一篇你就懂可以发现在使用 LiveData 分发数据的时候,是不会耦合任何 Context 对象的,并且是生命周期感知的,所以:这个机制就从框架层避免了 NPE(空指针异常),O.

2020-12-20 22:30:08 46

原创 基于AGP的Android组件化编译插件实践

作者:nebulae-pan概述组件化算是大型项目的一种较好的组织方案,可以很好解藕逻辑,单独编译需求模块方便测试复用,减少维护成本,甚至良好组件化的项目可以无痛过度到插件化。但是其也有相应的缺点,比如模块间需要额外通信手段导致编写复杂效率降低,不同模块需根据版本依赖并作额外管理。为了开发编译插件帮助项目达成解藕、复用、单独编译的目的,一般情况下要提供以下几种功能:单独运行(支持module作为App运行)不同module代码资源隔离(或者仅仅暴露指定接口)资源增加前缀以减少冲突Appl.

2020-12-18 17:56:33 69 1

原创 Android 面试主题集合整理

一、线程、多线程和线程池面试专题1、开启线程的三种方式?1)继承 Thread 类,重写 run()方法,在 run()方法体中编写要完成的任务 new Thread().start();2)实 现 Runnable 接 口 , 实 现 run() 方 法 new Thread(new MyRunnable()).start();3)实现 Callable 接口 MyCallable 类,实现 call()方法,使用 FutureTask 类来 包装 Callable 对象,使用 FutureTa.

2020-12-11 22:34:24 58

原创 程序员的中年危机该怎么度过,只能靠纯技术?

当你还在为35岁焦虑的时候,有些Android程序员已经悄悄度过了中年危机技术水平是一方面,但是并不是唯一一条出路,相比于技术,正确的职业规划路线才是重中之重只是相比来说,技术这条路比较简单,毕竟只要不断进阶就行了~最近有很多文章都在说996,事实上996对年轻人伤害不是最大的,起码还能加的动班,最郁闷的是那些35岁以上的互联网人,他们上有老下有小,身体每况愈下还得996,他们之中有人悄悄度过了中年危机,我们来看看一位40岁的架构师是如何说的。今年刚好40岁,算是非常幸运了,目前在一家世界100强

2020-12-10 20:56:13 67 1

转载 写给 Android 应用工程师的 Binder 原理剖析!

作者:张磊声明转载地址:https://mp.weixin.qq.com/s/NBm5lh8_ZLfodOXT8Ph5iA一. 前言这篇文章我酝酿了很久,参考了很多资料,读了很多源码,却依旧不敢下笔。生怕自己理解上还有偏差,对大家造成误解,贻笑大方。又怕自己理解不够透彻,无法用清晰直白的文字准确的表达出 Binder 的设计精髓。直到今天提笔写作时还依旧战战兢兢。Binder 之复杂远远不是一篇文章就能说清楚的,本文想站在一个更高的维度来俯瞰 Binder 的设计,最终帮助大家形成一个完整的概念.

2020-12-10 20:54:36 33

原创 2020秋招某大厂面试官:刷掉一批又一批的Android开发面试者,有些话不得不跟你们说……

前言该文是主要讲述一下2020这一年的秋招,上半年因疫情原因,大多数人是属于失业状态在家休息,直到下半年才稳定下来,正式这样导致许多找工作人群都挤在一起。从今年的九月份初到十月底,我大概面试了三百多位Android程序员,但因通过率较低,同事老实劝我手下留情。可能是我面试的标准要求比较高吧!下面我就在这大概的讲述一下我面试人的标准,这不是一篇什么攻略文,旨在抛砖引玉,大家一起探讨如何面试更有效率。需要写在前面的是,“平等“和”高效”一直都是互斥的。信息从一个人传递到另一个人那里,由于表达能力和接收能

2020-12-09 22:26:57 46

转载 Android事件分发机制抽象--钓钩模型

好文推荐作者:盛书强用户体验小姐姐巧妙地利用有限的手机屏幕空间,完美地设计出简单实用的交互功能,如果多问一句 “怎么做到的” ?答案必须是从事件分发机制的高超运用说起。在我 Android 应用业务开发职业生涯中,接触到最多的也正是如何运用事件分发机制和自定义控件,堆砌出一幅幅可交互的精致业务功能画面。下图是我分别在手机百度 App 和美团 App 上研发的“列表拖动排序”和“卡片抽屉效果”代表作。2018 年在我编码技战术水平的小巅峰期,创造性将 MECE(Mutually Exclu.

2020-12-09 16:07:59 46

原创 写给Android开发们的一封信

最近半年,常常有人问我 “Android就业市场究竟怎么样,我还能不能坚持下去 ?”现在想想,移动互联网的发展不知不觉已经十多年了,Mobile First 也已经变成了 AI First。换句话说,我们已经不再是“风口上的猪”。移动开发的光环和溢价开始慢慢消失,并且正在向 AI、区块链等新的领域转移。移动开发的新鲜血液也已经变少,最明显的是国内应届生都纷纷涌向了 AI 方向。​可以说,国内移动互联网的红利期已经过去了,现在是增量下降、存量厮杀,从争夺用户到争夺时长。比较明显的是手机厂商纷纷互联网化,

2020-12-08 22:46:12 35

原创 35岁Android开发,还能在程序员这条路上越走越远么?

前言想必不少伙伴担忧的情况——“晋升无望、收入见顶、生活开支飙升、财务危机如影随形”,小编之前精心收录整理了一些关于Android开发的知识点、面试题,推荐给大家化解成长的烦恼。它们都是我平时也经常翻看、学习的一些珍藏资料,包括Java基础、Android进阶、架构设计、NDK、音视频开发、跨平台、底层源码等技术,还有往年一线大厂最新面试题集锦,都分享给大家,助大家学习路上披荆斩棘~ 能力得到提升,思维得到开阔~View说下View 的绘制流程?MotionEvent 是什么?包含几种事件?什

2020-12-08 21:36:29 41

原创 程序员是青春饭吗?30岁后的发展方向和突破

前些年,有人说程序员只能干到 30,后来大家把年龄提到 35,最近好像又有提到 40 的迹象。程序员是青春饭吗很多人都说写代码最多到 35 岁,妥妥的青春饭,然而科学分析不这么认为。《Is Programming Knowledge Related to Age?》论文对 1694981 名 StackOverflow 用户的研究发现,程序员的平均年龄是 30.3 岁,其中数据清洗后参与分析的用户是 84248 名程序员,平均年龄 29.02 岁。在年龄分布中,人数最多的是 25 岁,中位数是 29

2020-12-07 22:17:54 49

原创 2020这一年都快过完了,作为Android程序员你还了解过JetPack?

一、Android JetPack——Google多么痛的领悟最近好几个小伙伴问我什么是Android JetPack,听说这个包好像有点牛,猪哥你会不?我心想什么鬼!Android JetPack这货不是一个库,是一整套的库,是一种信仰一种态度好么。从前,Android开发者基本都是被放养的。生态基本全靠自建,代表有Square全家桶,Glide,Google自己也肯定是出力的,但是并没有明确Android开发的几个大方向,所以安卓的开发生态一直是百花齐放百家争鸣。带来的问题就是经常出现包引用莫名报错

2020-12-07 22:15:56 55

转载 Jetpack|Paging的新增与删除

作者:伍六七_一、整体思路:创建新的数据源装载旧数据以及新增/删除数据。利用List集合进行增加和删除,通过loadInitial将最新的List数据返回给PagedList,最后调用submitList更新数据。以PageKeyedDataSource作为数据源为例,首先新建一个DataSource的类PageKeyedDataSourceExtension继承PageKeyedDataSource,在新的DataSource中创建一个List装载新的数据,也是后续用来增加和删除数据的集.

2020-12-02 22:42:25 78

原创 Android 开发被迫失业在家带娃,一个月后拿下百度Offer

自我介绍本人毕业于某二本渣院,从事Android开发4年,之前是在一家小型的初创工作做Android开发,由于今年公司业绩的下滑比较大,直至今年的九月份左右宣布破产,而我也随之失业了。于是我处于失业状态在家带娃,在一次偶然的机会,我朋友帮我弄到了一个百度Android开发岗位内推的名额,我抱着试一试的心态进行投简历,随着简历投出一个星期没有什么回应,本以为没有机会时,突然接到一个面试通知的电话,心里还有点开心的。于是连忙在家开始疯狂刷题,准备后面的面试。下面是我的面试过程一面(电话面,大约1h)

2020-12-02 22:28:21 95

原创 知乎热榜:找工作时普遍要求35岁以下,网友吐槽:35岁招谁惹谁了!

第一段:在网上,我们总会看到很多关于职场的问题,其中不少是跟经验和阅历相关的。近来,我空闲时间刷起了知乎,看到了其热榜上的一个话题:找工作时单位普遍要求 35 岁以下,那么 35 岁以上的人都去干什么了?看到这个话题,突然想到之前某互联网大厂的 HR 在大学招聘时宣传公司:“我们公司是年轻的公司,平均年龄 25 岁!”结果被学生反问:“那么请问,您公司里面 30 多岁的人去哪了?”直接把原本自信满满的 HR 当场问懵……无数网友纷纷吐槽:35 岁招谁惹谁了要被这样对待,谁不都得经历这个年龄吗?

2020-12-02 18:12:14 73

原创 35岁Android程序员面临失业,是不是该考虑转行了?

这几年,程序员的35岁焦虑,在一些媒体平台上的关注度比较高,有说程序员是吃青春饭的,现在这似乎成为了共识,不仅程序员群体中是这样,在其他行业眼中也是这样。但是这个共识,有一定的误导性,不能说全是对的。就好像说程序员容易秃头,其实是男性到了一定年龄,都容易秃头。有些人说,出来医生、老师等少数几个职业,大部分都是年龄越大越不吃香,尤其是劳动密集型和知识密集型的行业,年轻人总是更受欢迎。我们自己又何尝不是从年轻的时候走过来的呢?刚毕业的时候,因为没有什么工作经验,钱少点、加班多一点也都是愿意去,而工作几年后.

2020-12-01 20:36:29 120

原创 Android App开发之Jetpack架构

还记得15年那个时候,好像Android就是解析数据,列表展示,了解下四大组件生命周期,已经可以干活了,还记得当年一个View只要能滑动,就大呼自定义控件牛逼。不过,近几年的变化颇大。为了丰富大家日常开发的UI效果效果: Material Design进入大家的视野,后面陆陆续续涌现出一大批UI组件:DrawerLayout,AppbarLayout,CoordinateLayout,ToolBar,NestedScrollView,FlexBoxLayout等...在UI组件日益完善的同时,也

2020-11-30 22:18:19 88 1

转载 Android开发面试之RxJava

好文推荐:作者:xiangcman大家都知道RxJava上手是非常难的一个框架,为什么说是难呢,因为它的功能非常强大,各种操作符让人很难上手,搭配使用带生命周期的框架有RxLife等。以至于后面出了很多类似Rxjava的框架,有RxAndroid,我们用的RxJava切换主线程就是出自该框架,后面ACC架构中有LiveData、Lifecycle、包括后面协成中出来的flow异步流,都是向Rxjava靠拢,不过ACC出来的这些框架他们最大的特点就是操作简单,上手简单。所以RxJava强大的框架背后.

2020-11-30 21:52:34 157

WangyiPush.zip

直播详解,可运行,通过rtmp协议实现,直播的详细说明可参考https://github.com/interviewandroid/AndroidInterView/blob/master/android/live.md 关于直播的视频讲解可以加qq 1051917835 免费的 哦

2019-06-22

组件化通信之LiveData.rar

都说新项目组件通信一定用LiveData,我们就从源码层来聊聊LiveData的魅力 内容点: 1.LiveData到底是什么? 2.LiveData源码解读? 3.通过手写LiveData让大家了解更清晰 4.如何将LiveData封装得更加好用?

2020-12-18

FreScon源码下载

FreScon源码下载

2016-06-30

jbox2d愤怒的小鸟游戏源码

jbox2d愤怒的小鸟游戏源码

2016-07-14

resized_img.zip

手势识别图片,主要是训练神经网络图片。用tersorflow实现手势识别

2019-07-12

RabbitMQ消息中间件技术精讲

RabbitMQ消息中间件技术精讲(渐进式,深入RabbitMQ高级特性,手把手,整合RabbitMQ&Spring;家族,高可靠,构建RabbitMQ集群架构,追前沿,领略SET化架构衍化与设计)

2019-02-24

MySQL原理分析与架构设计视频教程

MySQL原理分析与架构设计(数据库索引优化,数据库的分库分表, SQL查询优化,mysql行内锁原理)

2019-02-24

2019Java高级面试专题

2019Java高级面试专题包含(微服务+数据库原理+Java性能优化面试视频)

2019-02-24

rxjava 1.0.14

rxjavah和rxandroid下载

2016-11-23

eclipse svn插件

2016-08-12

sdk build-tool 19.1.0

build-tool 19.1.0 解压到sdk下面的build-tools目录就可以了

2016-01-07

Xcode6.4 beta2 下载

Xcode6.4 ios版 适合mac 10.10以下版本

2015-12-27

cdt插件下载

Eclipse 中CDT插件 将文件解压后 分别放到对应的eclipse目录中的features 和plugins文件夹中

2015-12-27

城市选择器

城市选择器,自动定位,城市列表自动按拼音排序

2015-10-21

可以拨动的时间选择器

直接可以运行。漂亮的时间选择空间 public class MainActivity extends FragmentActivity implements OnDateSetListener, TimePickerDialog.OnTimeSetListener { public static final String DATEPICKER_TAG = "datepicker"; public static final String TIMEPICKER_TAG = "timepicker"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final Calendar calendar = Calendar.getInstance(); final DatePickerDialog datePickerDialog = DatePickerDialog.newInstance(this, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), isVibrate()); final TimePickerDialog timePickerDialog = TimePickerDialog.newInstance(this, calendar.get(Calendar.HOUR_OF_DAY) ,calendar.get(Calendar.MINUTE), false, false); findViewById(R.id.dateButton).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { datePickerDialog.setVibrate(isVibrate()); datePickerDialog.setYearRange(1985, 2028); datePickerDialog.setCloseOnSingleTapDay(isCloseOnSingleTapDay()); datePickerDialog.show(getSupportFragmentManager(), DATEPICKER_TAG); } }); findViewById(R.id.timeButton).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { timePickerDialog.setVibrate(isVibrate()); timePickerDialog.setCloseOnSingleTapMinute(isCloseOnSingleTapMinute()); timePickerDialog.show(getSupportFragmentManager(), TIMEPICKER_TAG); } }); if (savedInstanceState != null) { DatePickerDialog dpd = (DatePickerDialog) getSupportFragmentManager().findFragmentByTag(DATEPICKER_TAG); if (dpd != null) { dpd.setOnDateSetListener(this); } TimePickerDialog tpd = (TimePickerDialog) getSupportFragmentManager().findFragmentByTag(TIMEPICKER_TAG); if (tpd != null) { tpd.setOnTimeSetListener(this); } } } private boolean isVibrate() { return ((CheckBox) findViewById(R.id.checkBoxVibrate)).isChecked(); } private boolean isCloseOnSingleTapDay() { return ((CheckBox) findViewById(R.id.checkBoxCloseOnSingleTapDay)).isChecked(); } private boolean isCloseOnSingleTapMinute() { return ((CheckBox) findViewById(R.id.checkBoxCloseOnSingleTapMinute)).isChecked(); } @Override public void onDateSet(DatePickerDialog datePickerDialog, int year, int month, int day) { Toast.makeText(MainActivity.this, "new date:" + year + "-" + month + "-" + day, Toast.LENGTH_LONG).show(); } @Override public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute) { Toast.makeText(MainActivity.this, "new time:" + hourOfDay + "-" + minute, Toast.LENGTH_LONG).show(); } }

2015-10-21

annotations注解

android annotations注解 快速注解,findbyid

2015-10-21

仿QQ自定义ListView 下拉刷新

package me.maxwin; import java.util.ArrayList; import me.maxwin.view.XListView; import me.maxwin.view.XListView.IXListViewListener; import me.maxwin.view.XListView.RemoveListener; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; public class XListViewActivity extends Activity implements IXListViewListener ,RemoveListener,OnItemClickListener{ private XListView mListView; // private ArrayAdapter<String> mAdapter; private ItemAdapter adapter; // private Context context; private ArrayList<String> items = new ArrayList<String>(); private Handler mHandler; private int start = 0; private static int refreshCnt = 0; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); geneItems(); init(); mHandler = new Handler(); } private void init() { // TODO Auto-generated method stub mListView = (XListView) findViewById(R.id.xListView); mListView.setPullLoadEnable(true); mListView.setRemoveListener(this); mListView.setOnItemClickListener(this); // mListView.setPullLoadEnable(false); // mListView.setPullRefreshEnable(false); mListView.setXListViewListener(this); adapter=new ItemAdapter(this); adapter.setData(items); mListView.setAdapter(adapter); } private void geneItems() { for (int i = 0; i != 20; ++i) { items.add("refresh cnt " + (++start)); } } private void onLoad() { mListView.stopRefresh(); mListView.stopLoadMore(); mListView.setRefreshTime("刚刚"); } @Override public void onRefresh() { mHandler.postDelayed(new Runnable() { @Override public void run() { start = ++refreshCnt; items.clear(); geneItems(); // mAdapter.notifyDataSetChanged(); adapter=new ItemAdapter(XListViewActivity.this); adapter.setData(items); mListView.setAdapter(adapter); onLoad(); } }, 2000); } @Override public void onLoadMore() { mHandler.postDelayed(new Runnable() { @Override public void run() { geneItems(); adapter.notifyDataSetChanged(); onLoad(); } }, 2000); } @Override public void removeItem(int position) { // TODO Auto-generated method stub mListView.isSlide = false; mListView.itemView.findViewById(R.id.tv_coating).setVisibility(View.VISIBLE); items.remove(position); adapter.notifyDataSetChanged(); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub Intent intent = new Intent(getApplicationContext(), ItemActivity.class); intent.putExtra("item", items.get(position)); startActivity(intent); overridePendingTransition(R.anim.slide_in_from_right, R.anim.remain_original_location); } } 自定义LIstView * * @file XListView.java * @package me.maxwin.view * @create Mar 18, 2012 6:28:41 PM * @author Maxwin * @description An ListView support (a) Pull down to refresh, (b) Pull up to load more. * Implement IXListViewListener, and see stopRefresh() / stopLoadMore(). */ package me.maxwin.view; import me.maxwin.R; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.DecelerateInterpolator; import android.view.animation.ScaleAnimation; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.AdapterView; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.Scroller; import android.widget.TextView; public class XListView extends ListView implements OnScrollListener { private float mLastY = -1; // save event y private Scroller mScroller; // used for scroll back private OnScrollListener mScrollListener; // user's scroll listener // the interface to trigger refresh and load more. private IXListViewListener mListViewListener; // -- header view private XListViewHeader mHeaderView; // header view content, use it to calculate the Header's height. And hide it // when disable pull refresh. private RelativeLayout mHeaderViewContent; private TextView mHeaderTimeView; private int mHeaderViewHeight; // header view's height private boolean mEnablePullRefresh = true; private boolean mPullRefreshing = false; // is refreashing. // -- footer view private XListViewFooter mFooterView; private boolean mEnablePullLoad; private boolean mPullLoading; private boolean mIsFooterReady = false; // total list items, used to detect is at the bottom of listview. private int mTotalItemCount; // for mScroller, scroll back from header or footer. private int mScrollBack; private final static int SCROLLBACK_HEADER = 0; private final static int SCROLLBACK_FOOTER = 1; private final static int SCROLL_DURATION = 400; // scroll back duration private final static int PULL_LOAD_MORE_DELTA = 50; // when pull up >= 50px // at bottom, trigger // load more. private final static float OFFSET_RADIO = 1.8f; // support iOS like pull // feature. private int slidePosition, preSlidePosition; private int downY; private int downX; public static View itemView, preItemView; // private Scroller scroller; private static final int SNAP_VELOCITY = 600; private VelocityTracker velocityTracker; public static boolean isSlide = false; private boolean isResponse = true; public static boolean isObstruct = true; private int mTouchSlop; private RemoveListener mRemoveListener; private static Animation scaleHideAnimation; private static Animation scaleShowAnimation; /** * @param context */ public XListView(Context context) { super(context); initWithContext(context); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } public XListView(Context context, AttributeSet attrs) { super(context, attrs); initWithContext(context); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } public XListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // mScroller = new Scroller(context, new DecelerateInterpolator()); initWithContext(context); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } private void initWithContext(Context context) { mScroller = new Scroller(context, new DecelerateInterpolator()); // XListView need the scroll event, and it will dispatch the event to // user's listener (as a proxy). super.setOnScrollListener(this); // init header view mHeaderView = new XListViewHeader(context); mHeaderViewContent = (RelativeLayout) mHeaderView .findViewById(R.id.xlistview_header_content); mHeaderTimeView = (TextView) mHeaderView .findViewById(R.id.xlistview_header_time); addHeaderView(mHeaderView); // init footer view mFooterView = new XListViewFooter(context); // init header height mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener( new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { mHeaderViewHeight = mHeaderViewContent.getHeight(); getViewTreeObserver() .removeGlobalOnLayoutListener(this); } }); } @Override public void setAdapter(ListAdapter adapter) { // make sure XListViewFooter is the last footer view, and only add once. if (mIsFooterReady == false) { mIsFooterReady = true; addFooterView(mFooterView); } super.setAdapter(adapter); } /** * enable or disable pull down refresh feature. * * @param enable */ public void setPullRefreshEnable(boolean enable) { mEnablePullRefresh = enable; if (!mEnablePullRefresh) { // disable, hide the content mHeaderViewContent.setVisibility(View.INVISIBLE); } else { mHeaderViewContent.setVisibility(View.VISIBLE); } } /** * enable or disable pull up load more feature. * * @param enable */ public void setPullLoadEnable(boolean enable) { mEnablePullLoad = enable; if (!mEnablePullLoad) { mFooterView.hide(); mFooterView.setOnClickListener(null); } else { mPullLoading = false; mFooterView.show(); mFooterView.setState(XListViewFooter.STATE_NORMAL); // both "pull up" and "click" will invoke load more. mFooterView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startLoadMore(); } }); } } /** * stop refresh, reset header view. */ public void stopRefresh() { if (mPullRefreshing == true) { mPullRefreshing = false; resetHeaderHeight(); } } /** * stop load more, reset footer view. */ public void stopLoadMore() { if (mPullLoading == true) { mPullLoading = false; mFooterView.setState(XListViewFooter.STATE_NORMAL); } } /** * set last refresh time * * @param time */ public void setRefreshTime(String time) { mHeaderTimeView.setText(time); } private void invokeOnScrolling() { if (mScrollListener instanceof OnXScrollListener) { OnXScrollListener l = (OnXScrollListener) mScrollListener; l.onXScrolling(this); } } private void updateHeaderHeight(float delta) { mHeaderView.setVisiableHeight((int) delta + mHeaderView.getVisiableHeight()); if (mEnablePullRefresh && !mPullRefreshing) { // 未处于刷新状态,更新箭头 if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) { mHeaderView.setState(XListViewHeader.STATE_READY); } else { mHeaderView.setState(XListViewHeader.STATE_NORMAL); } } setSelection(0); // scroll to top each time } /** * reset header view's height. */ private void resetHeaderHeight() { int height = mHeaderView.getVisiableHeight(); if (height == 0) // not visible. return; // refreshing and header isn't shown fully. do nothing. if (mPullRefreshing && height <= mHeaderViewHeight) { return; } int finalHeight = 0; // default: scroll back to dismiss header. // is refreshing, just scroll back to show all the header. if (mPullRefreshing && height > mHeaderViewHeight) { finalHeight = mHeaderViewHeight; } mScrollBack = SCROLLBACK_HEADER; mScroller.startScroll(0, height, 0, finalHeight - height, SCROLL_DURATION); // trigger computeScroll invalidate(); } private void updateFooterHeight(float delta) { int height = mFooterView.getBottomMargin() + (int) delta; if (mEnablePullLoad && !mPullLoading) { if (height > PULL_LOAD_MORE_DELTA) { // height enough to invoke load // more. mFooterView.setState(XListViewFooter.STATE_READY); } else { mFooterView.setState(XListViewFooter.STATE_NORMAL); } } mFooterView.setBottomMargin(height); // setSelection(mTotalItemCount - 1); // scroll to bottom } private void resetFooterHeight() { int bottomMargin = mFooterView.getBottomMargin(); if (bottomMargin > 0) { mScrollBack = SCROLLBACK_FOOTER; mScroller.startScroll(0, bottomMargin, 0, -bottomMargin, SCROLL_DURATION); invalidate(); } } private void startLoadMore() { mPullLoading = true; mFooterView.setState(XListViewFooter.STATE_LOADING); if (mListViewListener != null) { mListViewListener.onLoadMore(); } } //RemoveListener public void setRemoveListener(RemoveListener removeListener) { this.mRemoveListener = removeListener; } public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { Log.e("lg", "dispatchTouchEvent ACTION_DOWN isSlide1111 = " + isSlide); addVelocityTracker(event); downX = (int) event.getX(); downY = (int) event.getY(); slidePosition = pointToPosition(downX, downY); if (slidePosition == AdapterView.INVALID_POSITION) { return super.dispatchTouchEvent(event); } if (preItemView != null && preItemView.findViewById(R.id.tv_coating).getVisibility() == View.GONE) { itemView = preItemView; slidePosition = preSlidePosition; } else { itemView = getChildAt(slidePosition - getFirstVisiblePosition()); preItemView = itemView; preSlidePosition = slidePosition; } break; } case MotionEvent.ACTION_MOVE: { if (Math.abs(getScrollVelocity()) > SNAP_VELOCITY || (Math.abs(event.getX() - downX) > mTouchSlop && Math.abs(event.getY() - downY) < mTouchSlop)) { isSlide = true; } break; } case MotionEvent.ACTION_UP: recycleVelocityTracker(); isObstruct = true; break; } return super.dispatchTouchEvent(event); } public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: if (itemView.findViewById(R.id.tv_coating).getVisibility() == View.VISIBLE) { isSlide = false; } else { isSlide = true; } break; default: break; } return super.onInterceptTouchEvent(ev); } //dispatchTouchEvent ACTION_DOWN isSlide // @Override dispatchTouchEvent public boolean onTouchEvent(MotionEvent ev) { if (isSlide && slidePosition != AdapterView.INVALID_POSITION) { addVelocityTracker(ev); final int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_MOVE: if (isObstruct) { if (itemView.findViewById(R.id.tv_coating).getVisibility() == View.VISIBLE && isResponse == true) { scaleHideAnimation = new ScaleAnimation(1.0f, 0.0f, 1.0f, 1.0f); scaleHideAnimation.setDuration(250); scaleHideAnimation.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { isResponse = false; isObstruct = false; } public void onAnimationRepeat(Animation animation) { } public void onAnimationEnd(Animation animation) { isResponse = true; itemView.findViewById(R.id.tv_coating).setVisibility(View.GONE); itemView.findViewById(R.id.tv_functions).setClickable(true); itemView.findViewById(R.id.tv_functions).setOnClickListener(new OnClickListener() { public void onClick(View v) { mRemoveListener.removeItem(slidePosition); } }); } }); itemView.findViewById(R.id.tv_coating).startAnimation(scaleHideAnimation); } else if (itemView.findViewById(R.id.tv_coating).getVisibility() == View.GONE && isResponse == true) { scaleShowAnimation = new ScaleAnimation(0.0f, 1.0f, 1.0f, 1.0f); scaleShowAnimation.setDuration(250); scaleShowAnimation.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) { isResponse = false; isObstruct = false; } public void onAnimationRepeat(Animation animation) { } public void onAnimationEnd(Animation animation) { isSlide = false; isResponse = true; itemView.findViewById(R.id.tv_coating).setVisibility(View.VISIBLE); } }); itemView.findViewById(R.id.tv_coating).startAnimation(scaleShowAnimation); } } break; case MotionEvent.ACTION_UP: isObstruct = true; recycleVelocityTracker(); isSlide = true; break; } return true; } if (mLastY == -1) { mLastY = ev.getRawY(); } switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mLastY = ev.getRawY(); break; case MotionEvent.ACTION_MOVE: final float deltaY = ev.getRawY() - mLastY; mLastY = ev.getRawY(); if (getFirstVisiblePosition() == 0 && (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) { // the first item is showing, header has shown or pull down. updateHeaderHeight(deltaY / OFFSET_RADIO); invokeOnScrolling(); } else if (getLastVisiblePosition() == mTotalItemCount - 1 && (mFooterView.getBottomMargin() > 0 || deltaY < 0)) { // last item, already pulled up or want to pull up. updateFooterHeight(-deltaY / OFFSET_RADIO); } break; default: mLastY = -1; // reset if (getFirstVisiblePosition() == 0) { // invoke refresh if (mEnablePullRefresh && mHeaderView.getVisiableHeight() > mHeaderViewHeight) { mPullRefreshing = true; mHeaderView.setState(XListViewHeader.STATE_REFRESHING); if (mListViewListener != null) { mListViewListener.onRefresh(); } } resetHeaderHeight(); } else if (getLastVisiblePosition() == mTotalItemCount - 1) { // invoke load more. if (mEnablePullLoad && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA && !mPullLoading) { startLoadMore(); } resetFooterHeight(); } break; } return super.onTouchEvent(ev); // return super.onTouchEvent(ev); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { if (mScrollBack == SCROLLBACK_HEADER) { mHeaderView.setVisiableHeight(mScroller.getCurrY()); } else { mFooterView.setBottomMargin(mScroller.getCurrY()); } postInvalidate(); invokeOnScrolling(); if (mScroller.isFinished()) { if (mRemoveListener == null) { throw new NullPointerException("RemoveListener is null, we should called setRemoveListener()"); } itemView.scrollTo(0, 0); } } super.computeScroll(); } //addVelocityTracker private void addVelocityTracker(MotionEvent event) { if (velocityTracker == null) { velocityTracker = VelocityTracker.obtain(); } velocityTracker.addMovement(event); } private void recycleVelocityTracker() { if (velocityTracker != null) { velocityTracker.recycle(); velocityTracker = null; } } private int getScrollVelocity() { velocityTracker.computeCurrentVelocity(1000); int velocity = (int) velocityTracker.getXVelocity(); return velocity; } public interface RemoveListener { public void removeItem(int position); } @Override public void setOnScrollListener(OnScrollListener l) { mScrollListener = l; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (mScrollListener != null) { mScrollListener.onScrollStateChanged(view, scrollState); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // send to user's listener mTotalItemCount = totalItemCount; if (mScrollListener != null) { mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); } } public void setXListViewListener(IXListViewListener l) { mListViewListener = l; } /** * you can listen ListView.OnScrollListener or this one. it will invoke * onXScrolling when header/footer scroll back. */ public interface OnXScrollListener extends OnScrollListener { public void onXScrolling(View view); } /** * implements this interface to get refresh/load more event. */ public interface IXListViewListener { public void onRefresh(); public void onLoadMore(); } }

2015-05-04

空空如也

空空如也

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

TA关注的人 TA的粉丝

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