rxjava 操作符简略

rxjava

变换字符:Map()/FlatMap/ConcatMap()/Buffer()/delay()/do()/onErrorReturn()/onErrorResumeNext()/onExceptionResumeNext()/retry()/retryUntil()/retryWhen()/repeat()/repeatWhen()/
1.Map 作用:对被观察者发送的每1个事件都通过 指定的函数 处理,从而变换成另外一种事件 场景:数据类型转换
2.FlatMap 作用:将被观察者发送的事件进行拆分&单独转换,在合并成一个新的事件序列,最后进行发送。 场景:无序的将被观察者发送的整个事件序列进行变换
3.ConcatMap 作用:类似FlatMap() 操作符 与FlatMap()的 区别在于:拆分 & 重新合并生成的事件序列 的顺序 = 被观察者旧序列生产的顺序 场景:有序的将被观察者发送的整个事件序列进行变换
4.Buffer 作用:定期从 被观察者(Obervable)需要发送的事件中 获取一定数量的事件 & 放到缓存区中,最终发送 场景:缓存被观察者发送的事件
5.delay 作用:使得被观察者延迟一段时间再发送事件 [observable]

1.在事件的生命周期中操作
6.do 作用:在某个事件的生命周期中调用
0601:doOnEach/onNext/onError/onCompleted 当observable每次发送一次数据事件就会调用
0602:doOnNext/doAftetNext 执行Next事件前调用/执行Next事件后调用
0603:doError()/doOnCompleted()/doOnTerminate()/doFianlly() 发送错误事件时/正常发送事件完毕后/无论正常发送或异常终止/最后执行
0604:doOnSubscribe()/doOnUnsubscribe() 观察者订阅时调用/观察者取消订阅时调用

2.错误处理 场景:发送事件过程中,遇到错误时的处理机制
1.onErrorResumeNext()拦截的错误 = Throwable;若需拦截Exception请用onExceptionResumeNext()
2.若onErrorResumeNext()拦截的错误 = Exception,则会将错误传递给观察者的onError方法

7.onErrorReturn 作用:遇到错误时,发送1个特殊事件&正常终止
8.onErrorResumeNext 作用:遇到错误时,发送1个新的Observable
9.onExceptionResumeNext 作用:遇到错误时,发送1个新的Observable
10.retry 作用:重试,即当出现错误时,让被观察者(Observable)重新发射数据
11.retryUntil 作用: 出现错误后,判断是否需要重新发送数据
1101.若需要重新发送 & 持续遇到错误,则持续重试
1102.作用类似于retry(Predicate predicate)
12.retryWhen 作用:遇到错误时,将发生的错误传递给一个新的被观察者(Observable),并决定是否需要重新订阅原始被观察者(Observable)& 发送事件
13.repeat 作用:无条件地、重复发送 被观察者事件
14.repeatWhen 作用:有条件地、重复发送 被观察者事件

合并操/组合操作符
1.组合多个被观察者 顺序:concat concatArray 时间:merge mergeArray 错误处理:concatDelayError mergeDelayError
2.合并多个事件 数量:zip 时间:combineLatest combineLatestDelayError 合并成1个事件发送 reduce collect
3.发送事件前追加发送事件 startWith startWithArray
4.统计发送事件数量 count

1.concat 作用:组合多个被观察者一起发送数据,合并后 按发送顺序串行执行 二者区别:组合被观察者的数量,即concat()组合被观察者数量≤4个,而concatArray()则可>4个
2.merge 作用:组合多个被观察者一起发送数据,合并后 按时间线并行执行 区别上述concat()操作符:同样是组合多个被观察者一起发送数据,但concat()操作符合并后是按发送顺序串行执行
3.concatDelayError 如果事件出现异常 决定是否继续发送
4.zip 作用:合并 多个被观察者(Observable)发送的事件,生成一个新的事件序列(即组合过后的事件序列),并最终发送 场景:当需要展示的信息需要从多个地方获取(即信息 = 信息1 + 信息2 )&统一结合后再展示 如合并网络请求的发送&统一显示结果
5.combineLatest 作用:当两个Observables中的任何一个发送了数据后,将先发送了数据的Observables 的最新(最后)一个数据 与 另外一个Observable发送的每个数据结合,最终基于该函数的结果发送数据
6.reduce 作用:把被观察者需要发送的事件聚合成1个事件 & 发送 聚合的逻辑根据需求撰写,但本质都是前2个数据聚合,然后与后1个数据继续进行聚合,依次类推
7.collect 作用:将被观察者Observable发送的数据事件收集到一个数据结构里
8.startWith / startWithArray 作用:在一个被观察者发送事件前,追加发送一些数据 / 一个新的被观察者
9.conunt 作用:统计被观察者发送事件的数量

View的技术传递

1. 基础知识
(1) 所有Touch事件都被封装成MotionEvent对象,包括Touch的位置、时间、历史记录以及第几个手指(多手指触摸灯)。
(2) 事件类型分类为ACTION_DOWN,ACTION_UP,ACTION_MOVE,ACTION_POINTER_DOWN,ACTION_POINTER_UP,ACTION_CANCEL,每个事件都以ACTION_DOWN开始ACTION_UP结束。
(3) 对事件的处理包括三类,分别为传递—dispatchTouchEvent()函数、拦截—oninterceptTouchEvent函数、消费—-onTouchEvent函数和OnTouchListener
2.传递流程
(1) 事件从Activity.dispatchTouchEvent开始传递,只要没有被停止或拦截,从最上层的View(ViewGroup)开始一直往下(子View)传递。子View可以通过OnTouchEvent()对事件进行处理。
(2) 事件由父View(ViewGroup)传递给子View,ViewGroup可以通过oniterceptTouchEvent对事件做拦截,停止其往下传递。
(3) 如果事件从上往下传递过程中一直没有被停止,且最底层子View没有消费事件,事件会反向往上传递,这时父View(Group)可以进行消费,如果还是没有被消费的话,最后会到Activity的OnTouchEven()函数。
(4)如果View没有对ACTION_DOUWN进行消费,之后的其他事件不会传递过来
(5) OnTouchListener优于OnTouchEvent()对事件进行消费。
上面的消费即表示相应函数返回值为true
(1)View不处理事件流程图
此处输入图片的描述
(2)View处理事件流程图
此处输入图片的描述

RecyclerView的万能分割线

##使用方法:

#添加默认分割线:高度为2px,颜色为灰色

1
mRecyclerView.addItemDecoration(new RecyclerViewDivider(mContext, LinearLayoutManager.VERTICAL));

#添加自定义分割线:可自定义分割线drawable

1
2
mRecyclerView.addItemDecoration(new RecyclerViewDivider(
mContext, LinearLayoutManager.VERTICAL, R.drawable.divider_mileage));

#添加自定义分割线:可自定义分割线高度和颜色

1
2
mRecyclerView.addItemDecoration(new RecyclerViewDivider(
mContext, LinearLayoutManager.VERTICAL, 10, ContextCompat.getColor(mContext, R.color.divide_gray_color)));

#万能分割线登场:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package utils;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
* Created by ${火龙裸先生} on 2016/10/29.
* 邮箱:791335000@qq.com
*/
public class RecyclerViewDivider extends RecyclerView.ItemDecoration {
private Paint mPaint;
private Drawable mDivider;
private int mDividerHeight = 2;//分割线高度,默认为1px
private int mOrientation;//列表的方向:LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};

/**
* 默认分割线:高度为2px,颜色为灰色
*
* @param context
* @param orientation 列表方向
*/
public RecyclerViewDivider(Context context, int orientation) {
if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
throw new IllegalArgumentException("请输入正确的参数!");
}
mOrientation = orientation;

final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}

/**
* 自定义分割线
*
* @param context
* @param orientation 列表方向
* @param drawableId 分割线图片
*/
public RecyclerViewDivider(Context context, int orientation, int drawableId) {
this(context, orientation);
mDivider = ContextCompat.getDrawable(context, drawableId);
mDividerHeight = mDivider.getIntrinsicHeight();
}

/**
* 自定义分割线
*
* @param context
* @param orientation 列表方向
* @param dividerHeight 分割线高度
* @param dividerColor 分割线颜色
*/
public RecyclerViewDivider(Context context, int orientation, int dividerHeight, int dividerColor) {
this(context, orientation);
mDividerHeight = dividerHeight;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(dividerColor);
mPaint.setStyle(Paint.Style.FILL);
}


//获取分割线尺寸
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.set(0, 0, 0, mDividerHeight);
}

//绘制分割线
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
if (mOrientation == LinearLayoutManager.VERTICAL) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}

//绘制横向 item 分割线
private void drawHorizontal(Canvas canvas, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getMeasuredWidth() - parent.getPaddingRight();
final int childSize = parent.getChildCount();
for (int i = 0; i < childSize; i++) {
final View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
final int top = child.getBottom() + layoutParams.bottomMargin;
final int bottom = top + mDividerHeight;
if (mDivider != null) {
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
if (mPaint != null) {
canvas.drawRect(left, top, right, bottom, mPaint);
}
}
}

//绘制纵向 item 分割线
private void drawVertical(Canvas canvas, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom();
final int childSize = parent.getChildCount();
for (int i = 0; i < childSize; i++) {
final View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + layoutParams.rightMargin;
final int right = left + mDividerHeight;
if (mDivider != null) {
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
if (mPaint != null) {
canvas.drawRect(left, top, right, bottom, mPaint);
}
}
}

}

mac android studio 几个文件夹夹路径

vue 目录解析

在mac资源目录下保存的的目录地址

gradle 关系文件

~/.gradle

Android 模拟器(AVDs) and *.keystore 文件

~/.android

Android SDK 工具

~/Library/Android*

完全移除android studio终端中执行下列命令

rm -Rf /Applications/Android\ Studio.app
rm -Rf ~/Library/Preferences/AndroidStudio
rm -Rf ~/Library/Preferences/com.google.android.studio.plist
rm -Rf ~/Library/Application\ Support/AndroidStudio

rm -Rf ~/Library/Logs/AndroidStudio
rm -Rf ~/Library/Caches/AndroidStudio

Android SO文件的兼容和适配

如何查看自己手机的架构?

1
adb shell getprop ro.product.cpu.abi

adb查看不同机型的CPU信息

1
adb shell cat  /proc/cpuinfo

其中
processor: 表示第几个核。
Features:表示当前CPU所支持的特性,比如neon,vfp等。
CPU architecture:7表示arm-v7,8表示arm-v8

2 cpu架构与so兼容

对于一个cpu是arm64-v8a架构的手机,它运行app时,进入jnilibs去读取库文件时,先看有没有arm64-v8a文件夹,如果没有该文件夹,去找armeabi-v7a文件夹,如果没有,再去找armeabi文件夹,如果连这个文件夹也没有,就抛出异常。
注意:这里说的是文件夹,即如果有arm64-v8a文件夹,那么就去找特定名称的.so文件,如果没有找到想要的.so文件,不会再往下(armeabi-v7a文件夹)找了,而是直接抛出异常。

现在大部分Android机型CPU都是armeabi-v7a和arm64-v8架构,而他们又是向下兼容,因此,仅适配一种CPU架构就能满足绝大部分要求,这样就能最大限度减少APK的大小。

方案一:只适配armeabi

1
2
3
ndk {
abiFilters 'armeabi'
}

优点:基本上适配了全部CPU架构(除了淘汰的mips和mips_64)。
缺点:性能低,相当于在绝大多数手机上都是需要辅助ABI或动态转码来兼容。

方案二:只适配 armeabi-v7a

1
2
3
ndk {
abiFilters 'armeabi-v7a'
}

同方案一,只是又筛掉了一部分老旧设备,在性能和兼容二者中比较平衡。

方案三:只适配 arm64-v8a

1
2
3
ndk {
abiFilters 'arm64-v8a'
}

优点:性能最佳
缺点:只能运行在arm64-v8上,要放弃部分老旧设备用户。

Android SO文件的兼容和适配

开发Android应用时,有时候Java层的编码不能满足实现需求,就需要到C/C++实现后生成SO文件,再用System.loadLibrary()加载进行调用,这里成为JNI层的实现。常见的场景如:加解密算法,音视频编解码等。在生成SO文件时,需要考虑适配市面上不同手机CPU架构,而生成支持不同平台的SO文件进行兼容。目前Android共支持七种不同类型的CPU架构,分别是:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起)。如果你要完美兼容所有类型的手机,理论上是要在的libs目录下放置各个架构平台的SO文件。
Alt text

这样一来,虽然可以兼容所有机型,但你的项目体积也会变得非常庞大。是否一定需要带入这么多SO文件去兼容呢?答案是否定的。

查看更多