Android数据缓存框架 - 开始编写BaseDatabaseCacheRepository数据库缓存

之前我们已经完成了BaseRepository的编写,实现了数据仓库的顶层设计,下面我们完成一些具体一点的功能。

```
package dora.cache.repository

import android.content.Context
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import dora.cache.data.fetcher.DataFetcher
import dora.cache.data.fetcher.IDataFetcher
import dora.cache.data.fetcher.IListDataFetcher
import dora.cache.data.fetcher.ListDataFetcher
import dora.cache.data.page.DataPager
import dora.cache.data.page.IDataPager
import dora.db.builder.Condition
import dora.db.builder.QueryBuilder
import dora.db.builder.WhereBuilder
import dora.http.DoraCallback
import dora.http.DoraListCallback
import dora.rx.RxTransformer
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import java.lang.IllegalArgumentException

/**
 * 使用内置SQLite数据库进行缓存的仓库。
 */
abstract class BaseDatabaseCacheRepository<M> @JvmOverloads
    constructor(context: Context) : BaseRepository<M>(context) {

    protected val dataMap = HashMap<String, M>()
    protected val listDataMap = HashMap<String, MutableList<M>>()

    /**
     * 如果返回true,则放弃强制覆盖原有数据的模式,而采用map映射,注意这种方式在程序退出后会丢失map缓存的数据。
     */
    protected open fun disallowForceUpdate() : Boolean {
        return false
    }

    /**
     * 只要mapKey的值不冲突即可追加缓存,读取的时候则通过mapKey取不同条件(如接口的参数不同,请求的时间戳不同等)
     * 接口返回的数据的缓存。
     */
    protected open fun mapKey() : String {
        // 通过时间戳保证打开disallowForceUpdate后每次接口返回的数据都被缓存到map,而不是livedata
        return System.currentTimeMillis().toString()
    }

    /**
     * 根据查询条件进行初步的过滤从数据库加载的数据,过滤不完全则再调用onInterceptData。通常在断网情况下,指定
     * 离线数据的过滤条件。
     *
     * @return
     */
    @Deprecated(message = "Use query() instead.",
            replaceWith = ReplaceWith("query"),
            level = DeprecationLevel.ERROR)
    protected open fun where(): Condition {
        return WhereBuilder.create().toCondition()
    }

    protected open fun query(): Condition {
        return QueryBuilder.create().toCondition()
    }

    override fun selectData(ds: DataSource): Boolean {
        val isLoaded = ds.loadFromCache(DataSource.CacheType.DATABASE)
        return if (isNetworkAvailable) {
            try {
                ds.loadFromNetwork()
                true
            } catch (e: Exception) {
                Log.e(TAG, e.toString())
                isLoaded
            }
        } else isLoaded
    }

    override fun createDataFetcher(): DataFetcher<M> {
        return object : DataFetcher<M>() {
            override fun fetchData(listener: IDataFetcher.OnLoadListener?): LiveData<M?> {
                selectData(object : DataSource {
                    override fun loadFromCache(type: DataSource.CacheType): Boolean {
                        if (type === DataSource.CacheType.DATABASE) {
                            return onLoadFromCache(liveData)
                        }
                        liveData.postValue(null)
                        return false
                    }

                    override fun loadFromNetwork() {
                        rxOnLoadFromNetwork(listener, liveData)
                        onLoadFromNetwork(callback(listener))
                    }
                })
                return liveData
            }

            override fun callback(listener: IDataFetcher.OnLoadListener?): DoraCallback<M> {
                return object : DoraCallback<M>() {
                    override fun onSuccess(model: M) {
                        parseModel(model, listener, liveData)
                    }

                    override fun onFailure(msg: String) {
                        onParseModelFailure(msg, listener)
                    }
                }
            }

            override fun clearData() {
                liveData.postValue(null)
            }
        }
    }

    override fun createListDataFetcher(): ListDataFetcher<M> {
        return object : ListDataFetcher<M>() {

            override fun fetchListData(listener: IListDataFetcher.OnLoadListener?): LiveData<MutableList<M>> {
                selectData(object : DataSource {
                    override fun loadFromCache(type: DataSource.CacheType): Boolean {
                        if (type === DataSource.CacheType.DATABASE) {
                            return onLoadFromCacheList(liveData)
                        }
                        liveData.postValue(arrayListOf())
                        return false
                    }

                    override fun loadFromNetwork() {
                        rxOnLoadFromNetwork(listener, liveData)
                        onLoadFromNetwork(listCallback(listener))
                    }
                })
                return liveData
            }

            override fun listCallback(listener: IListDataFetcher.OnLoadListener?): DoraListCallback<M> {
                return object : DoraListCallback<M>() {
                    override fun onSuccess(models: MutableList<M>) {
                        parseModels(models, listener, liveData)
                    }

                    override fun onFailure(msg: String) {
                        onParseModelsFailure(msg, listener)
                    }
                }
            }

            override fun obtainPager(): IDataPager<M> {
                return DataPager(liveData.value ?: arrayListOf())
            }

            override fun clearListData() {
                liveData.postValue(arrayListOf())
            }
        }
    }

    private fun onLoadFromCache(liveData: MutableLiveData<M?>) : Boolean {
        if (checkValuesNotNull()) {
            val model = cacheHolder.queryCache(query())
            model?.let {
                onInterceptData(DataSource.Type.CACHE, it)
                liveData.postValue(it)
                return true
            }
        } else throw IllegalArgumentException("Query parameter would be null, checkValuesNotNull return false.")
        return false
    }

    private fun onLoadFromCacheList(liveData: MutableLiveData<MutableList<M>>) : Boolean {
        if (checkValuesNotNull()) {
            val models = listCacheHolder.queryCache(query())
            models?.let {
                onInterceptData(DataSource.Type.CACHE, it)
                liveData.postValue(it)
                return true
            }
        } else throw IllegalArgumentException("Query parameter would be null, checkValuesNotNull return false.")
        return false
    }

    /**
     * 非集合数据模式需要重写它,callback和observable二选一。
     */
    override fun onLoadFromNetwork(callback: DoraCallback<M>) {
    }

    /**
     * 集合数据模式需要重写它,callback和observable二选一。
     */
    override fun onLoadFromNetwork(callback: DoraListCallback<M>) {
    }

    /**
     * 非集合数据模式需要重写它,callback和observable二选一。
     */
    override fun onLoadFromNetworkObservable() : Observable<M> {
        return Observable.empty()
    }

    /**
     * 集合数据模式需要重写它,callback和observable二选一。
     */
    override fun onLoadFromNetworkObservableList() : Observable<MutableList<M>> {
        return Observable.empty()
    }

    @JvmOverloads
    private fun rxOnLoadFromNetwork(listener: IDataFetcher.OnLoadListener?, liveData: MutableLiveData<M?>) {
        RxTransformer.doApi(onLoadFromNetworkObservable(), object : Observer<M> {
            override fun onSubscribe(d: Disposable?) {
            }

            override fun onNext(model: M) {
                parseModel(model, listener, liveData)
            }

            override fun onError(e: Throwable?) {
                onParseModelFailure(e.toString(), listener)
            }

            override fun onComplete() {
            }
        })
    }

    @JvmOverloads
    private fun rxOnLoadFromNetwork(listener: IListDataFetcher.OnLoadListener?, liveData: MutableLiveData<MutableList<M>>) {
        RxTransformer.doApi(onLoadFromNetworkObservableList(), object : Observer<MutableList<M>> {
            override fun onSubscribe(d: Disposable?) {
            }

            override fun onNext(models: MutableList<M>?) {
                parseModels(models, listener, liveData)
            }

            override fun onError(e: Throwable?) {
                onParseModelsFailure(e.toString(), listener)
            }

            override fun onComplete() {
            }
        })
    }

    @JvmOverloads
    protected open fun parseModel(model: M, listener: IDataFetcher.OnLoadListener?, liveData: MutableLiveData<M?>) {
        model?.let {
            if (isLogPrint) {
                Log.d(TAG, it.toString())
            }
            onInterceptData(DataSource.Type.NETWORK, it)
            if (!disallowForceUpdate()) {
                if (checkValuesNotNull()) {
                    cacheHolder.removeOldCache(query())
                } else throw IllegalArgumentException("Query parameter would be null, checkValuesNotNull return false.")
            } else {
                if (dataMap.containsKey(mapKey())) {
                    if (checkValuesNotNull()) {
                        cacheHolder.removeOldCache(query())
                    } else throw IllegalArgumentException("Query parameter would be null, checkValuesNotNull return false.")
                } else {
                    dataMap[mapKey()] = it
                }
            }
            cacheHolder.addNewCache(it)
            if (disallowForceUpdate()) {
                liveData.postValue(dataMap[mapKey()])
            } else {
                liveData.postValue(it)
            }
        }
        listener?.onSuccess()
    }

    @JvmOverloads
    protected open fun parseModels(models: MutableList<M>?, listener: IListDataFetcher.OnLoadListener?,
                            liveData: MutableLiveData<MutableList<M>>) {
        models?.let {
            if (isLogPrint) {
                for (model in it) {
                    Log.d(TAG, model.toString())
                }
            }
            onInterceptData(DataSource.Type.NETWORK, it)
            if (!disallowForceUpdate()) {
                if (checkValuesNotNull()) {
                    listCacheHolder.removeOldCache(query())
                } else throw IllegalArgumentException("Query parameter would be null, checkValuesNotNull return false.")
            } else {
                if (listDataMap.containsKey(mapKey())) {
                    if (checkValuesNotNull()) {
                        listCacheHolder.removeOldCache(query())
                    } else throw IllegalArgumentException("Query parameter would be null, checkValuesNotNull return false.")
                } else {
                    listDataMap[mapKey()] = it
                }
            }
            listCacheHolder.addNewCache(it)
            if (disallowForceUpdate()) {
                liveData.postValue(listDataMap[mapKey()])
            } else {
                liveData.postValue(it)
            }
        }
        listener?.onSuccess()
    }

    @JvmOverloads
    protected open fun onParseModelFailure(msg: String, listener: IDataFetcher.OnLoadListener?) {
        if (isLogPrint) {
            Log.d(TAG, msg)
        }
        if (isClearDataOnNetworkError) {
            if (checkValuesNotNull()) {
                clearData()
                cacheHolder.removeOldCache(query())
            } else throw IllegalArgumentException("Query parameter would be null, checkValuesNotNull return false.")
        }
        listener?.onFailure(msg)
    }

    @JvmOverloads
    protected open fun onParseModelsFailure(msg: String, listener: IListDataFetcher.OnLoadListener?) {
        if (isLogPrint) {
            Log.d(TAG, msg)
        }
        if (isClearDataOnNetworkError) {
            if (checkValuesNotNull()) {
                clearListData()
                listCacheHolder.removeOldCache(query())
            } else throw IllegalArgumentException("Query parameter would be null, checkValuesNotNull return false.")
        }
        listener?.onFailure(msg)
    }
}
```

我们先来看看selectData方法,这个方法是一个决定数据来源优先级的关键方法。通常我们主要有两种实现。第一种,无论有无网,先加载缓存数据,然后加载网络数据,使用网络数据覆盖掉本地缓存数据的占位。第二种,如果有网则加载网络数据,没网则加载缓存数据。在业务层调用fetchData或fetchListData,途经selectData,则会调用onLoadFromNetwork这一类的方法。我们在这里重写它来实现Retrofit的接口调用。这样,数据就传给了框架。然后会调用parseModel方法,在这里框架将解析model,然后将数据设置到Repository内置的livedata中,实现内存缓存。最后框架会将livedata返回给fetchData或fetchListData,使用者就可以通过监听这个livedata的变化来改变UI了。有一点需要注意,rxOnLoadFromNetwork和onLoadFromNetwork虽然在loadFromNetwork中都会调用,但Retrofit接口的返回值类型要么是Call,要么是Observable,所以你只需要实现一个就行了,切忌都实现。

另外一个重点就是query方法,这个方法在数据加载过程被调用,即从缓存中读取数据,通过指定一定的条件,我们从数据库中过滤需要的数据,这个过滤条件通常和onLoadFromNetwork中Retrofit请求的参数保持一致。查询条件通过QueryBuilder或WhereBuilder构建,我们最终需要的是一个Condition,前面的文章我们讲过了Condition类这个协议,我们重点来看一下QueryBuilder和WhereBuilder怎么实现。

```
package dora.db.builder

/**
 * 查询条件构建者。
 *
 * @see WhereBuilder
 */
class QueryBuilder private constructor() {

    var columns: Array<String>? = null
    private var group: String? = null
    private var having: String? = null
    private var order: String? = null
    private var limit: String? = null
    private var whereBuilder: WhereBuilder

    /**
     * 指定where子句。
     */
    fun where(builder: WhereBuilder): QueryBuilder {
        whereBuilder = builder
        return this
    }

    /**
     * 指定where子句。
     */
    fun where(condition: Condition): QueryBuilder {
        whereBuilder = WhereBuilder.create()
        whereBuilder.where(condition)
        return this
    }

    /**
     * 指定要查询的列。
     */
    fun column(columns: Array<String>): QueryBuilder {
        this.columns = columns
        return this
    }

    /**
     * 指定having子句。
     */
    fun having(having: String): QueryBuilder {
        this.having = HAVING + having
        return this
    }

    /**
     * 指定order by。
     */
    fun orderBy(order: String): QueryBuilder {
        this.order = ORDER_BY + order
        return this
    }

    /**
     * 指定group by。
     */
    fun groupBy(group: String): QueryBuilder {
        this.group = GROUP_BY + group
        return this
    }

    /**
     * 指定limit。
     */
    fun limit(limit: Int): QueryBuilder {
        this.limit = LIMIT + limit
        return this
    }

    /**
     * 指定limit,数据索引从start到end位置。
     */
    fun limit(start: Int, end: Int): QueryBuilder {
        limit = LIMIT + start + COMMA + end
        return this
    }

    /**
     * 构建query的sql语句。
     */
    fun build(): String {
        return (whereBuilder.build() + (if (group != null) group else SPACE) + (if (having != null) having else SPACE)
                + (if (order != null) order else SPACE) + if (limit != null) limit else SPACE)
    }

    fun getWhereBuilder(): WhereBuilder {
        return whereBuilder
    }

    fun getHaving(): String {
        return if (having != null) StringBuilder(having).delete(0, HAVING.length).toString() else SPACE
    }

    fun getOrder(): String {
        return if (order != null) StringBuilder(order).delete(0, ORDER_BY.length).toString() else SPACE
    }

    fun getGroup(): String {
        return if (group != null) StringBuilder(group).delete(0, GROUP_BY.length).toString() else SPACE
    }

    fun getLimit(): String {
        return if (limit != null) StringBuilder(limit).delete(0, LIMIT.length).toString() else SPACE
    }

    /**
     * 转化为Condition。
     */
    fun toCondition(): Condition {
        return Condition(whereBuilder.selection, whereBuilder.selectionArgs ?: arrayOf(),
                limit, order, group, having)
    }

    companion object {

        private const val GROUP_BY = " GROUP BY "
        private const val HAVING = " HAVING "
        private const val ORDER_BY = " ORDER BY "
        private const val LIMIT = " LIMIT "
        private const val COMMA = ","
        private const val SPACE = ""

        fun create(): QueryBuilder {
            return QueryBuilder()
        }
    }

    init {
        whereBuilder = WhereBuilder.create()
    }
}
```

然后是WhereBuilder。

```
package dora.db.builder

/**
 * 查询条件where部分的构建者,即为简单查询条件,和QueryBuilder类似,最终都是得到Condition。
 *
 * @see QueryBuilder
 */
class WhereBuilder {

    var selection: String = ""
        private set
    var selectionArgs: Array<String?>? = null

    private constructor()

    private constructor(condition: Condition) {
        selection = condition.selection
        selectionArgs = condition.selectionArgs
    }

    private constructor(whereClause: String, whereArgs: Array<String?>?) {
        this.selection = whereClause
        this.selectionArgs = whereArgs
    }

    /**
     * 添加sql语句片段,and语句。
     */
    fun and(): WhereBuilder {
        if (selection != null) {
            selection += AND
        }
        return this
    }

    /**
     * 添加sql语句片段,or语句。
     */
    fun or(): WhereBuilder {
        if (selection != null) {
            selection += OR
        }
        return this
    }

    /**
     * 添加sql语句片段,not语句。
     */
    fun not(): WhereBuilder {
        if (selection != null) {
            selection += NOT
        } else {
            selection = NOT
        }
        return this
    }

    /**
     * 添加sql语句片段,and语句。
     */
    fun and(whereClause: String, vararg whereArgs: Any): WhereBuilder {
        return append(AND, whereClause, arrayOf(whereArgs))
    }

    /**
     * 添加sql语句片段,or语句。
     */
    fun or(whereClause: String, vararg whereArgs: Any): WhereBuilder {
        return append(OR, whereClause, arrayOf(whereArgs))
    }

    /**
     * 添加sql语句片段,not语句。
     */
    fun not(whereClause: String, vararg whereArgs: Any): WhereBuilder {
        return not().parenthesesLeft().append(null, whereClause, arrayOf(whereArgs)).parenthesesRight()
    }

    /**
     * 添加sql语句片段,and not语句。
     */
    fun andNot(whereClause: String, whereArgs: Array<Any>): WhereBuilder {
        return and(not(whereClause, whereArgs))
    }

    /**
     * 添加sql语句片段,or not语句。
     */
    fun orNot(whereClause: String, whereArgs: Array<Any>): WhereBuilder {
        return or(not(whereClause, whereArgs))
    }

    /**
     * 添加sql语句片段,and语句。
     */
    fun and(builder: WhereBuilder): WhereBuilder {
        val selection = builder.selection
        val selectionArgs = builder.selectionArgs
        return and(selection, selectionArgs!!)
    }

    /**
     * 添加sql语句片段,or语句。
     */
    fun or(builder: WhereBuilder): WhereBuilder {
        val selection = builder.selection
        val selectionArgs = builder.selectionArgs
        return or(selection, selectionArgs!!)
    }

    /**
     * 添加sql语句片段,not语句。
     */
    fun not(builder: WhereBuilder): WhereBuilder {
        val selection = builder.selection
        val selectionArgs = builder.selectionArgs
        return not(selection, selectionArgs!!)
    }

    /**
     * 添加sql语句片段,and not语句。
     */
    fun andNot(builder: WhereBuilder): WhereBuilder {
        return and(not(builder))
    }

    /**
     * 添加sql语句片段,or not语句。
     */
    fun orNot(builder: WhereBuilder): WhereBuilder {
        return or(not(builder))
    }

    /**
     * 添加sql语句片段,左括号"("。
     */
    fun parenthesesLeft(): WhereBuilder {
        if (selection != null) {
            selection += PARENTHESES_LEFT
        } else {
            selection = PARENTHESES_LEFT
        }
        return this
    }

    /**
     * 添加sql语句片段,右括号")"。
     */
    fun parenthesesRight(): WhereBuilder {
        if (selection != null) {
            selection += PARENTHESES_RIGHT
        }
        return this
    }

    /**
     * 添加sql语句片段,如a = 0。
     */
    fun addWhereEqualTo(column: String, value: Any): WhereBuilder {
        return append(null, column + EQUAL_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如a != 0。
     */
    fun addWhereNotEqualTo(column: String, value: Any): WhereBuilder {
        return append(null, column + NOT_EQUAL_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如a > 0。
     */
    fun addWhereGreaterThan(column: String, value: Number): WhereBuilder {
        return append(null, column + GREATER_THAN_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如a >= 0。
     */
    fun addWhereGreaterThanOrEqualTo(column: String, value: Number): WhereBuilder {
        return append(null, column + GREATER_THAN_OR_EQUAL_TO_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如a < 10。
     */
    fun addWhereLessThan(column: String, value: Number): WhereBuilder {
        return append(null, column + LESS_THAN_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如a <= 10。
     */
    fun addWhereLessThanOrEqualTo(column: String, value: Number): WhereBuilder {
        return append(null, column + LESS_THAN_OR_EQUAL_TO_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如a in(?,?,...)。
     */
    fun addWhereIn(column: String, values: Array<Any>): WhereBuilder {
        return appendWhereIn(null, column, values)
    }

    /**
     * 添加sql语句片段,如and a = 0。
     */
    fun andWhereEqualTo(column: String, value: Any): WhereBuilder {
        return append(AND, column + EQUAL_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如and a != 0。
     */
    fun andWhereNotEqualTo(column: String, value: Any): WhereBuilder {
        return append(AND, column + NOT_EQUAL_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如and a > 0。
     */
    fun andWhereGreaterThan(column: String, value: Number): WhereBuilder {
        return append(AND, column + GREATER_THAN_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如and a >= 0。
     */
    fun andWhereGreaterThanOrEqualTo(column: String, value: Number): WhereBuilder {
        return append(AND, column + GREATER_THAN_OR_EQUAL_TO_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如and a < 10。
     */
    fun andWhereLessThan(column: String, value: Number): WhereBuilder {
        return append(AND, column + LESS_THAN_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如and a <= 10。
     */
    fun andWhereLessThanOrEqualTo(column: String, value: Number): WhereBuilder {
        return append(AND, column + LESS_THAN_OR_EQUAL_TO_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如and a in(?,?,...)。
     */
    fun andWhereIn(column: String, values: Array<Any>): WhereBuilder {
        return appendWhereIn(AND, column, values)
    }

    /**
     * 添加sql语句片段,如or a = 0。
     */
    fun orWhereEqualTo(column: String, value: Any): WhereBuilder {
        return append(OR, column + EQUAL_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如or a != 0。
     */
    fun orWhereNotEqualTo(column: String, value: Any): WhereBuilder {
        return append(OR, column + NOT_EQUAL_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如or a > 0。
     */
    fun orWhereGreaterThan(column: String, value: Number): WhereBuilder {
        return append(OR, column + GREATER_THAN_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如or a >= 0。
     */
    fun orWhereGreaterThanOrEqualTo(column: String, value: Number): WhereBuilder {
        return append(OR, column + GREATER_THAN_OR_EQUAL_TO_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如or a < 10。
     */
    fun orWhereLessThan(column: String, value: Number): WhereBuilder {
        return append(OR, column + LESS_THAN_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如or a <= 10。
     */
    fun orWhereLessThanOrEqualTo(column: String, value: Number): WhereBuilder {
        return append(OR, column + LESS_THAN_OR_EQUAL_TO_HOLDER, arrayOf(value))
    }

    /**
     * 添加sql语句片段,如or a in(?,?,...)。
     */
    fun orWhereIn(column: String, values: Array<Any>): WhereBuilder {
        return appendWhereIn(OR, column, values)
    }

    private fun append(connect: String?, whereClause: String, whereArgs: Array<Any>): WhereBuilder {
        if (connect != null) {
            selection += connect
        }
        selection += whereClause
        if (this.selectionArgs == null) {
            selectionArgs = arrayOfNulls(whereArgs.size)
            for (i in whereArgs.indices) {
                this.selectionArgs!![i] = whereArgs[i].toString()
            }
        } else {
            val tempArgs = arrayOfNulls<String>(this.selectionArgs!!.size + whereArgs.size)
            System.arraycopy(this.selectionArgs, 0, tempArgs, 0, this.selectionArgs!!.size)
            System.arraycopy(whereArgs, 0, tempArgs, this.selectionArgs!!.size, whereArgs.size)
            this.selectionArgs = tempArgs
        }
        return this
    }

    private fun appendWhereIn(connect: String?, column: String, values: Array<Any>): WhereBuilder {
        val whereIn = buildWhereIn(column, values.size)
        return append(connect, whereIn, values)
    }

    private fun buildWhereIn(column: String, num: Int): String {
        val sb = StringBuilder(column).append(SPACE).append(IN).append(PARENTHESES_LEFT)
                .append(HOLDER)
        for (i in 0 until num - 1) {
            sb.append(COMMA_HOLDER)
        }
        return sb.append(PARENTHESES_RIGHT).toString()
    }

    /**
     * 构建where的sql语句,自动添加语句首的where。
     */
    fun build(): String {
        return WHERE + selection
    }

    fun where(condition: Condition): WhereBuilder {
        selection = condition.selection
        selectionArgs = condition.selectionArgs
        return this
    }

    /**
     * 转化为Condition。
     */
    fun toCondition() : Condition {
        return Condition(selection, selectionArgs ?: arrayOf())
    }

    companion object {
        private const val WHERE = " WHERE "
        private const val EQUAL_HOLDER = "=?"
        private const val NOT_EQUAL_HOLDER = "!=?"
        private const val GREATER_THAN_HOLDER = ">?"
        private const val LESS_THAN_HOLDER = "<?"
        private const val GREATER_THAN_OR_EQUAL_TO_HOLDER = ">=?"
        private const val LESS_THAN_OR_EQUAL_TO_HOLDER = "<=?"
        private const val COMMA_HOLDER = ",?"
        private const val HOLDER = "?"
        private const val AND = " AND "
        private const val OR = " OR "
        private const val NOT = " NOT "
        private const val IN = " IN "
        private const val PARENTHESES_LEFT = "("
        private const val PARENTHESES_RIGHT = ")"
        private const val SPACE = " "

        fun create(): WhereBuilder {
            return WhereBuilder()
        }

        fun create(whereClause: String, whereArgs: Array<String?>?): WhereBuilder {
            return WhereBuilder(whereClause, whereArgs)
        }

        fun create(condition: Condition): WhereBuilder {
            return WhereBuilder(condition)
        }
    }
}
```

具体的使用例子:查询a=10的第5~15条数据 QueryBuilder.create().limit(5, 15).where(WhereBuilder.create().addWhereEqualTo("a", 10)).toCondition(),以及简单的where查询,查询a=10的数据 WhereBuilder.create().addWhereEqualTo("a", 10).toCondition()。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dora丶Android

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值