需求:
1项目中有个需求,假设有N个数据,格式为8位纯数字字符串("00015756"),
2需要把N个数据按照尾号0-9分组排好。尾号为“0”的一组,尾号为“1”的一组...最多10组3在每一组之前添加新唤醒数据帧”AAAAAAAA“,在结尾添加新睡眠数据帧“BBBBBBBB”
4按照0-9分好组的顺序,蓝牙把这些数据发送给硬件
5每组中唤醒帧”AAAAAAAA“发完等待11s,(11s内硬件不回复任何内容),后发送数据,
发送完数据后蓝牙会立刻回复,收到数据后立即发送下一条数据(不等待3s超时),
如果超过3秒未回复,就要发送下一个数据。
最后发本组睡眠帧“BBBBBBBBB”,等待3s(3s内硬件不回复任何内容).循环剩下的组
想了很久,这个逻辑是无法用rxjava一行代码写下来的,因为处理的是两个数据流。
(蓝牙发送数据,蓝牙接收数据)
各位宝宝先看看本宝宝最后完美实现的结果
发送唤醒帧后间隔11s发数据,发送睡眠帧后间隔3s发数据,发送数据帧数据间隔3s,
如果收到回复数据直接发下一数据
实现代码贴上:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button button; Context context; private ArrayList<String> dataList; static Subscription subscription; static Disposable disposable; static String currentData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); context = this; setContentView(R.layout.activity_main); initView(); generateData(); sortArray(); } /** * 生成原始数据 */ public void generateData() { dataList = new ArrayList<>(); for (int i = 0; i < 30; i++) { dataList.add("000000" + i); } } /** * 数据排序 此方法写的太丑,可以跳过不看 * 1需要把N个数据按照尾号0-9分组排好。尾号为“0”的一组,尾号为“1”的一组...最多10组 * 2在每一组之前添加新数据”AAAAAAAA“,在结尾添加新数据“BBBBBBBB” * 例如: AAAAAAAA, 00000020, 00000010, 0000000, BBBBBBBB, */ public void sortArray() { ArrayList<String> list0 = new ArrayList<>(); list0.add("AAAAAAAA"); list0.add("BBBBBBBB"); ArrayList<String> list1 = (ArrayList<String>) list0.clone(); ArrayList<String> list2 = (ArrayList<String>) list0.clone(); ArrayList<String> list3 = (ArrayList<String>) list0.clone(); ArrayList<String> list4 = (ArrayList<String>) list0.clone(); ArrayList<String> list5 = (ArrayList<String>) list0.clone(); ArrayList<String> list6 = (ArrayList<String>) list0.clone(); ArrayList<String> list7 = (ArrayList<String>) list0.clone(); ArrayList<String> list8 = (ArrayList<String>) list0.clone(); ArrayList<String> list9 = (ArrayList<String>) list0.clone(); for (String ss : dataList) { if (ss.endsWith("0")) { list0.add(1, ss); } else if (ss.endsWith("1")) { list1.add(1, ss); } else if (ss.endsWith("2")) { list2.add(1, ss); } else if (ss.endsWith("3")) { list3.add(1, ss); } else if (ss.endsWith("4")) { list4.add(1, ss); } else if (ss.endsWith("5")) { list5.add(1, ss); } else if (ss.endsWith("6")) { list6.add(1, ss); } else if (ss.endsWith("7")) { list7.add(1, ss); } else if (ss.endsWith("8")) { list8.add(1, ss); } else if (ss.endsWith("9")) { list9.add(1, ss); } } dataList.clear(); dataList.addAll(list0); dataList.addAll(list1); dataList.addAll(list2); dataList.addAll(list3); dataList.addAll(list4); dataList.addAll(list5); dataList.addAll(list6); dataList.addAll(list7); dataList.addAll(list8); dataList.addAll(list9); System.out.println(dataList); } private void initView() { button = (Button) findViewById(R.id.button); button.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button: test(dataList); break; } } //处理业务逻辑的主要代码 private void test(List<String> list) { Flowable.fromIterable(list) .onBackpressureBuffer() .observeOn(AndroidSchedulers.mainThread()) .subscribe(new MySubscriber()); } /** * 倒计时3秒,用于蓝牙超时未反回时请求下一条数据 * @param time 延时时间 单位 :秒 */ public static void countDown(final int time) { //取消当前延时 if (disposable != null && !disposable.isDisposed()) { disposable.dispose(); } //开始下个延时 Observable.timer(time, TimeUnit.SECONDS) .subscribe(new Observer<Long>() { @Override public void onSubscribe(Disposable d) { disposable = d; } @Override public void onNext(Long value) { requestNext(); } @Override public void onError(Throwable e) {} @Override public void onComplete() {} }); } /** * 请求发送下一个数据 */ public static void requestNext() { if (subscription != null) { subscription.request(1); } } /** * 模拟蓝牙收到数据后并解析成功后的回调 * 收到数据后取消当前3s等待超时,并请求下一条数据 */ public static void onBluetoothReceive() { Observable.intervalRange(0, 30, 1300, 1800, TimeUnit.MILLISECONDS) .subscribe(new Consumer<Long>() { @Override public void accept(Long aLong) throws Exception { //假设是偶数的蓝牙数据都收到了硬件的回复 if (aLong % 2 == 0 && currentData.matches("\\d+")) { Log.e("蓝牙收到数据", "时间:" + String.format("%tT%n", new Date())); requestNext(); countDown(3); } } }); } static class MySubscriber implements Subscriber<String> { @Override public void onSubscribe(Subscription s) { subscription = s; s.request(1); onBluetoothReceive(); } @Override public void onNext(String o) { currentData = o; Log.d("蓝牙发送数据", o+"时间:" + String.format("%tT%n", new Date())); //如果发送数据延迟3s if (o.matches("\\d+")) { countDown(3); } else { //如果发送唤醒延迟11s (包含A) if (o.contains("A")) countDown(11); else //如果发送睡眠延迟3s countDown(3); } } @Override public void onError(Throwable t) {} @Override public void onComplete() {} } }
总结:
整个代码逻辑思路:1:把dataList发射出来,在MySubscriber中的onSubscribe中请求数据,并假装开启蓝牙数据接收回调
2:在onNext收到数据执行后,调用countDown开始超时的延时,如果收到数据,取消当前延时,否则在countDown内又请求数据
3:核心方法 subscription.requset(long n) 要求上游给下游发射多少个数据,这样可以主动控制
数据下发的速度。
4:Flowable 主要是解决背压问题的,但我用subscription.requset(long n)来处理异步回调,也不矛盾
当我把dataList添加300个元素时也没有出现什么异常情况,这其实和数据数量没啥关系,和处理速度有
关。我是参考:https://www.jianshu.com/p/ff8167c1d191