# 项目通用模块使用文档

## 1. 在 application 中注册

在主 module 的 application 中
```kotlin
override fun onCreate() {
    super.onCreate()
    YdlCommonApp.initApp(this)
}
```

<br/><br/>

## 2. Base 基类的使用

### 2.1 BaseActivity
>所有的 Activity 都继承自 BaseActivity

#### 2.1.1 设置布局文件
重写 layoutResId 方法来设置布局文件

```kotlin
override fun layoutResId(): Int {
    return R.layout.activity_fragment
}
```
<br/>

#### 2.1.2 初始化
重写 initDataAndEvent 进行初始化操作
```kotlin
override fun initDataAndEvent() {
    //...
}
```
<br/>

#### 2.1.3 Android 6.0 以上运行时权限
使用 requestPermissions 方法请求请求权限,两个参数分别标识请求码和需要请求的权限,若同意请求权限,在 grantedPermission 方法中回调,否则在
deniedPermission 方法中回调,参数与请求时的请求码相对应
```kotlin
override fun initDataAndEvent() {
    camera.setOnClickListener {
        requestPermissions(PERMISSION_CAMERA, Manifest.permission.CAMERA)
    }
}

override fun grantedPermission(requestCode: Int) {
    if (requestCode == PERMISSION_CAMERA) {
        RemindHelper.show("同意了相机权限")
    }
}

override fun deniedPermission(requestCode: Int) {
    if (requestCode == PERMISSION_CAMERA) {
        RemindHelper.show("拒绝了相机权限")
    }
}
```
<br/>

### 2.2 BaseFragment
>所有的 Fragment 都继承自 BaseFragment

#### 2.1.1 设置布局文件
同 BaseActivity
<br/>

#### 2.1.2 初始化和懒加载
如果需要懒加载,重写 initDataAndEventLazy 进行初始化操作,否则,重写 initDataAndEvent 进行初始化操作
```kotlin
override fun initDataAndEvent() {
    //...
}

override fun initDataAndEventLazy() {
    //...
}
```
<br/>

#### 2.1.3 Android 6.0 以上运行时权限
同 BaseActivity
<br/>

### 2.3 只包含一个 Fragment 的 Activity
如果需要使用 Fragment 代替 Activity,可以使用只包含一个 Fragment 的 Activity,继承 SingleFragmentActivity,
重写 createFragment 方法来创建初始 Fragment
```kotlin
override fun createFragment(): Fragment {
    return MainFragment()
}
```

可以调用 replace 方法来切换 Fragment,达到跳转的效果,如果需要在 Fragment 中直接跳转,可以给
Fragment 设置 Callback 接口,然后调用 SingleFragmentActivity 的 replace 方法
```kotlin
override fun createFragment(): Fragment {
    return MainFragment().setCallback(object : BaseFragment.Callback {
        override fun replace(fragment: Fragment) {
            this@MainActivity.replace(fragment)
        }
    })
}
```

在 Fragment 中需要跳转的时候直接调用 callback 的 replace 方法即可
```kotlin
override fun initDataAndEvent() {
    premission.setOnClickListener { callback?.replace(PermissionFragment()) }
}
```

<br/><br/>

## 3. 弹出消息提示
直接调用 RemindHelp 的 show 方法即可弹出消息提示
```kotlin
RemindHelper.show("...")
RemindHelper.show(R.string.app_name)
```
这是两个重载方法,CharSequence 类型的参数和
Int 类型的参数分别表示消息的字符串和 string 资源文件

<br/><br/>

## 4. mvp 的使用
定义一个 Contract 接口,在其内部分别定义 View,Model,Presenter 的接口,并在各自的接口中
定义需要使用的方法(如需要异步获取数据,建议 Model 中的方法返回 Observable,可避免使用接口回调)
```kotlin
interface TestContract {
    interface View: MVPView {
        fun updateUI(data: String)
    }

    interface Model: MVPModel {
        fun getData(): Observable<String>
    }

    interface Presenter: MVPPresenter<View, Model> {
        fun requestData()
    }
}
```

定义三个类分别实现上述三个接口

>Presenter 的实现类必须继承自 BasePresenter,
如果使用 RxJava,必须继承自 RxPresenter,
泛型类型就是上述定义的接口中的 View 和 Model,
BasePresenter 和 RxPresenter 中的构造方法需要的参数也从构造方法传入,
重写 createModel 方法,返回上述接口中 Model 的实现类,
如果有延时操作,需要重写 onViewDestroy 方法,并将其取消,防止内存泄露,
如使用 RxPresenter,可以通过调用 addDisposable 方法把 RxJava 的相关操作放入 Disposable 集合中,
再在 onViewDestroy 方法中取消其他的延时操作

```kotlin
class TestPresenter(view: TestContract.View): RxPresenter<TestContract.View, TestContract.Model>(view), TestContract.Presenter {
    override fun createModel(): TestContract.Model {
        return TestModel()
    }

    override fun requestData() {
        val d = model.getData().subscribe { view.updateUI(it) }
        addDisposable(d)
    }

    override fun onViewDestroy() {
        super.onViewDestroy()
        //取消其他延时操作
    }
}
```
<br/>

>View 的实现类一定是 Activity 或 Fragment,并且必须继承 MVPActivity 或 MVPFragment,泛型类型是上述接口中的 Presenter,
重写 createPresenter 方法,返回上述接口中 Presenter 的实现类,构造方法的参数传入 this
```kotlin
class TestFragment: MVPFragment<TestContract.Presenter>(), TestContract.View {
    override fun updateUI(data: String) {
        text.text = data
    }

    override fun createPresenter(): TestContract.Presenter {
        return TestPresenter(this)
    }

    override fun layoutResId(): Int {
        return R.layout.fragment_mvp
    }

    override fun initDataAndEvent() {
        button.setOnClickListener { mPresenter.requestData() }
    }

    override fun initDataAndEventLazy() {}
}
```
<br/>

>Model 的实现类直接实现上述 Model 接口,重写方法即可
```kotlin
class TestModel : TestContract.Model {
    override fun getData(): Observable<String> {
        return Observable.just("my data")
                .subscribeOn(Schedulers.io())
                .doOnNext { Thread.sleep(2000) }
                .observeOn(AndroidSchedulers.mainThread())
    }
}
```