一、工具
- 网络层retrofit+rxjava
- 使用mvp
- 使用databing进行组件注入
二、结构
1、网络层
实例化 Retrofit 使用 companion object ,因为kotlin没有静态类,使用这种方式创造一个单例
class ApiClient {
/.../
companion object {
fun retrofit() : Retrofit {
return ApiClient().retrofit()
}
}
fun retrofit() : Retrofit {
val builder = OkHttpClient.Builder() builder.connectTimeout(S_DEFAULT_TIMEOUT, TimeUnit.SECONDS).writeTimeout(S_DEFAULT_TIMEOUT, TimeUnit.SECONDS).readTimeout(S_DEFAULT_TIMEOUT, TimeUnit.SECONDS)
if (BuildConfig.DEBUG) {
// Log信息拦截器
val loggingInterceptor = HttpLoggingInterceptor() loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
//设置 Debug Log 模式
builder.addInterceptor(loggingInterceptor)
}
val okHttpClient = builder.build()
return Retrofit.Builder().baseUrl(getHost()).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).client(okHttpClient).build()
}
/**
* 根据当前配置设置host地址
*
* @return host 地址
*/
fun getHost() : String {
if (FORCEUSE_TEST_HOST) {
return HS_HOST_TEST
} else {
if (BuildConfig.DEBUG) {
return HS_HOST_TEST
} else {
return HS_HOST
}
}
}
}
统一一个网络请求返回数据的接口,这里遇到了问题,但我使用一个kt文件的activity时,这里对model.data进行判空(== 、 !!) ,无论怎么样,model.data 都被判断成空的,但用一个普通的activity却可以
abstract class ApiCallback < T > {
abstract fun onFailure(errorCode: Int) abstract fun onSuccess(model: T)
fun onFinish() {}
fun onNext(model: HttpBase < T > ?) {
if (model == null) {
onFailure(Error.S_ERROR_DATA) return
}
if (model.errorCode == 0) {
try {
onSuccess(model.data as T)
} catch(e: Exception) {
onFailure(Error.S_ERROR_DATA)
}
} else {
onFailure(Error.S_ERROR_DATA)
}
}
fun onError(e: Throwable) {
e.printStackTrace() if (e is HttpException) {
val code = e.code() LogUtils.i("network -> onError: " + code) onFailure(code)
} else {
onFailure(Error.S_UNKNOW_ERROR)
}
}
fun onComplete() {
onFinish()
}
}
这个接口的返回值是HttpBase<User>,在HttpBase中做了请求错误码统一的判断,方便处理
@FormUrlEncoded
@POST("user/login.json")
fun login(@FieldMap params: Map<String, String>): Flowable<HttpBase<User>>
这里抛出一个异常就要写注解了 @Throws(Exception::class)
class HttpBase <T> {
var errorCode: Int = 0
var data: T ? =null
}
2、Presenter
open class BasePresenter<V>(var mvpView: V) {
private val TAG = BasePresenter::class.java.simpleName
var apiStores = ApiClient.retrofit().create(ApiStores::class.java)
var mCompositeDisposable: CompositeDisposable = CompositeDisposable()
fun detachView() {
onUnsubscribe()
}
fun <T> addSubscription(flowable: Flowable<HttpBase<T>>, apiCallback: ApiCallback<T>) {
mCompositeDisposable.add(flowable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Consumer<HttpBase<T>> {
@Throws(Exception::class)
override fun accept(t: HttpBase<T>?) {
apiCallback.onNext(t)
}
}, object : Consumer<Throwable> {
@Throws(Exception::class)
override fun accept(t: Throwable) {
LogUtils.d(t)
apiCallback.onError(t)
}
}, object : Action {
@Throws(Exception::class)
override fun run() {
apiCallback.onComplete()
}
}))
}
fun addSubscription(disposable: Disposable) {
mCompositeDisposable.add(disposable)
}
fun onUnsubscribe() {
mCompositeDisposable.clear()
}
}
3、Fragment/Activity
open class BaseFragment : Fragment() {
private val TAG = BaseFragment::class.java.simpleName
protected var apiStores = ApiClient.retrofit().create(ApiStores::class.java)
private var mCompositeDisposable: CompositeDisposable = CompositeDisposable()
override fun onDestroy() {
onUnsubscribe()
super.onDestroy()
}
fun <T> addSubscription(flowable: Flowable<HttpBase<T>>, apiCallback: ApiCallback<T>) {
mCompositeDisposable.add(flowable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Consumer<HttpBase<T>> {
@Throws(Exception::class)
override fun accept(t: HttpBase<T>?) {
apiCallback.onNext(t)
}
}, object : Consumer<Throwable> {
@Throws(Exception::class)
override fun accept(t: Throwable) {
apiCallback.onError(t)
}
}, object : Action {
@Throws(Exception::class)
override fun run() {
apiCallback.onComplete()
}
}))
}
fun addSubscription(disposable: Disposable) {
mCompositeDisposable.add(disposable)
}
fun onUnsubscribe() {
mCompositeDisposable.clear()
}
}
open class BaseActivity : Activity() {
private val TAG = BaseActivity::class.java.simpleName
protected var apiStores = ApiClient.retrofit().create(ApiStores::class.java)
private var mCompositeDisposable: CompositeDisposable = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onDestroy() {
onUnsubscribe()
super.onDestroy()
}
fun <T> addSubscription(flowable: Flowable<HttpBase<T>>, apiCallback: ApiCallback<T>) {
mCompositeDisposable.add(flowable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Consumer<HttpBase<T>> {
@Throws(Exception::class)
override fun accept(t: HttpBase<T>?) {
apiCallback.onNext(t)
}
}, object : Consumer<Throwable> {
@Throws(Exception::class)
override fun accept(t: Throwable) {
apiCallback.onError(t)
}
}, object : Action {
@Throws(Exception::class)
override fun run() {
apiCallback.onComplete()
}
}))
}
fun addSubscription(disposable: Disposable) {
mCompositeDisposable.add(disposable)
}
fun onUnsubscribe() {
mCompositeDisposable.clear()
}
}
三、问题
在kt的activcity中,导入databinding时显示异常, 查了一些资料,但是没什么结果,好在kt提供自己的view注入。但是在普通的activity中却无法使用
class MainActivity : MvpActivity<MainPresenter>(), MainView {
override fun createPresenter(): MainPresenter {
return MainPresenter(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mvpPresenter.getName()
}
override fun setTextView(name: String) {
LogUtils.d("name : " + name)
text.setText(name)
}
override fun error(error: Int) {
LogUtils.d(error)
}
}