自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(74)
  • 资源 (4)
  • 收藏
  • 关注

转载 logback 配置详解(二)——appender

目录1、appender  1.1、ConsoleAppender  1.2、FileAppender  1.3、RollingFileAppender  1.4、其他**Appender 2、encoder正文回到顶部1、appender  <appender>是<configuration>的子节点,是负责写日志的组件。  <appender>有两个必要属性name和class。name指定appender名称,cla.

2021-03-11 17:04:03 934

转载 logback 配置详解(一)——logger、root

目录1、根节点包含的属性 2、根节点的子节点  2.1、设置上下文名称:  2.2、设置loger、root 正文回到顶部1、根节点<configuration>包含的属性scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。debug:当此属性设置.

2021-03-11 17:00:21 587 1

原创 一些JVM常用参数配置

GC 常用参数-Xmn -Xms -Xmx –Xss 年轻代 最小堆 最大堆 栈空间-XX:+UseTLAB -XX:+PrintTLAB -XX:TLABSize 使用 TLAB, 默认打开 打印 TLAB 的使用情况 设置 TLAB 大小 -XX:+DisableExplicitGC 启用用于禁用对的调用处理的选项 System.gc() -XX:+PrintGC 查看 GC 基本信息 -XX:+PrintGCDetails -XX.

2021-01-21 14:52:22 177

原创 JVM 垃圾回收器之---Garbage First(G1)

Garbage First(G1)设计思想随着 JVM 中内存的增大, STW 的时间成为 JVM 急迫解决的问题, 但是如果按照传统的分代模型, 总跳不出 STW 时间不可预测这点。为了实现 STW 的时间可预测, 首先要有一个思想上的改变。 G1 将堆内存“化整为零” , 将堆内存划分成多个大小相等独立区域(Region) , 每一个 Region都可以根据需要, 扮演新生代的 Eden 空间、 Survivor 空间, 或者老年代空间。 回收器能够对扮演不同角色的 Region 采用不同的策略

2021-01-21 11:43:45 151

原创 JVM垃圾回收器-标记清除算法----三色标记

三色标记在三色标记法之前有一个算法叫 Mark-And-Sweep(标记清除) 。 这个算法会设置一个标志位来记录对象是否被使用。 最开始所有的标记位都是 0, 如果发现对象是可达的就会置为 1, 一步步下去就会呈现一个类似树状的结果。 等标记的步骤完成后, 会将未被标记的对象统一清理, 再次把所有的标记位设置成 0 方便下次清理。这个算法最大的问题是 GC 执行期间需要把整个程序完全暂停, 不能异步进行 GC 操作。 因为在不同阶段标记清扫法的标志位 0 和 1 有不同的含义,那么新增的对象无论

2021-01-21 11:30:18 834

原创 JVM---对象的分配策略

对象的分配策略栈上分配没有逃逸即方法中的对象没有发生逃逸。逃逸分析的原理: 分析对象动态作用域, 当一个对象在方法中定义后, 它可能被外部方法所引用。比如: 调用参数传递到其他方法中, 这种称之为方法逃逸。 甚至还有可能被外部线程访问到, 例如: 赋值给其他线程中访问的变量, 这个称之为线程逃逸。从不逃逸到方法逃逸到线程逃逸, 称之为对象由低到高的不同逃逸程度。如果确定一个对象不会逃逸出线程之外, 那么让对象在栈上分配内存可以提高 JVM 的效率。逃逸分析代码 这段代码在调用的过程中 Myb..

2021-01-20 10:12:40 100

原创 JHSDB 工具

JHSDB 是一款基于服务性代理实现的进程外调试工具。 服务性代理是 HotSpot 虚拟机中一组用于映射 Java 虚拟机运行信息的, 主要基于 Java 语言实现的API 集合。JDK1.8 的开启方式开启 HSDB 工具Jdk1.8 启动 JHSDB 的时候必须将 sawindbg.dll( 一般会在 JDK 的目录下) 复制到对应目录的 jre 下(注意在 win 上安装了 JDK1.8 后往往同级目录下有一个jre 的目录)然后到目录: C:\Program Files\Java\

2021-01-19 10:09:28 1923 3

原创 ScopedProxy----spring多例情况下代理的实现

1、多例的bean@Component@Scope(value = DefaultListableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)public class ScopedProxyBean { public void code() { System.out.println(this.hashCode());//直接打印hashcode值,若每次打印的一致则是同一个对象

2021-01-18 15:01:26 347

原创 spring中Scope接口的使用

1、实现Scope 接口public class CustomScope implements Scope { private ThreadLocal local = new ThreadLocal(); //获取bean实例 objectFactory.getObject()方法可以回调到spring //中 createBean方法,完成bean的创建,bean生成后由自己进行管理 //并没有在spring容器中管理 @Override pub

2021-01-05 15:12:30 783

原创 spring中自定义对象交给spring容器管理的4种方式

1、自定义一个 BeanDefinition@Componentpublic class BeanPro implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, Ordered { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

2021-01-05 13:58:54 1942 4

转载 Spring之 Event事件通知机制

Spring的事件通知机制是一项很有用的功能,使用事件机制我们可以将相互耦合的代码解耦,从而方便功能的修改与添加。本文我来学习并分析一下Spring中事件的原理。举个例子,假设有一个添加评论的方法,在评论添加成功之后需要进行修改redis缓存、给用户添加积分等等操作。当然可以在添加评论的代码后面假设这些操作,但是这样的代码违反了设计模式的多项原则:单一职责原则、迪米特法则、开闭原则。一句话说就是耦合性太大了,比如将来评论添加成功之后还需要有另外一个操作,这时候我们就需要去修改我们的添加评论代码了。

2020-12-24 15:54:10 272 1

原创 Spring5.2.8之Aware接口

Spring5.2.8之Aware接口接口使用demo源码分析Aware.java是个没有定义任何方法的接口,拥有众多子接口,在spring源码中有多处都在使用这些子接口完成各种场景下的回调操作,当业务有需要时,我们只需创建类来实现相关接口,再声明为bean,就可以被spring容器主动回调.接口使用demo@Componentpublic class AwareBean implements BeanNameAware {@Overridepublic void setBeanName(Str

2020-12-24 15:06:26 129

原创 CyclicBarrier

cyclicBarrier 重复栅栏(CountDownLatch),语法和CountDownLatch差不多基本语法//初始化一个cyclicBarrier 计数器为2CyclicBarrier cyclicBarrier = new CyclicBarrier(2);//阻塞 计数器不为0的时候并且会把计数器-1cyclicBarrier.await();示例代码import lombok.extern.slf4j.Slf4j;import java.util.concurr..

2020-11-26 16:48:46 90

原创 CountDownLatch

倒计时锁;某个线程x等待倒计时为0的时候才执行;所谓的倒计时其实就是一个int类型的变量,在初始化CountDownLatch的时候会给他一个初始值(程序员定的);在多线程工作的时候可以通过countDown()方法来对计数器-1;当等于0的时候x则会解阻塞运行基本语法 //初始化对象,给一个初始值 CountDownLatch latch = new CountDownLatch(3); //x线程 调用await阻塞 等待计数器为0的时候才会解阻塞 l...

2020-11-26 16:42:15 92

原创 samephore

来限制对资源访问的线程的上限;好比洗浴店里面的手牌,比如你进去一个洗浴店里,服务生首先会给你一个手牌;如果手牌没有了你则需要去喝茶等待;等他其他问洗完你才可以去享受服务;手牌相当于你一个许可;你去享受服务的时候先要获取手牌,服务完成之后需要归还手牌;基本语法 //线程的上限 Semaphore semaphore = new Semaphore(3); //获取一个许可 - semaphore.acquire(); //释放 +...

2020-11-26 16:30:18 323 1

原创 高性能读写锁StampedLock

ReentrantReadWriteLock 的性能已经很好了但是他底层还是需要进行一系列的cas操作去加锁;StampedLock如果是读锁上锁是没有这种cas操作的性能比ReentrantReadWriteLock 更好也称为乐观读锁;即读获取锁的时候 是不加锁 直接返回一个值;然后执行临界区的时候去验证这个值是否有被人修改(写操作加锁)如果没有被人修改则直接执行临界区的代码;如果被人修改了则需要升级为读写锁(ReentrantReadWriteLock--->readLock);基本

2020-11-26 16:02:30 246

原创 粘包/半包问题

什么是 TCP 粘包半包?假设客户端分别发送了两个数据包 D1 和 D2 给服务端, 由于服务端一次读取到的字节数是不确定的, 故可能存在以下 4 种情况。(1) 服务端分两次读取到了两个独立的数据包, 分别是 D1 和 D2, 没有粘包和拆包;(2) 服务端一次接收到了两个数据包, D1 和 D2 粘合在一起, 被称为 TCP 粘包;(3) 服务端分两次读取到了两个数据包, 第一次读取到了完整的 D1 包和 D2 包的部分内容, 第二次读取到了 D2 包的剩余内容, 这被称为 TCP 拆

2020-11-05 15:55:31 146

原创 netty---ByteBuf

ByteBufByteBuf API 的优点:它可以被用户自定义的缓冲区类型扩展;通过内置的复合缓冲区类型实现了透明的零拷贝;容量可以按需增长(类似于 JDK 的 StringBuilder) ;在读和写这两种模式之间切换不需要调用 ByteBuffer 的 flip()方法;读和写使用了不同的索引;支持方法的链式调用;支持引用计数;支持池化。ByteBuf 维护了两个不同的索引, 名称以 read 或者 write 开头的 ByteBuf 方法, 将会推进其对应的索引, 而名称以 s

2020-11-05 15:37:52 302

原创 ChannelOption

ChannelOption 的各种属性在套接字选项中都有对应。1、 ChannelOption.SO_BACKLOGChannelOption.SO_BACKLOG 对应的是 tcp/ip 协议 listen 函数中的 backlog 参数, 函数listen(int socketfd,int backlog)用来初始化服务端可连接队列,服务端处理客户端连接请求是顺序处理的, 所以同一时间只能处理一个客户端连接, 多个客户端来的时候, 服务端将不能处理的客户端连接请求放在队列中等待处理, backl

2020-11-05 15:29:37 465

原创 netty组件----Bootstrap

Bootstrap网络编程里, “服务器” 和“客户端” 实际上表示了不同的网络行为; 换句话说, 是监听传入的连接还是建立到一个或者多个进程的连接。因此, 有两种类型的引导: 一种用于客户端(简单地称为 Bootstrap) , 而另一种(ServerBootstrap) 用于服务器。 无论你的应用程序使用哪种协议或者处理哪种类型的数据,唯一决定它使用哪种引导类的是它是作为一个客户端还是作为一个服务器。比较 Bootstrap 类ServerBootstrap 将绑定到一个端口, 因为服务

2020-11-05 15:27:48 215 1

原创 netty组件---ChannelPipeline 和 ChannelHandlerContext

ChannelPipeline 和 ChannelHandlerContextChannelPipeline 接口当 Channel 被创建时, 它将会被自动地分配一个新的 ChannelPipeline。 这项关联是永久性的; Channel 既不能附加另外一个 ChannelPipeline, 也不能分离其当前的。 在 Netty 组件的生命周期中, 这是一项固定的操作, 不需要开发人员的任何干预。使得事件流经 ChannelPipeline 是 ChannelHandler 的工作, 它们是在

2020-11-05 15:25:03 217

原创 netty组件---ChannelHandler

ChannelHandler 接口从应用程序开发人员的角度来看, Netty 的主要组件是 ChannelHandler, 它充当了所有处理入站和出站数据的应用程序逻辑的容器。 ChannelHandler 的方法是由网络事件触发的。事实上, ChannelHandler 可专门用于几乎任何类型的动作, 例如将数据从一种格式转换为另外一种格式, 例如各种编解码, 或者处理转换过程中所抛出的异常。举例来说, ChannelInboundHandler 是一个你将会经常实现的子接口。 这种类型的Ch

2020-11-05 15:19:43 302

原创 netty组件---EventLoop 和 EventLoopGroup

回想一下我们在 NIO 中是如何处理我们关心的事件的? 在一个 while 循环中 select 出事件, 然后依次处理每种事件。 我们可以把它称为事件循环, 这就是 EventLoop。 interfaceio.netty.channel. EventLoop 定义了 Netty 的核心抽象, 用于处理网络连接的生命周期中所发生的事件。io.netty.util.concurrent 包构建在 JDK 的 java.util.concurrent 包上。而 io.netty.channel 包中

2020-11-05 15:16:25 406

原创 netty组件--Channel、EventLoop(Group)和 ChannelFuture

Channel、EventLoop(Group)和 ChannelFutureNetty 网络抽象的代表:Channel—Socket;EventLoop—控制流、 多线程处理、 并发;ChannelFuture—异步通知。Channel 和 EventLoop 关系如图:Channel 接口基本的 I/O 操作(bind()、 connect()、 read()和 write()) 依赖于底层网络传输所提供的原语。 在基于 Java 的网络编程中, 其基本的构造是类 Socket。 Ne

2020-11-05 15:13:07 399

原创 netty组件初步了解

EventLoop(Group) 、ChannelChannel 是 Java NIO 的一个基本构造。它代表一个到实体(如一个硬件设备、 一个文件、 一个网络套接字或者一个能够执行一个或者多个不同的 I/O 操作的程序组件) 的开放连接, 如读操作和写操作目前, 可以把 Channel 看作是传入(入站) 或者传出(出站) 数据的载体。 因此, 它可以被打开或者被关闭, 连接或者断开连接。EventLoop 暂时可以看成一个线程、 EventLoopGroup 自然就可以看成线程组。事件和 C

2020-11-05 14:42:13 55

原创 第一个netty程序

netty 分为客户端和服务端代码1、先看服务端代码public class EchoServer { //指定服务端绑定的端口 private final int port; public EchoServer(int port) { this.port = port; } public static void main(String[] args) throws InterruptedException { int

2020-11-05 14:39:48 107

原创 HTTP

HTTPHTTP 协议是 Hyper Text Transfer Protocol(超文本传输协议) 的缩写,是用于从万维网(WWW:World Wide Web ) 服务器传输超文本到本地浏览器的传送协议。HTTP 协议我们使用 http 来访问 Web 上某个资源, 比如 html/文本、 word、 avi 电影、 其他资源。官方协议网站: https://tools.ietf.org/html/rfc2608HTTP 使用统一资源标识符(Uniform Resource Identifi

2020-10-26 09:37:55 86

原创 常用的网络工具 Wireshark 和 tcpdump

WireShark为什么要抓包1、 定位网络问题;2、 分析接口数据;3、 学习网络协议, 使用抓包工具分析网络数据更直观。大部分场合都可以通过程序调试来定位问题, 但有些场景使用抓包来定位接口问题更准确、 更方便, 如以下场景:1、 你发送数据给后台, 但后台没有收到, 可以对接口进行抓包分析, 看是后台处理有问题, 还是没有将数据发出去, 或是发送数据格式有误;2、 你和后台接口联调测通, 但业务数据对不上, 你认为是后台问题, 后台认为是你发的问题, 可以抓包确认问题所在;3、

2020-10-26 09:34:24 370 1

原创 TCP 概述

TCP(Transmission Control Protocol) 是面向连接的通信协议, 通过三次握手建立连接,然后才能开始数据的读写, 通讯完成时要拆除连接, 由于 TCP 是面向连接的所以只能用于端到端的通讯。TCP 提供的是一种可靠的数据流服务, 数据有可能被拆分后发送, 那么采用超时重传机制是和应答确认机制是组成 TCP 可靠传输的关键设计。而超时重传机制中最最重要的就是重传超时(RTO, Retransmission TimeOut) 的时间选择, 很明显, 在工程上和现实中网络环

2020-10-26 09:25:23 222

原创 网络编程基础知识

1、网络协议计算机网络是什么?随着计算机技术发展, 计算机的体积和价格都在下降, 之前计算机多用于研究机构, 现阶段逐步进入一般的公司用于办公。 原来计算机之间传输数据需要通过软盘等第三方存储介质进行转存, 人们需要将数据直接通过通信线路传输, 来缩短传输时间, 于是计算机网络开始诞生, 并逐渐发展为现在巨大的 Internet。定义和分类计算机网络的标准定义是: 利用通信线路将地理上分散的、 具有独立功能的计算机系统和通信设备按不同的形式连接起来, 以功能完善的网络软件及协议实现资源共享和

2020-10-26 09:22:44 301

转载 redis中RDB和AOF两种持久化方式的比较

1、RDB持久化机制就是我们俗称的备份,他可以在定期内对数据进行备份,将Redis服务器中的数据持久化到硬盘中;文件格式是:dump.rdb快照持久化通用的配置:RDB持久化的工作流程:Redis根据配置自己尝试生成RDB快照文件; fork一个子进程出来; 子进程尝试将数据写到临时的RDB快照文件中; 完成RDB快照文件的生成之后,就替换之前旧的快照文件;2、AOF持久化机制他会在执行写命令的时候,将执行的每条写命令以append-only的模式写入一个日志文件中存放在

2020-10-13 17:17:42 466

转载 优雅的使用线程池

线程池不仅在项目中是非常常用的一项技术而且在面试中基本上也是必问的知识点,接下来跟着我一起来巩固一下线程池的相关知识。在了解线程池之前我们先了解一下什么是进程什么是线程进程程序:一般是一组CPU指令的集合构成的文件,静态存储在诸如硬盘之类的存储设备上 进程:当一个程序要被计算机运行时,就是在内存中产生该程序的一个运行时实例,我们就把这个实例叫做进程用户下达运行程序的命令以后,就会产生一个进程,同一个程序可以产生多个进程(一对多的关系),以允许同时有多个用户运行同一个程序,却不会相冲突。进程需

2020-09-29 19:36:24 128

原创 ReentrantReadWriteLock--读写锁

ReentrantReadWriteLock-读写锁特点 1、读读并发 2、读写互斥 3、写写互斥 4、读锁 不支持条件 ---> throw new UnsupportedOperationException();用法tatic ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();static Lock r = rwl.readLock();static L...

2020-09-23 18:41:06 81

原创 ReentrantLock---基本用法

ReentrantLock 特点1、可打断、可重入2、可以设置超时时间3、可以设置为公平锁(默认为非公平锁)4、支持多个条件标量使用1、基本语法ReentrantLock lock = new ReentrantLock();//获取锁lock.lock();try { //临界区}finally { //释放锁 lock.unlock();}2、重入ReentrantLock lock = new ReentrantLock();

2020-09-23 18:12:31 2327 2

转载 Java特性——反射

概述定义JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。用途在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后

2020-09-18 13:55:20 82

原创 一道面试题:实现一个容器,提供两个方法,add,size 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束线程2

1、案例一/** * 一道面试题:实现一个容器,提供两个方法,add,size * 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数, * 当个数到5个时,线程2给出提示并结束线程2 * * 这里list在两个线程之间不保证可见性,所以线程2始终结束不了 */@Slf4j(topic = "test")public class Container1 { List lists = new ArrayList(); public void add(Ob

2020-09-16 18:02:46 295 1

原创 一道面试题:多个atomic类连续调用能否构成原子性?

代码/** * atomicXXX * 一道面试题:多个atomic类连续调用能否构成原子性? */@Slf4j(topic = "test")public class Demo { AtomicInteger count = new AtomicInteger(0); public void test(){ for (int i = 0; i < 10000; i++) { if(count.get() < 1000

2020-09-16 17:59:26 290

原创 volatile 关键字

1、/** * volatile 关键字,使一个变量在多个线程间可见 * mian,t1线程都用到一个变量,java默认是T1线程中保留一份副本,这样如果main线程修改了该变量, * t1线程未必知道 * * 使用volatile关键字,会让所有线程都会读到变量的修改值 * * 在下面的代码中,running是存在于堆内存的t对象中 * 当线程t1开始运行的时候,会把running值从内存中读到t1线程的工作区,在运行过程中直接使用这个副本, * 并不会每次都去读取堆内存,这样,当

2020-09-16 17:42:04 237

原创 synchronized 和异常的关系

synchronized 和异常的关系,如果没有对异常进行try,则会释放锁,结束线程执行测试代码如下/** * synchronized 和异常的关系 * T2线程能否执行? */@Slf4j(topic = "test")public class Demo { Object o = new Object(); int count = 0; void test(){ synchronized(o) { //t1.

2020-09-16 17:28:56 342

原创 synchronized 锁的重入

1、/一个同步方法调用另外一个同步方法,能否得到锁?//重入 synchronized默认支持重入@Slf4j(topic = "test")public class Demo { synchronized void test1(){ log.debug("test1 start........."); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedEx

2020-09-16 17:24:51 82

解决粘包半包问题--分隔符和消息定长

由于底层的 TCP 无法理解上层的业务数据, 所以在底层是无法保证数据包不被拆分和重 组的, 这个问题只能通过上层的应用协议栈设计来解决, 根据业界的主流协议的解决方案, 可以归纳如下。 (1) 在包尾增加分割符, 比如回车换行符进行分割, 例如 FTP 协议; (2) 消息定长, 例如每个报文的大小为固定长度 200 字节, 如果不够, 空位补空格;

2020-11-05

Android---防支付宝支付密码输入弹窗

防支付宝支付密码输入弹窗, (1),封装成dialog (2),在构造方法中设置样式 (3),密码的存储和删除是操作字符串

2018-05-24

中文转英文

package com.yk.yk_doctor.util; import java.io.UnsupportedEncodingException; /** * * @author zsw 中文转为拼音 * */ public class Spell { static final int GB_SP_DIFF = 160; static final int[] secPosValueList = { 1601, 1637, 1833, 2078, 2274, 2302, 2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 3858, 4027, 4086, 4390, 4558, 4684, 4925, 5249, 5600 }; static final char[] firstLetter = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'w', 'x', 'y', 'z' }; public static String getSpells(String characters) { StringBuffer buffer = new StringBuffer(); for (int i = 0; i > 7) == 0) { } else { char spell = getFirstLetter(ch); buffer.append(String.valueOf(spell)); } } return buffer.toString(); } private static Character getFirstLetter(char ch) { byte[] uniCode = null; try { uniCode = String.valueOf(ch).getBytes("GBK"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } if (uniCode[0] 0) { return null; } else { return convert(uniCode); } } private static char convert(byte[] bytes) { char result = '-'; int secPosValue = 0; int i; for (i = 0; i < bytes.length; i++) { bytes[i] -= GB_SP_DIFF; } secPosValue = bytes[0] * 100 + bytes[1]; for (i = 0; i = secPosValueList[i] && secPosValue < secPosValueList[i + 1]) { result = firstLetter[i]; break; } } return result; } }

2016-01-12

android 分页加载

下拉刷新,上拉加载 /** * @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 com.yk.yk_doctor.widget.xlistview; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.animation.DecelerateInterpolator; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.Scroller; import android.widget.TextView; import com.yk.yk_doctor.R; 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. /** * @param context */ public XListView(Context context) { super(context); initWithContext(context); } public XListView(Context context, AttributeSet attrs) { super(context, attrs); initWithContext(context); } public XListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initWithContext(context); } 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); //make sure "pull up" don't show a line in bottom when listview with one page setFooterDividersEnabled(false); } else { mPullLoading = false; mFooterView.show(); mFooterView.setState(XListViewFooter.STATE_NORMAL); //make sure "pull up" don't show a line in bottom when listview with one page setFooterDividersEnabled(true); // 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(); } } @Override public boolean onTouchEvent(MotionEvent ev) { 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); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { if (mScrollBack == SCROLLBACK_HEADER) { mHeaderView.setVisiableHeight(mScroller.getCurrY()); } else { mFooterView.setBottomMargin(mScroller.getCurrY()); } postInvalidate(); invokeOnScrolling(); } super.computeScroll(); } @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(); } }

2016-01-12

空空如也

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

TA关注的人

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