Browse Source

- 新增下载图片请求(要求Glide依赖)
- 解决异常无法正常打印

drake 5 years ago
parent
commit
b23ba176dd

+ 1 - 1
README.md

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

+ 4 - 0
net/build.gradle

@@ -32,6 +32,7 @@ android {
 
 dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation 'androidx.appcompat:appcompat:1.1.0'
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
     testImplementation 'junit:junit:4.12'
     androidTestImplementation 'androidx.test:runner:1.2.0'
@@ -41,7 +42,10 @@ dependencies {
 
     compileOnly 'androidx.appcompat:appcompat:1.1.0'
     compileOnly 'com.github.liangjingkanji:BRV:1.1.1'
+    compileOnly 'com.github.bumptech.glide:glide:4.9.0'
 
     compileOnly 'io.reactivex.rxjava2:rxkotlin:2.3.0'
     compileOnly 'io.reactivex.rxjava2:rxandroid:2.1.1'
+
+
 }

+ 138 - 33
net/src/main/java/com/drake/net/Net.kt

@@ -9,6 +9,8 @@
 
 package com.drake.net
 
+import android.content.Context
+import com.bumptech.glide.Glide
 import com.drake.net.error.ResponseException
 import com.yanzhenjie.kalle.Kalle
 import com.yanzhenjie.kalle.download.UrlDownload
@@ -17,7 +19,9 @@ import com.yanzhenjie.kalle.simple.SimpleUrlRequest
 import io.reactivex.Observable
 import io.reactivex.android.schedulers.AndroidSchedulers
 import io.reactivex.schedulers.Schedulers
+import java.io.File
 
+// <editor-fold desc="异步请求">
 
 /**
  * Get请求
@@ -61,20 +65,27 @@ inline fun <reified M> get(
         .observeOn(AndroidSchedulers.mainThread())
 }
 
-
-inline fun <reified M> syncGet(
+/**
+ * Post提交
+ * @param path String 网络路径, 非绝对路径会加上HOST为前缀
+ * @see NetConfig.host
+ * @param isAbsolutePath Boolean 是否是绝对路径
+ * @param block SimpleBodyRequest.Api.() -> UnitUtils
+ * @return Observable<M> 结果会在主线程
+ */
+inline fun <reified M> post(
     path: String,
     isAbsolutePath: Boolean = false,
-    noinline block: (SimpleUrlRequest.Api.() -> Unit)? = null
+    noinline block: (SimpleBodyRequest.Api.() -> Unit)? = null
 ): Observable<M> {
 
     return Observable.create<M> {
         try {
-            val get = Kalle.get(if (isAbsolutePath) path else (NetConfig.host + path))
+            val post = Kalle.post(if (isAbsolutePath) path else (NetConfig.host + path))
             val response = if (block == null) {
-                get.perform(M::class.java, String::class.java)
+                post.perform<M, String>(M::class.java, String::class.java)
             } else {
-                get.apply(block).perform<M, String>(M::class.java, String::class.java)
+                post.apply(block).perform<M, String>(M::class.java, String::class.java)
             }
 
             if (!it.isDisposed) {
@@ -92,31 +103,108 @@ inline fun <reified M> syncGet(
                 it.onError(e)
             }
         }
-    }.onTerminateDetach()
+    }.onTerminateDetach().subscribeOn(Schedulers.computation())
+        .observeOn(AndroidSchedulers.mainThread())
 }
 
 
 /**
- * Post提交
+ * 下载文件
+ *
  * @param path String 网络路径, 非绝对路径会加上HOST为前缀
  * @see NetConfig.host
- * @param isAbsolutePath Boolean 是否是绝对路径
- * @param block SimpleBodyRequest.Api.() -> UnitUtils
- * @return Observable<M> 结果会在主线程
+ * @param directory String 下载文件存放目录 {默认存在android/data/packageName/cache目录}
+ * @param isAbsolutePath Boolean 下载链接是否是绝对路径
+ * @param block 请求参数
+ * @return Observable<String> 结果会在主线程
  */
-inline fun <reified M> post(
+fun download(
     path: String,
+    directory: String = NetConfig.app.externalCacheDir!!.absolutePath,
     isAbsolutePath: Boolean = false,
-    noinline block: (SimpleBodyRequest.Api.() -> Unit)? = null
+    block: (UrlDownload.Api.() -> Unit)? = null
+): Observable<String> {
+
+    return Observable.create<String> {
+        try {
+            val realPath = if (isAbsolutePath) path else (NetConfig.host + path)
+
+            val download = Kalle.Download.get(realPath).directory(directory)
+
+            val filePath = if (block == null) {
+                download.perform()
+            } else {
+                download.apply(block).perform()
+            }
+
+            if (!it.isDisposed) {
+                it.onNext(filePath)
+                it.onComplete()
+            }
+        } catch (e: Exception) {
+            if (!it.isDisposed) {
+                it.onError(e)
+            }
+        }
+    }.onTerminateDetach().subscribeOn(Schedulers.computation())
+        .observeOn(AndroidSchedulers.mainThread())
+}
+
+/**
+ * 下载图片, 图片宽高要求要么同时指定要么同时不指定
+ *
+ * @receiver Context
+ * @param url String
+ * @param with Int 图片宽度
+ * @param height Int 图片高度
+ * @return Observable<File>
+ */
+fun Context.downloadImg(url: String, with: Int = -1, height: Int = -1): Observable<File> {
+
+    return Observable.create<File> {
+
+        Glide.with(this).downloadOnly()
+
+        val download = Glide.with(this).download(url)
+
+        val futureTarget = if (with == -1 && height == -1) {
+            download.submit()
+        } else {
+            download.submit(with, height)
+        }
+
+        try {
+            val file = futureTarget.get()
+            if (!it.isDisposed) {
+                it.onNext(file)
+                it.onComplete()
+            }
+        } catch (e: Exception) {
+            if (!it.isDisposed) {
+                it.onError(e)
+            }
+        }
+
+    }.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread())
+}
+
+// </editor-fold>
+
+// <editor-fold desc="同步请求">
+
+inline fun <reified M> syncGet(
+    path: String,
+    isAbsolutePath: Boolean = false,
+    noinline block: (SimpleUrlRequest.Api.() -> Unit)? = null
 ): Observable<M> {
 
     return Observable.create<M> {
         try {
-            val post = Kalle.post(if (isAbsolutePath) path else (NetConfig.host + path))
+            val get = Kalle.get(if (isAbsolutePath) path else (NetConfig.host + path))
             val response = if (block == null) {
-                post.perform<M, String>(M::class.java, String::class.java)
+                get.perform(M::class.java, String::class.java)
             } else {
-                post.apply(block).perform<M, String>(M::class.java, String::class.java)
+                get.apply(block).perform<M, String>(M::class.java, String::class.java)
             }
 
             if (!it.isDisposed) {
@@ -134,11 +222,9 @@ inline fun <reified M> post(
                 it.onError(e)
             }
         }
-    }.onTerminateDetach().subscribeOn(Schedulers.computation())
-        .observeOn(AndroidSchedulers.mainThread())
+    }.onTerminateDetach()
 }
 
-
 inline fun <reified M> syncPost(
     path: String,
     isAbsolutePath: Boolean = false,
@@ -172,18 +258,7 @@ inline fun <reified M> syncPost(
     }.onTerminateDetach()
 }
 
-
-/**
- * 下载文件
- *
- * @param path String 网络路径, 非绝对路径会加上HOST为前缀
- * @see NetConfig.host
- * @param directory String 下载文件存放目录 {默认存在android/data/packageName/cache目录}
- * @param isAbsolutePath Boolean 下载链接是否是绝对路径
- * @param block 请求参数
- * @return Observable<String> 结果会在主线程
- */
-fun download(
+fun syncDownload(
     path: String,
     directory: String = NetConfig.app.externalCacheDir!!.absolutePath,
     isAbsolutePath: Boolean = false,
@@ -211,8 +286,38 @@ fun download(
                 it.onError(e)
             }
         }
-    }.onTerminateDetach().subscribeOn(Schedulers.computation())
-        .observeOn(AndroidSchedulers.mainThread())
+    }.onTerminateDetach()
 }
 
+fun Context.syncDownloadImg(url: String, with: Int = 0, height: Int = 0): Observable<File> {
+
+    return Observable.create<File> {
+
+        Glide.with(this).downloadOnly()
+
+        val download = Glide.with(this).download(url)
+
+        val futureTarget = if (with == 0 && height == 0) {
+            download.submit()
+        } else {
+            download.submit(with, height)
+        }
+
+        try {
+            val file = futureTarget.get()
+            if (!it.isDisposed) {
+                it.onNext(file)
+                it.onComplete()
+            }
+        } catch (e: Exception) {
+            if (!it.isDisposed) {
+                it.onError(e)
+            }
+        }
+
+    }.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread())
+}
+
+// </editor-fold>
+
 

+ 37 - 7
net/src/main/java/com/drake/net/NetConfig.kt

@@ -21,10 +21,10 @@ import com.drake.net.error.RequestParamsException
 import com.drake.net.error.ResponseException
 import com.drake.net.error.ServerResponseException
 import com.drake.net.observer.DialogObserver
-import com.drake.net.observer.PageObserver
 import com.yanzhenjie.kalle.Kalle
 import com.yanzhenjie.kalle.KalleConfig
 import com.yanzhenjie.kalle.exception.*
+import java.util.concurrent.ExecutionException
 
 
 object NetConfig {
@@ -33,8 +33,9 @@ object NetConfig {
     lateinit var app: Application
 
     internal var defaultToast: Toast? = null
-    internal var onError: Throwable.() -> Unit = {
+    internal var defaultDialog: (DialogObserver<*>.(context: FragmentActivity) -> Dialog)? = null
 
+    internal var onError: Throwable.() -> Unit = {
 
         val message = when (this) {
             is NetworkError -> app.getString(R.string.network_error)
@@ -50,18 +51,47 @@ object NetConfig {
             is ParseError -> app.getString(R.string.parse_error)
             is RequestParamsException -> app.getString(R.string.request_error)
             is ServerResponseException -> app.getString(R.string.server_error)
+            is ExecutionException -> app.getString(R.string.image_error)
             is ResponseException -> msg
             else -> {
                 app.getString(R.string.other_error)
             }
-        }
 
-        if (BuildConfig.DEBUG) {
-            printStackTrace()
         }
 
+        printStackTrace()
         app.toast(message)
     }
+
+    internal var onPageError: Throwable.(pageRefreshLayout: PageRefreshLayout) -> Unit = {
+
+        val message = when (this) {
+            is NetworkError -> app.getString(R.string.network_error)
+            is URLError -> app.getString(R.string.url_error)
+            is HostError -> app.getString(R.string.host_error)
+            is ConnectTimeoutError -> app.getString(R.string.connect_timeout_error)
+            is ReadException -> app.getString(R.string.read_exception)
+            is WriteException -> app.getString(R.string.write_exception)
+            is ConnectException -> app.getString(R.string.connect_exception)
+            is ReadTimeoutError -> app.getString(R.string.read_timeout_error)
+            is DownloadError -> app.getString(R.string.download_error)
+            is NoCacheError -> app.getString(R.string.no_cache_error)
+            is ParseError -> app.getString(R.string.parse_error)
+            is RequestParamsException -> app.getString(R.string.request_error)
+            is ServerResponseException -> app.getString(R.string.server_error)
+            is ResponseException -> msg
+            else -> {
+                app.getString(R.string.other_error)
+            }
+        }
+
+        printStackTrace()
+        when (this) {
+            is ParseError, is ResponseException -> {
+                app.toast(message)
+            }
+        }
+    }
 }
 
 
@@ -108,7 +138,7 @@ fun KalleConfig.Builder.onError(block: Throwable.() -> Unit) {
  * @param block [@kotlin.ExtensionFunctionType] Function2<Throwable, [@kotlin.ParameterName] PageRefreshLayout, Unit>
  */
 fun KalleConfig.Builder.onPageError(block: Throwable.(pageRefreshLayout: PageRefreshLayout) -> Unit) {
-    PageObserver.onPageError = block
+    NetConfig.onPageError = block
 }
 
 
@@ -118,6 +148,6 @@ fun KalleConfig.Builder.onPageError(block: Throwable.(pageRefreshLayout: PageRef
  * @param block [@kotlin.ExtensionFunctionType] Function2<DialogObserver<*>, [@kotlin.ParameterName] FragmentActivity, Dialog>
  */
 fun KalleConfig.Builder.onDialog(block: (DialogObserver<*>.(context: FragmentActivity) -> Dialog)) {
-    DialogObserver.defaultDialog = block
+    NetConfig.defaultDialog = block
 }
 

+ 3 - 2
net/src/main/java/com/drake/net/observer/ObserverUtils.kt → net/src/main/java/com/drake/net/ObserverUtils.kt

@@ -2,10 +2,10 @@
  * Copyright (C) 2018, Umbrella CompanyLimited All rights reserved.
  * Project:Net
  * Author:Drake
- * Date:9/16/19 12:54 AM
+ * Date:11/19/19 9:23 PM
  */
 
-package com.drake.net.observer
+package com.drake.net
 
 import android.app.Dialog
 import android.view.View
@@ -13,6 +13,7 @@ import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentActivity
 import androidx.lifecycle.LifecycleOwner
 import com.drake.brv.PageRefreshLayout
+import com.drake.net.observer.*
 import com.drake.statelayout.StateLayout
 import io.reactivex.Observable
 

+ 3 - 6
net/src/main/java/com/drake/net/observer/DialogObserver.kt

@@ -17,6 +17,7 @@ import androidx.lifecycle.Lifecycle.Event
 import androidx.lifecycle.LifecycleObserver
 import androidx.lifecycle.OnLifecycleEvent
 import com.drake.net.NetConfig
+import com.drake.net.NetConfig.defaultDialog
 import io.reactivex.observers.DefaultObserver
 
 /**
@@ -43,12 +44,6 @@ abstract class DialogObserver<M>(
         cancelable: Boolean = true
     ) : this(fragment?.activity, dialog, cancelable)
 
-    companion object {
-
-        internal var defaultDialog: (DialogObserver<*>.(context: FragmentActivity) -> Dialog)? =
-            null
-    }
-
 
     override fun onStart() {
         activity ?: return
@@ -77,6 +72,8 @@ abstract class DialogObserver<M>(
         }
     }
 
+    abstract override fun onNext(it: M)
+
     /**
      * 关闭进度对话框并提醒错误信息
      *

+ 2 - 0
net/src/main/java/com/drake/net/observer/NetObserver.kt

@@ -24,6 +24,8 @@ abstract class NetObserver<M>() : DefaultObserver<M>(), LifecycleObserver {
         lifecycleOwner?.lifecycle?.addObserver(this)
     }
 
+    abstract override fun onNext(it: M)
+
     /**
      * 关闭进度对话框并提醒错误信息
      *

+ 9 - 49
net/src/main/java/com/drake/net/observer/PageObserver.kt

@@ -11,14 +11,7 @@ import android.view.View
 import android.view.View.OnAttachStateChangeListener
 import com.drake.brv.BindingAdapter
 import com.drake.brv.PageRefreshLayout
-import com.drake.net.BuildConfig
-import com.drake.net.NetConfig
-import com.drake.net.R
-import com.drake.net.error.RequestParamsException
-import com.drake.net.error.ResponseException
-import com.drake.net.error.ServerResponseException
-import com.drake.net.toast
-import com.yanzhenjie.kalle.exception.*
+import com.drake.net.NetConfig.onPageError
 import io.reactivex.observers.DefaultObserver
 
 /**
@@ -26,45 +19,10 @@ import io.reactivex.observers.DefaultObserver
  * 自动展示缺省页
  * 自动分页加载
  */
-abstract class PageObserver<M>(val pageRefreshLayout: PageRefreshLayout) : DefaultObserver<M>() {
-
-    companion object {
-        internal var onPageError: Throwable.(pageRefreshLayout: PageRefreshLayout) -> Unit = {
-
-            val message = when (this) {
-                is NetworkError -> NetConfig.app.getString(R.string.network_error)
-                is URLError -> NetConfig.app.getString(R.string.url_error)
-                is HostError -> NetConfig.app.getString(R.string.host_error)
-                is ConnectTimeoutError -> NetConfig.app.getString(R.string.connect_timeout_error)
-                is ReadException -> NetConfig.app.getString(R.string.read_exception)
-                is WriteException -> NetConfig.app.getString(R.string.write_exception)
-                is ConnectException -> NetConfig.app.getString(R.string.connect_exception)
-                is ReadTimeoutError -> NetConfig.app.getString(R.string.read_timeout_error)
-                is DownloadError -> NetConfig.app.getString(R.string.download_error)
-                is NoCacheError -> NetConfig.app.getString(R.string.no_cache_error)
-                is ParseError -> NetConfig.app.getString(R.string.parse_error)
-                is RequestParamsException -> NetConfig.app.getString(R.string.request_error)
-                is ServerResponseException -> NetConfig.app.getString(R.string.server_error)
-                is ResponseException -> msg
-                else -> {
-                    NetConfig.app.getString(R.string.other_error)
-                }
-            }
-
-            if (BuildConfig.DEBUG) {
-                printStackTrace()
-            }
-
-            when (this) {
-                is ParseError, is ResponseException -> {
-                    NetConfig.app.toast(message)
-                }
-            }
-        }
-    }
+abstract class PageObserver<M>(val page: PageRefreshLayout) : DefaultObserver<M>() {
 
     init {
-        pageRefreshLayout.addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
+        page.addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
             override fun onViewAttachedToWindow(v: View) {
 
             }
@@ -75,14 +33,16 @@ abstract class PageObserver<M>(val pageRefreshLayout: PageRefreshLayout) : Defau
         })
     }
 
+    abstract override fun onNext(it: M)
+
     /**
      * 关闭进度对话框并提醒错误信息
      *
      * @param e 包括错误信息
      */
     override fun onError(e: Throwable) {
-        pageRefreshLayout.showError()
-        onPageError.invoke(e, pageRefreshLayout)
+        page.showError()
+        onPageError.invoke(e, page)
     }
 
     override fun onComplete() {
@@ -94,11 +54,11 @@ abstract class PageObserver<M>(val pageRefreshLayout: PageRefreshLayout) : Defau
      * @param data 要添加的数据集
      */
     fun addData(data: List<Any>, hasMore: BindingAdapter.() -> Boolean) {
-        pageRefreshLayout.addData(data, hasMore)
+        page.addData(data, hasMore)
     }
 
 
     fun showEmpty() {
-        pageRefreshLayout.showEmpty()
+        page.showEmpty()
     }
 }

+ 8 - 6
net/src/main/java/com/drake/net/observer/RefreshObserver.kt

@@ -17,14 +17,14 @@ import io.reactivex.observers.DefaultObserver
  * 自动结束下拉刷新
  */
 abstract class RefreshObserver<M>(
-    val refreshLayout: SmartRefreshLayout,
-    val enableLoadMore: Boolean = false
+    val refresh: SmartRefreshLayout,
+    val loadMore: Boolean = false
 ) : DefaultObserver<M>() {
 
 
     init {
-        refreshLayout.setEnableLoadMore(enableLoadMore)
-        refreshLayout.addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
+        refresh.setEnableLoadMore(loadMore)
+        refresh.addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
             override fun onViewAttachedToWindow(v: View) {
 
             }
@@ -35,12 +35,14 @@ abstract class RefreshObserver<M>(
         })
     }
 
+    abstract override fun onNext(it: M)
+
     override fun onError(e: Throwable) {
-        refreshLayout.finishRefresh(false)
+        refresh.finishRefresh(false)
         NetConfig.onError(e)
     }
 
     override fun onComplete() {
-        refreshLayout.finishRefresh(true)
+        refresh.finishRefresh(true)
     }
 }

+ 3 - 1
net/src/main/java/com/drake/net/observer/StateObserver.kt

@@ -18,7 +18,7 @@ import io.reactivex.observers.DefaultObserver
 /**
  * 自动显示多状态布局
  */
-abstract class StateObserver<S> : DefaultObserver<S> {
+abstract class StateObserver<M> : DefaultObserver<M> {
 
     var stateLayout: StateLayout
 
@@ -55,6 +55,8 @@ abstract class StateObserver<S> : DefaultObserver<S> {
         })
     }
 
+    abstract override fun onNext(it: M)
+
     override fun onError(e: Throwable) {
         stateLayout.showError()
     }

+ 1 - 0
net/src/main/res/values/strings.xml

@@ -16,6 +16,7 @@
     <string name="parse_error">解析数据时发生异常</string>
     <string name="request_error">请求参数错误</string>
     <string name="server_error">服务响应错误</string>
+    <string name="image_error">图片下载错误</string>
     <string name="other_error">服务器未响应</string>
 
 

+ 2 - 0
sample/build.gradle

@@ -43,4 +43,6 @@ dependencies {
     implementation  'com.scwang.smart:refresh-footer-classics:2.0.0-alpha-1'
     implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
     implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
+
+    implementation 'com.github.bumptech.glide:glide:4.9.0'
 }

+ 0 - 2
sample/src/main/java/com/drake/net/sample/App.kt

@@ -22,8 +22,6 @@ class App : Application() {
             })
         }
 
-
-
         SmartRefreshLayout.setDefaultRefreshHeaderCreator { context, layout -> ClassicsHeader(this) }
         SmartRefreshLayout.setDefaultRefreshFooterCreator { context, layout -> ClassicsFooter(this) }
     }

+ 7 - 0
sample/src/main/java/com/drake/net/sample/MainActivity.kt

@@ -2,6 +2,8 @@ package com.drake.net.sample
 
 import android.os.Bundle
 import androidx.appcompat.app.AppCompatActivity
+import com.drake.net.dialog
+import com.drake.net.downloadImg
 
 class MainActivity : AppCompatActivity() {
 
@@ -10,5 +12,10 @@ class MainActivity : AppCompatActivity() {
         setContentView(R.layout.activity_main)
 
 
+        downloadImg("static-mobile.xbzhaopin.com/xy00000/images_fh/upload/2019/04/1555745799934.png").dialog(
+            this
+        ) {
+
+        }
     }
 }

+ 2 - 1
sample/src/main/res/layout/activity_main.xml

@@ -6,7 +6,8 @@
     android:layout_height="match_parent"
     tools:context=".MainActivity">
 
-    <TextView
+    <ImageView
+        android:id="@+id/iv"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="Hello World!" />