可能部分人會才取接口增長onError的方案,至於緣由,能夠是由於不一樣線程拋出的異常,android沒法直接在最外層try catch住,可是這種方案在調用層次一多,書寫上就更加繚亂了。java
val mainHandler = Handler(Looper.getMainLooper())
interface CallBack {
fun onSuccess(response : String)
fun onError(errorCode : Int)
}
/**
* 1.根據url地址下載播放列表, 網絡訪問,運行後臺
*/
fun download(url : String, callBack : CallBack) {
thread {
println("根據url下載播放節目表 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
callBack.onSuccess("節目表")
}
}
/**
* 2.先解析下載好播放列表文件中佈局相關信息,協議解析,運行後臺
*/
fun parseLayout(filePath : String, callBack : CallBack) {
thread {
println("先解析節目表界面佈局 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
callBack.onSuccess("界面佈局信息")
}
}
/**
* 3.根據佈局信息先繪製出界面框架,界面繪製,運行主線程
*/
fun drawLayout(layoutInfo : String, callBack : CallBack) {
mainHandler.post(Runnable {
println("繪製ui界面佈局 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
callBack.onSuccess("佈局繪製完成")
})
}
/**
* 4.接着解析播放列表中的播放素材列表,解析協議,運行後臺
*/
fun parsePlayList(filePath : String, callBack : CallBack) {
thread {
println("繼續解析節目單播放的素材內容 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
callBack.onSuccess("播放素材列表")
}
}
/**
* 5.界面上播放多媒體素材,運行主線程
*/
fun startPlay(playList : String, callBack : CallBack) {
mainHandler.post(Runnable {
println("播放多媒體素材 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
callBack.onSuccess("播放成功")
})
}
/**
* 6.反饋平臺播放結果,網絡訪問,運行後臺
*/
fun notifyResult() {
thread {
println("反饋平臺播放結果 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
}
}
/**
* android原生方式, 回調的方法一多,回調層次多,更加眼花繚亂
*/
fun android() {
download("http://....", object : CallBack {
override fun onError(errorCode: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onSuccess(filePath: String) {
parseLayout(filePath, object : CallBack {
override fun onError(errorCode: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onSuccess(layoutInfo: String) {
drawLayout(layoutInfo, object : CallBack {
override fun onError(errorCode: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onSuccess(filePath: String) {
parsePlayList(filePath, object : CallBack {
override fun onError(errorCode: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onSuccess(playList: String) {
startPlay(playList, object : CallBack {
override fun onError(errorCode: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onSuccess(response: String) {
notifyResult()
}
})
}
})
}
})
}
})
}
})
}
複製代碼
rxjava支持統一的異常處理,已經能知足大部分需求,可是相比kotlin仍是存在不足。android
/**
* 1.根據url地址下載播放列表, 網絡訪問,運行後臺
*/
fun _download(url : String) : String {
println("根據url下載播放節目表 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
return "節目表"
}
/**
* 2.先解析下載好播放列表文件中佈局相關信息,協議解析,運行後臺
*/
fun _parseLayout(filePath : String) : String {
println("先解析節目表界面佈局 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
return "界面佈局信息"
}
/**
* 3.根據佈局信息先繪製出界面框架,界面繪製,運行主線程
*/
fun _drawLayout(layoutInfo : String) : String {
println("繪製ui界面佈局 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
return "佈局繪製完成"
}
/**
* 4.接着解析播放列表中的播放素材列表,解析協議,運行後臺
*/
fun _parsePlayList(filePath : String) : String {
println("繼續解析節目單播放的素材內容 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
return "播放素材列表"
}
/**
* 5.界面上播放多媒體素材,運行主線程
*/
fun _startPlay(playList : String) : String {
println("播放多媒體素材 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
return "播放成功"
}
/**
* 6.反饋平臺播放結果,網絡訪問,運行後臺
*/
fun _notifyResult() {
println("反饋平臺播放結果 thread.name = ${Thread.currentThread().name} , id = ${Thread.currentThread().id}")
}
//經過lambda表達式優化下
fun rxjavaLambda() {
Observable.just("http://......")
//後臺線程
.map { url -> _download(url) }
//後臺線程
.map { filePath -> _parseLayout(filePath) }
.observeOn(AndroidSchedulers.mainThread())
//UI線程
.map { layoutInfo -> _drawLayout(layoutInfo) }
.observeOn(Schedulers.newThread())
//後臺線程
.map { filePath -> _parsePlayList(filePath) }
.observeOn(AndroidSchedulers.mainThread())
//UI線程
.map { playList -> _startPlay(playList) }
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
//後臺線程
.subscribe({isSuccess -> _notifyResult()},
{ throwable -> fun(){}})//統一的異常處理
}
複製代碼
協程的方式不只能夠統一處理, 而且能夠有選擇的忽略某些步驟中拋出的異常,以避免影響繼續往下執行。bash
fun coroutines() {
//async默認最後一行是返回值,因此下面的return@async均可以去掉
runBlocking {
try {
//後臺線程
var filePath = async(Dispatchers.Default) { _download("http://...")}.await()
//後臺線程
val layoutInfo = async(Dispatchers.IO) { _parseLayout(filePath) }.await()
//這邊是與上邊rxjava方案相比最大的不一樣,能夠實現_drawLayout與_parsePlayList同步進行,效率更高
//UI線程
launch(Dispatchers.Main) { _drawLayout(layoutInfo) }
//後臺線程
val playList = async(Dispatchers.IO) { _parsePlayList(filePath) }.await()
//UI線程
val isSuccess = async(Dispatchers.Main) { _startPlay(playList) }.await()
//後臺線程
launch(Dispatchers.Main) { _notifyResult() }
} catch (exception : Exception) {
//統一處理異常
}
}
}
複製代碼