ner, ChoiseModes
, 还有扩展版的ExpandableListView
.
本文作者就介绍这个开源库, ExpandableRecyclerView
, 用自定义的RecyclerView.Adapter
来实现展开关闭分组的功能.
首先明白一下Adapter的功能, 其实adapter就是一个中间人, 将一些数据按照index翻译给View, 然后显示.
当显示的list是单维度的时候, 这样的翻译很简单, 数据的index就直接对应了屏幕上view的index.
当时当你显示二维数据时, 翻译就变得有点复杂,数据和view的index可能对应, 也可能不对应.
RecyclerView.Adapter
就只能处理一维数据的情况, 这就是为什么要对其进行一些扩展, 才能实现ExpandableRecyclerView.
后来作者简单讲了实现的原理, 用到了ExpandableListPosition
, 是Android SDK中就有的类, 只不过有包限制, 所以拷贝到了这个库里.
最后附上repo地址: expandable-recycler-view
注解是什么
Annotations are Metadata.
注解是元数据, 而元数据是一些关于其他数据的信息.
所以说, 注解是关于代码的信息.
比如@Override
注解, 即便你不在方法上标注它, 程序依然能够正常工作. 那么它是用来干什么的呢?
@Override
是用来告诉编译器, 这个方法覆写了一个方法, 如果父类没有这个方法, 则会报一个编译错误.
如果你不加这个注解, 有可能你方法名不小心拼错了却仍然编译通过了.
创建自定义注解:
比如, 创建一个:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Status {
public enum Priority {LOW, MEDIUM, HIGH}
Priority priority() default Priority.LOW;
String author() default “Amit”;
int completion() default 0;
}
其中@Target
指定了这个注解可以放在哪里. 如果你不设置, 这个注解可以放在任何地方.
可能的值有:
ElementType.TYPE
(class, interface, enum)
ElementType.FIELD
(instance variable)
ElementType.METHOD
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
@Retention
定义这个注解可以被保存多久.
可能的值有:
RetentionPolicy.SOURCE
- 到编译结束, 不会被编进.class, 只会留在源文件中. @Override
, @SuppressWarnings
都是这种.
RetentionPolicy.CLASS
- 到类加载丢弃, 注解将存储在.class文件中, 这是默认值.
RetentionPolicy.RUNTIME
- 不被丢弃. .class文件中有, 并且可由VM读入, 在运行时可以通过反射的方式读取到.
上面的注解使用时:
// in Foo.java
@Status(priority = STATUS.Priority.MEDIUM, author = “Amit Shekhar”, completion = 0)
public void methodOne() {
//no code
}
// get the annotation information
Class foo = Foo.class;
for(Method method : foo.getMethods()) {
Status statusAnnotation = (Status)method.getAnnotation(Status.class);
if(statusAnnotation != null) {
System.out.println(" Method Name : " + method.getName());
System.out.println(" Author : " + statusAnnotation.author());
System.out.println(" Priority : " + statusAnnotation.priority());
System.out.println(" Completion Status : " + statusAnnotation.completion());
}
}
如果你的注解中仅有一个属性, 它应该叫value, 并且使用的时候不用指定属性名.
@interface Status{
int value();
}
@Status(50)
public void someMethod() {
//few codes
}
最后作者还附上了另一个他的文章, 推荐他的网络请求库: Fast Android Networking
作者介绍他的库: confetti.
这个库实现了一个粒子系统, 来发射出随机的纸屑, 并且可以被定制化, 比如发射源的形状(点或者线), 初始的物理约束(速度, 加速度, 旋转等), 还可以定义消失或者拖拽行为, 感觉效果还挺好的.
关于性能, 纸屑对象是循环利用的, 每一个bitmap也只被分配一次地址, 动画参数也做了一些预计算, 所以作者说不用担心丢帧, 除非你一次性出现的片儿实在是太多了.
作者他们在自己Android应用里开始使用RxJava以后, 经常会遇到由于API没有follow reactive model, 导致他们必须做一些转换工作, 将它们和其他的RxJava Observable链连接起来.
API对于很重的操作通常提供这两种方式之一
- 1.同步阻塞方法调用, 通常需要后台线程调用.
- 2.异步非阻塞方法调用, 结合callback, listener, 或者broadcast receiver等.
把同步方法变为Observable:
用这个Observable.fromCallable()
比如:
// wrapping synchronous operation in an RxJava Observable
Observable<Boolean> wipeContents(final SharedPreferences sharedPreferences) {
return Observable.fromCallable(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return sharedPreferences.edit().clear().commit();
}
});
}
把异步方法变为Observable:
变异步没那么简单了, 之前有一些模式是