寫這個庫的目的是爲了可以讓代碼看起來簡約,優雅。本庫是使用Kotlin實現的,因此它只支持Kotlin,同時集成了上傳,下載,斷點續傳,添加通用參數,和參數簽名等功能,節省開發時間。java
github地址:github.com/VipMinF/Lyc…git
本庫其餘相關文章github
dependencies {
implementation 'com.vecharm:lycheehttp:1.0.2'
}
複製代碼
若是你喜歡用RxJava 還須要加入json
dependencies {
//RxJava
implementation 'com.vecharm.lycheehttp:lychee_rxjava:1.0.2'
//或者 RxJava2
implementation 'com.vecharm.lycheehttp:lychee_rxjava2:1.0.2'
}
複製代碼
在Application中調用LycheeHttp::ini
,若是你不喜歡這種方式,本身寫個單例,調用時才初始化也是能夠的,比較簡單我就不寫了。api
override fun onCreate() {
super.onCreate()
LycheeHttp.init(MyCoreConfig(this))
}
複製代碼
下載只須要使用 Download
註解API就能夠啦服務器
@Download
@GET("https://xxxx/xxxx.apk")
fun download(): Call<DownloadBean>
複製代碼
Upload
進行註解@Upload
@Multipart
@POST("http://xxx/xxx")
fun upload(@Part("file") file: File): Call<ResultBean<UploadResult>>
複製代碼
FileType("png")
或者FileType("image/png")
@Multipart
@POST("http:/xxx/xxx")
fun upload(@Part("file") @FileType("png") file: File): Call<ResultBean<UploadResult>>
複製代碼
MultiFileType("png")
或者MultiFileType("image/png")
@Multipart
@MultiFileType("png")
@POST("http://xxx/xxx")
fun upload(@PartMap map: MutableMap<String, Any>): Call<ResultBean<UploadResult>>
複製代碼
API的定義和原來沒有什麼區別,只是多了幾個註解,上傳不再用RequestBody做爲參數了。若是要打印文件的內容,可使用FileLog
,通常這種需求比較少。app
//普通請求
getService<API>().hello().request {
onSuccess = { Toast.makeText(App.app, it.data ?: "", Toast.LENGTH_SHORT).show() }
onErrorMessage = {}
onCompleted = {}
}
//單個文件下載
getService<API>().download().request(File(App.app.externalCacheDir, "xx.apk")) {
onSuccess = { Toast.makeText(App.app, "${it.downloadInfo?.fileName} 下載完成", Toast.LENGTH_SHORT).show() }
onErrorMessage = {}
onCompleted = {}
}
//多任務下載
addDownloadTaskButton.setOnClickListener {
val downloadTask = DownloadTask()
val file = File(App.app.externalCacheDir, "qq${adapter.data.size + 1}.apk"
downloadTask.download("https://xxx/xxx.apk", file)
adapter.addData(downloadTask)
}
//多任務上傳
addUploadTaskButton.setOnClickListener {
val uploadTask = UploadTask()
uploadTask.upload(File(App.app.externalCacheDir, "qq${adapter.data.size + 1}.apk"))
adapter.addData(uploadTask)
}
複製代碼
三個註解能夠同時使用,優先級FileType
> MultiFileType
> Upload
,喜歡哪種就看你本身了框架
對於多任務上傳和下載,因爲每一個業務的API定義可能不同,因此UploadTask
和DownloadTask
須要本身實現,下面是兩個例子(Rxjava2版的),也能夠徹底本身寫。dom
//上傳
class UploadTask : DefaultTask() {
override fun onCancel() {}
override fun onResume(url: String, filePath: String) {}
fun upload(file: File) {
getService<API>().upload(file).upload {
onUpdateProgress = onUpdate
onSuccess = { Toast.makeText(App.app, "${id}上傳完成", Toast.LENGTH_LONG).show() }
}
}
}
//下載
class DownloadTask : DefaultTask() {
override fun onCancel() {
service?.dispose()
}
override fun onResume(url: String, filePath: String) {
download(url, File(filePath))
}
var service: Disposable? = null
fun download(url: String, saveFile: File) {
setPathInfo(url, saveFile.absolutePath)
service = getService<API>().download(url, range.bytesRange()).request(saveFile.setRange(range)) {
onUpdateProgress = onUpdate
onSuccess = { Toast.makeText(App.app, "${id}下載完成", Toast.LENGTH_LONG).show() }
}
}
}
複製代碼
RxJavaCallAdapterFactory
或者你的自定義的實現class RxJavaConfig(val context: Application) : DefaultCoreConfig() {
......
override fun onInitRetrofit(builder: Retrofit.Builder): Retrofit.Builder {
builder.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
return super.onInitRetrofit(builder)
}
}
複製代碼
class SimplestConfig:DefaultCoreConfig() {
override fun getHostString() = "https://host:port/"
}
複製代碼
若是你不喜歡默認的配置,能夠實現ICoreConfig
接口本身寫一個,下面的我都是基於默認配置Defaultxxxx
來說。ide
override DefaultCoreConfig::isShowLog
override DefaultCoreConfig::getGsonConverterFactory
override DefaultCoreConfig::getCookieJar
,能夠試試PersistentCookieJar
ResponseBean
或者說項目比較複雜,一些接口返回ResultBean,一些接口返回OKBean,那麼能夠實現IResponseHandler
接口。並在api執行以前調用DefaultCoreConfig:registerResponseHandler
class SimplestConfig : DefaultCoreConfig() {
init {
/* * 註冊自定義的返回值處理,能夠註冊多個 * */
registerResponseHandler(ResponseBean::class.java, MyResponseHandler::class.java)
}
.......
}
class MyResponseHandler : DefaultResponseHandler() {
override fun onError(status: Int, message: String?) {
if (10001 == status) {//沒有登錄
Toast.makeText(App.app, "沒有登錄", Toast.LENGTH_LONG).show()
}
super.onError(status, message)
Toast.makeText(App.app, "$status:$message", Toast.LENGTH_LONG).show()
}
}
複製代碼
override DefaultCoreConfig::getRequestConfig
,而後繼承DefaultRequestConfig
,下面是例子。class MyRequestConfig : DefaultRequestConfig() {
/** * 添加默認頭部參數 * */
override fun addHeaders(newRequestBuild: Request.Builder, oldRequest: Request) {
newRequestBuild.addHeader("Accept", "application/json")
newRequestBuild.addHeader("Accept-Language", "zh")
}
/** * 添加通用參數 * */
override fun onAddCommonParams(map: MutableMap<String, String>) {
map["app_version"] = com.vecharm.lychee.sample.BuildConfig.VERSION_CODE.toString()
map["nonce"] = map["nonce"] ?: randomUUID()
map["timestamp"] = System.currentTimeMillis().div(1000).toString()
map["pkg_name"] = App.app.packageName
map["app_sign"] = "s9fkjs0a-d234ew-adfadf"
}
/** * 參數簽名 * */
override fun onSignParams(map: MutableMap<String, String>) {
super.onSignParams(map)
//簽完名將key移除,避免將這個傳到服務器
map.remove("app_sign")
}
/** * 不須要參與簽名的字段,文件參與簽名默認是進行md5 * */
override fun unSignParamNames() = arrayOf("file")
/** * 是否參數簽名 * */
override fun isSignParam() = true
}
複製代碼
MediaType
列表,放在DefaultMediaTypeManager
,目前裏面收集了300個左右,若是不夠用,能夠繼承DefaultMediaTypeManager
在types
添加,或者override DefaultMediaTypeManager::filter
。ISpeedComputer
,在初始化時替換ProgressHelper::downloadSpeedComputer
和ProgressHelper::uploadSpeedComputer
。後話:第一次寫文章,寫的頭暈腦漲,寫的不太好。若是這篇文章對各位大大有用的話,能夠給我點個贊鼓勵一下我哦,感謝!