浏览代码

- 增加轮询器: Interval
- 比RxJava增加 开始|停止|暂停|继续 功能, 应对任何计时功能

drake 5 年之前
父节点
当前提交
da1ca258c0

+ 1 - 1
README.md

@@ -54,7 +54,7 @@ allprojects {
 module 的 build.gradle
 
 ```groovy
-implementation 'com.github.liangjingkanji:Net:1.2.8'
+implementation 'com.github.liangjingkanji:Net:1.2.9'
 ```
 
 

+ 155 - 0
sample/src/main/java/com/drake/net/sample/Interval.kt

@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2018, Umbrella CompanyLimited All rights reserved.
+ * Project:Net
+ * Author:Drake
+ * Date:11/26/19 11:11 PM
+ */
+package com.drake.net.sample
+
+import io.reactivex.Observable
+import io.reactivex.Observer
+import io.reactivex.Scheduler
+import io.reactivex.disposables.Disposable
+import io.reactivex.internal.disposables.DisposableHelper
+import io.reactivex.internal.schedulers.TrampolineScheduler
+import io.reactivex.schedulers.Schedulers
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicReference
+
+
+/**
+ * 轮循器
+ *
+ * 多个观察者可观察同一个计时器
+ * 开始 | 暂停 | 继续 | 结束
+ */
+class Interval(
+    var end: Long, // -1 表示永远不结束, 可以修改
+    private val period: Long,
+    private val unit: TimeUnit,
+    private val initialDelay: Long = 0,
+    private val start: Long = 0,
+    private val scheduler: Scheduler = Schedulers.computation()
+) : Observable<Long>() {
+
+    /**
+     * 不会自动结束的轮循器
+     */
+    constructor(
+        period: Long,
+        unit: TimeUnit,
+        initialDelay: Long = 0,
+        scheduler: Scheduler = Schedulers.computation()
+    ) : this(-1, period, unit, initialDelay, 0, scheduler)
+
+    private var observerList = ArrayList<IntervalRangeObserver>()
+    private var pause = false
+    private var stop = false
+
+
+    public override fun subscribeActual(observer: Observer<in Long?>) {
+
+        val agentObserver = IntervalRangeObserver(observer)
+
+        observerList.add(agentObserver)
+        observer.onSubscribe(agentObserver)
+
+        if (observerList.size == 1) {
+            val sch = scheduler
+            val iterator = {
+
+                if (!pause) {
+                    synchronized(this) {
+                        count += 1
+                    }
+                    for (i in 0 until observerList.size) {
+                        observerList[i].run(count, end, stop)
+                    }
+                }
+            }
+            if (sch is TrampolineScheduler) {
+                val worker = sch.createWorker()
+                agentObserver.setResource(worker)
+                worker.schedulePeriodically(iterator, initialDelay, period, unit)
+            } else {
+                val d = sch.schedulePeriodicallyDirect(iterator, initialDelay, period, unit)
+                agentObserver.setResource(d)
+            }
+        }
+    }
+
+    // <editor-fold desc="操作">
+
+
+    /**
+     * 计数器
+     */
+    var count = start
+
+    /**
+     * 停止轮循器
+     * 如果开启轮循器请订阅观察者[subscribe], 多个观察者观察的同一轮循计数器
+     */
+    fun stop() {
+        stop = true
+    }
+
+    /**
+     * 重置轮循器
+     */
+    fun reset() {
+        count = start
+    }
+
+    /**
+     * 暂停轮循
+     */
+    fun pause() {
+        pause = true
+    }
+
+    /**
+     * 继续轮循器
+     */
+    fun resume() {
+        pause = false
+    }
+
+    // </editor-fold>
+
+    class IntervalRangeObserver(
+        private val downstream: Observer<in Long?>
+    ) : AtomicReference<Disposable?>(), Disposable {
+
+        override fun dispose() {
+            DisposableHelper.dispose(this)
+        }
+
+        override fun isDisposed(): Boolean {
+            return get() === DisposableHelper.DISPOSED
+        }
+
+        fun run(count: Long, end: Long, stop: Boolean) {
+            if (!isDisposed) {
+
+                downstream.onNext(count)
+
+                if (end != -1L && count == end || stop) {
+                    DisposableHelper.dispose(this)
+                    downstream.onComplete()
+                    return
+                }
+            }
+        }
+
+        fun setResource(d: Disposable?) {
+            DisposableHelper.setOnce(this, d)
+        }
+
+        companion object {
+            private const val serialVersionUID = 1891866368734007884L
+        }
+
+    }
+
+}

+ 1 - 5
sample/src/main/java/com/drake/net/sample/MainActivity.kt

@@ -1,7 +1,6 @@
 package com.drake.net.sample
 
 import android.os.Bundle
-import android.util.Log
 import androidx.appcompat.app.AppCompatActivity
 import com.drake.net.download
 import com.drake.net.observer.net
@@ -17,14 +16,11 @@ class MainActivity : AppCompatActivity() {
             "https://cdn.sspai.com/article/ebe361e4-c891-3afd-8680-e4bad609723e.jpg?imageMogr2/quality/95/thumbnail/!2880x620r/gravity/Center/crop/2880x620/interlace/1",
             isAbsolutePath = true
         ).net(this) {
-            Log.d("日志", "(MainActivity.kt:22)    下载文件路径 = $it")
         }.error {
-            Log.d("日志", "(MainActivity.kt:24)    fuck error")
             handleError(it)
         }
 
-
-        // netObserver.dispose() // 立刻取消
+        netObserver.dispose() // 立刻取消
 
     }
 }

+ 42 - 5
sample/src/main/res/layout/activity_main.xml

@@ -1,15 +1,52 @@
 <?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/content"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:orientation="vertical"
     tools:context=".MainActivity">
 
-    <ImageView
-        android:id="@+id/iv"
+
+    <TextView
+        android:id="@+id/textView"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:text="Hello World!" />
+        android:text="TextView" />
+
+    <TextView
+        android:id="@+id/textView2"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="TextView" />
+
+    <TextView
+        android:id="@+id/textView3"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="TextView" />
+
+    <TextView
+        android:id="@+id/textView4"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="TextView" />
+
+    <TextView
+        android:id="@+id/textView5"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="TextView" />
 
-</FrameLayout>
+    <TextView
+        android:id="@+id/textView6"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="TextView" />
+
+    <TextView
+        android:id="@+id/textView7"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="TextView" />
+</LinearLayout>