杨充 4 年 前
コミット
19f17f14a3
53 ファイル変更2597 行追加3399 行削除
  1. 0 1
      VideoSqlHelper/.gitignore
  2. 0 27
      VideoSqlHelper/build.gradle
  3. 0 0
      VideoSqlHelper/consumer-rules.pro
  4. 0 21
      VideoSqlHelper/proguard-rules.pro
  5. 0 7
      VideoSqlHelper/src/main/AndroidManifest.xml
  6. 0 33
      VideoSqlHelper/src/main/java/com/yc/database/annotation/Column.java
  7. 0 22
      VideoSqlHelper/src/main/java/com/yc/database/annotation/NotDBColumn.java
  8. 0 33
      VideoSqlHelper/src/main/java/com/yc/database/annotation/PrimaryKey.java
  9. 0 28
      VideoSqlHelper/src/main/java/com/yc/database/annotation/Table.java
  10. 0 53
      VideoSqlHelper/src/main/java/com/yc/database/bean/BindSQL.java
  11. 0 62
      VideoSqlHelper/src/main/java/com/yc/database/bean/EntityTable.java
  12. 0 26
      VideoSqlHelper/src/main/java/com/yc/database/bean/PrimaryKey.java
  13. 0 185
      VideoSqlHelper/src/main/java/com/yc/database/bean/Property.java
  14. 0 31
      VideoSqlHelper/src/main/java/com/yc/database/listener/InterDBListener.java
  15. 0 27
      VideoSqlHelper/src/main/java/com/yc/database/listener/SimpleDBListener.java
  16. 0 270
      VideoSqlHelper/src/main/java/com/yc/database/manager/EntityTableManager.java
  17. 0 191
      VideoSqlHelper/src/main/java/com/yc/database/manager/FieldTypeManager.java
  18. 0 286
      VideoSqlHelper/src/main/java/com/yc/database/manager/SQLExecuteManager.java
  19. 0 382
      VideoSqlHelper/src/main/java/com/yc/database/sql/SQLBuilder.java
  20. 0 122
      VideoSqlHelper/src/main/java/com/yc/database/sql/SQLiteContext.java
  21. 0 462
      VideoSqlHelper/src/main/java/com/yc/database/sql/SQLiteDB.java
  22. 0 119
      VideoSqlHelper/src/main/java/com/yc/database/sql/SQLiteDBConfig.java
  23. 0 73
      VideoSqlHelper/src/main/java/com/yc/database/sql/SQLiteDBFactory.java
  24. 0 136
      VideoSqlHelper/src/main/java/com/yc/database/sql/SQLiteHelper.java
  25. 0 152
      VideoSqlHelper/src/main/java/com/yc/database/utils/CursorUtil.java
  26. 0 81
      VideoSqlHelper/src/main/java/com/yc/database/utils/DBLog.java
  27. 0 407
      VideoSqlHelper/src/main/java/com/yc/database/utils/DateUtil.java
  28. 0 119
      VideoSqlHelper/src/main/java/com/yc/database/utils/FieldUtil.java
  29. 0 18
      VideoSqlHelper/src/main/java/com/yc/database/utils/ValueUtil.java
  30. 1 1
      VideoSqlLite/build.gradle
  31. 0 12
      VideoSqlLite/src/main/java/com/yc/videosqllite/dao/SqlLiteCache.java
  32. 249 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskFileUtils.java
  33. 836 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskLruCache.java
  34. 70 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskUtils.java
  35. 180 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/SqlLiteCache.java
  36. 196 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/StrictLineReader.java
  37. 73 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCache.java
  38. 29 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCacheAdapter.java
  39. 97 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCacheWriteLocker.java
  40. 72 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskLruCacheFactory.java
  41. 182 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskLruCacheWrapper.java
  42. 38 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/ExternalCacheDiskCacheFactory.java
  43. 67 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/ExternalPreferredCacheDiskCacheFactory.java
  44. 40 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/InternalCacheDiskCacheFactory.java
  45. 42 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/Key.java
  46. 54 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/Preconditions.java
  47. 23 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/SafeKeyGenerator.java
  48. 14 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/Synthetic.java
  49. 25 2
      VideoSqlLite/src/main/java/com/yc/videosqllite/manager/CacheConfig.java
  50. 149 9
      VideoSqlLite/src/main/java/com/yc/videosqllite/manager/LocationManager.java
  51. 89 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/model/VideoLocation.java
  52. 71 0
      VideoSqlLite/src/main/java/com/yc/videosqllite/utils/CacheLogUtils.java
  53. 0 1
      settings.gradle

+ 0 - 1
VideoSqlHelper/.gitignore

@@ -1 +0,0 @@
-/build

+ 0 - 27
VideoSqlHelper/build.gradle

@@ -1,27 +0,0 @@
-apply plugin: 'com.android.library'
-
-android {
-    compileSdkVersion 29
-    buildToolsVersion "29.0.3"
-
-    defaultConfig {
-        minSdkVersion 17
-        targetSdkVersion 29
-        versionCode 1
-        versionName "1.0"
-
-        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
-        consumerProguardFiles "consumer-rules.pro"
-    }
-
-    buildTypes {
-        release {
-            minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
-        }
-    }
-}
-
-dependencies {
-    implementation fileTree(dir: "libs", include: ["*.jar"])
-}

+ 0 - 0
VideoSqlHelper/consumer-rules.pro


+ 0 - 21
VideoSqlHelper/proguard-rules.pro

@@ -1,21 +0,0 @@
-# Add project specific ProGuard rules here.
-# You can control the set of applied configuration files using the
-# proguardFiles setting in build.gradle.
-#
-# For more details, see
-#   http://developer.android.com/guide/developing/tools/proguard.html
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-#   public *;
-#}
-
-# Uncomment this to preserve the line number information for
-# debugging stack traces.
-#-keepattributes SourceFile,LineNumberTable
-
-# If you keep the line number information, uncomment this to
-# hide the original source file name.
-#-renamesourcefileattribute SourceFile

+ 0 - 7
VideoSqlHelper/src/main/AndroidManifest.xml

@@ -1,7 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.yc.database">
-
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
-
-</manifest>

+ 0 - 33
VideoSqlHelper/src/main/java/com/yc/database/annotation/Column.java

@@ -1,33 +0,0 @@
-package com.yc.database.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 实体字段不设置该注解,则默认已字段名作为列名
- *     revise: 此注解配置数据库指定列名和字段默认值,不配置columnName则默认以字段名作为列名,不配置defaultValue则无列默认值
- * </pre>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface Column {
-
-	/**
-	 * 配置该字段映射到数据库中的列名,不配置默认为字段名
-	 * @return
-	 */
-	String columnName() default "";
-	/**
-	 * 字段默认值
-	 * @return
-	 */
-	String defaultValue() default "";
-
-}

+ 0 - 22
VideoSqlHelper/src/main/java/com/yc/database/annotation/NotDBColumn.java

@@ -1,22 +0,0 @@
-package com.yc.database.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 标识哪些字段不映射为数据库列
- *     revise:
- * </pre>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface NotDBColumn {
-
-}

+ 0 - 33
VideoSqlHelper/src/main/java/com/yc/database/annotation/PrimaryKey.java

@@ -1,33 +0,0 @@
-package com.yc.database.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 主键配置,必须配置该注解,不配置columnName则默认以字段名作为列名,autoGenerate表示主键是否为自增长,默认为是
- *     revise:
- * </pre>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface PrimaryKey {
-
-	/**
-	 * 配置该字段映射到数据库中的列名,不配置默认为字段名
-	 * @return
-	 */
-	String columnName() default "";
-	/**
-	 * 该主键是否设置为自增长,默认为否
-	 * @return
-	 */
-	boolean isAutoGenerate() default false;
-
-}

+ 0 - 28
VideoSqlHelper/src/main/java/com/yc/database/annotation/Table.java

@@ -1,28 +0,0 @@
-package com.yc.database.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 表名注解,实体不设置此注解,或者设置了此注解但name不设置则默认以实体类名作为表名
- *     revise:
- * </pre>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface Table {
-
-	/**
-	 * 自定义表名
-	 * @return
-	 */
-	String name() default "";
-
-}

+ 0 - 53
VideoSqlHelper/src/main/java/com/yc/database/bean/BindSQL.java

@@ -1,53 +0,0 @@
-package com.yc.database.bean;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : Bind SQL信息,包括执行SQL语句以及执行参数
- *     revise:
- * </pre>
- */
-public class BindSQL {
-	/**
-	 * 执行语句(参数使用占位符),表名不能使用占位符
-	 */
-	private String sql;
-	/**
-	 * 占位符绑定参数
-	 */
-	private Object[] bindArgs;
-	
-	public BindSQL() {
-	}
-	
-	public BindSQL(String sql) {
-		super();
-		this.setSql(sql);
-	}
-
-	public BindSQL(String sql, Object[] bindArgs) {
-		super();
-		this.setSql(sql);
-		this.setBindArgs(bindArgs);
-	}
-
-	public Object[] getBindArgs() {
-		return bindArgs;
-	}
-
-	public void setBindArgs(Object[] bindArgs) {
-		this.bindArgs = bindArgs;
-	}
-
-	public String getSql() {
-		return sql;
-	}
-
-	public void setSql(String sql) {
-		this.sql = sql;
-	}
-
-}

+ 0 - 62
VideoSqlHelper/src/main/java/com/yc/database/bean/EntityTable.java

@@ -1,62 +0,0 @@
-package com.yc.database.bean;
-
-import java.util.LinkedHashMap;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 实体类信息
- *     revise:
- * </pre>
- */
-public final class EntityTable {
-	/**
-	 * 实体类Class对象
-	 */
-	private Class<?> mClass;
-	/**
-	 * 实体类对应的表名
-	 */
-	private String mTableName;
-	/**
-	 * 实体类对应的表主键
-	 */
-	private PrimaryKey mPrimaryKey;
-	/**
-	 * 实体类对应的表字段集合<column(字段名), {@link Property}>,不包括主键
-	 */
-	private LinkedHashMap<String, Property> mColumnMap;
-	
-	public EntityTable(Class<?> mClass) {
-		super();
-		this.mClass = mClass;
-		mColumnMap = new LinkedHashMap<String, Property>();
-	}
-
-	public String getTableName() {
-		return mTableName;
-	}
-
-	public void setTableName(String mTableName) {
-		this.mTableName = mTableName;
-	}
-
-	public LinkedHashMap<String, Property> getColumnMap() {
-		return mColumnMap;
-	}
-
-	public PrimaryKey getPrimaryKey() {
-		return mPrimaryKey;
-	}
-
-	public void setPrimaryKey(PrimaryKey mPrimaryKey) {
-		this.mPrimaryKey = mPrimaryKey;
-	}
-
-	public Class<?> getEntityClass() {
-		return mClass;
-	}
-}

+ 0 - 26
VideoSqlHelper/src/main/java/com/yc/database/bean/PrimaryKey.java

@@ -1,26 +0,0 @@
-package com.yc.database.bean;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 主键字段
- *     revise:
- * </pre>
- */
-public class PrimaryKey extends Property {
-	/**
-	 * 当前主键是否为自增长
-	 */
-	private boolean isAutoGenerate;
-
-	public boolean isAutoGenerate() {
-		return isAutoGenerate;
-	}
-
-	public void setAutoGenerate(boolean isAutoGenerate) {
-		this.isAutoGenerate = isAutoGenerate;
-	}
-}

+ 0 - 185
VideoSqlHelper/src/main/java/com/yc/database/bean/Property.java

@@ -1,185 +0,0 @@
-package com.yc.database.bean;
-
-import android.database.Cursor;
-
-import java.lang.reflect.Field;
-import java.util.Date;
-
-import com.yc.database.manager.FieldTypeManager;
-import com.yc.database.utils.DateUtil;
-import com.yc.database.utils.ValueUtil;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 实体属性字段
- *     revise:
- * </pre>
- */
-public class Property {
-	/**
-	 * 字段名,建表时用
-	 */
-	private String column;
-	/**
-	 * 默认值,建表时要设置的字段默认值
-	 */
-	private String defaultValue;
-	/**
-	 * 该字段对应实体信息中的属性字段信息
-	 */
-	private Field field;
-	
-	/**
-	 * 获取指定对象的当前字段的值
-	 * Author: hyl
-	 * Time: 2015-8-16下午10:23:35
-	 * @param entity	获取字段值的对象
-	 * @return
-	 */
-	@SuppressWarnings("unchecked")
-	public <T> T getValue(Object entity) {
-		if(entity != null) {
-			try {
-				field.setAccessible(true);
-				return (T) field.get(entity);
-			} catch (IllegalArgumentException e) {
-				e.printStackTrace();
-			} catch (IllegalAccessException e) {
-				e.printStackTrace();
-			}
-		}
-		return null;
-	}
-	
-	/**
-	 * 设置指定对象的当前字段的值
-	 * Author: hyl
-	 * Time: 2015-8-16下午10:24:08
-	 * @param entity	要设置字段值的对象
-	 * @param value		要设置的值
-	 * @throws Exception
-	 */
-	public void setValue(Object entity, Object value) throws Exception {
-		int fieldType = FieldTypeManager.getFieldType(field);
-		try {
-			field.setAccessible(true);
-			switch(fieldType) {
-				case FieldTypeManager.BASE_TYPE_BOOLEAN:
-					field.set(entity, Boolean.parseBoolean(value.toString()));
-					break;
-				case FieldTypeManager.BASE_TYPE_BYTE_ARRAY:
-					field.set(entity, (byte[])value);
-					break;
-				case FieldTypeManager.BASE_TYPE_CHAR:
-					field.set(entity, value.toString().charAt(0));
-					break;
-				case FieldTypeManager.BASE_TYPE_STRING:
-					field.set(entity, value.toString());
-					break;
-				case FieldTypeManager.BASE_TYPE_DATE:
-					field.set(entity, DateUtil.formatDatetime((Date) value));
-					break;
-				case FieldTypeManager.BASE_TYPE_DOUBLE:
-					field.set(entity, Double.parseDouble(value.toString()));
-					break;
-				case FieldTypeManager.BASE_TYPE_FLOAT:
-					field.set(entity, Float.parseFloat(value.toString()));
-					break;
-				case FieldTypeManager.BASE_TYPE_INT:
-					field.set(entity, Integer.parseInt(value.toString()));
-					break;
-				case FieldTypeManager.BASE_TYPE_LONG:
-					field.set(entity, Long.parseLong(value.toString()));
-					break;
-				case FieldTypeManager.BASE_TYPE_SHORT:
-					field.set(entity, Short.parseShort(value.toString()));
-					break;
-			}
-		} catch (Exception e) {
-			throw e;
-		}
-	}
-	
-	/**
-	 * 设置指定实体对象当前属性字段的值
-	 * Author: hyl
-	 * Time: 2015-8-21上午10:20:14
-	 * @param entity		要设置值的实体对象
-	 * @param cursor		数据来源
-	 * @throws Exception
-	 */
-	public void setValue(Object entity, Cursor cursor) throws Exception {
-		int fieldType = FieldTypeManager.getFieldType(field);
-		try {
-			int columnIdx = cursor.getColumnIndex(column);
-			if(columnIdx == -1) {//当前游标中没有该字段的值
-				return;
-			}
-			String columnValue = cursor.getString(columnIdx);
-			boolean isEmpty = ValueUtil.isEmpty(columnValue);
-			field.setAccessible(true);
-			switch(fieldType) {
-				case FieldTypeManager.BASE_TYPE_BOOLEAN:
-					field.set(entity, isEmpty ? false : Boolean.parseBoolean(columnValue));
-					break;
-				case FieldTypeManager.BASE_TYPE_BYTE_ARRAY:
-					field.set(entity, cursor.getBlob(columnIdx));
-					break;
-				case FieldTypeManager.BASE_TYPE_CHAR:
-					field.set(entity, isEmpty ? Character.valueOf(' ') : columnValue.charAt(0));
-					break;
-				case FieldTypeManager.BASE_TYPE_STRING:
-					field.set(entity, isEmpty ? "" : columnValue);
-					break;
-				case FieldTypeManager.BASE_TYPE_DATE:
-					field.set(entity, isEmpty ? "" : DateUtil.parseDatetime(columnValue));
-					break;
-				case FieldTypeManager.BASE_TYPE_DOUBLE:
-					field.set(entity, cursor.getDouble(columnIdx));
-					break;
-				case FieldTypeManager.BASE_TYPE_FLOAT:
-					field.set(entity, cursor.getFloat(columnIdx));
-					break;
-				case FieldTypeManager.BASE_TYPE_INT:
-					field.set(entity, cursor.getInt(columnIdx));
-					break;
-				case FieldTypeManager.BASE_TYPE_LONG:
-					field.set(entity, cursor.getLong(columnIdx));
-					break;
-				case FieldTypeManager.BASE_TYPE_SHORT:
-					field.set(entity, cursor.getShort(columnIdx));
-					break;
-			}
-		} catch (Exception e) {
-			throw e;
-		}
-	}
-	
-	public String getColumn() {
-		return column;
-	}
-	
-	public void setColumn(String column) {
-		this.column = column;
-	}
-	
-	public String getDefaultValue() {
-		return defaultValue;
-	}
-	
-	public void setDefaultValue(String defaultValue) {
-		this.defaultValue = defaultValue;
-	}
-	
-	public Field getField() {
-		return field;
-	}
-	
-	public void setField(Field field) {
-		this.field = field;
-	}
-}

+ 0 - 31
VideoSqlHelper/src/main/java/com/yc/database/listener/InterDBListener.java

@@ -1,31 +0,0 @@
-package com.yc.database.listener;
-
-import android.database.sqlite.SQLiteDatabase;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 数据监听(数据库第一次创建,版本变更时的监听)
- *     revise:
- * </pre>
- */
-public interface InterDBListener {
-	/**
-	 * 数据库版本变更的时候执行,在数据库DB打开时会进行版本号判断,当版本号不同的时候会执行该监听处理函数(只会执行一次)
-	 * 在此方法中执行数据库操作不会出现(java.lang.IllegalStateException: getDatabase called recursively)异常,已解决
-	 * @param db			数据库
-	 * @param oldVersion	旧版本号
-	 * @param newVersion	新版本号
-	 */
-	void onUpgradeHandler(SQLiteDatabase db, int oldVersion, int newVersion);
-
-	/**
-	 * 数据库文件第一次创建时的监听响应函数,已经存在的数据库不会执行此方法
-	 * 在此方法中执行数据库操作不会出现(java.lang.IllegalStateException: getDatabase called recursively)异常,已解决
-	 * @param db	数据库
-	 */
-	void onDbCreateHandler(SQLiteDatabase db);
-}

+ 0 - 27
VideoSqlHelper/src/main/java/com/yc/database/listener/SimpleDBListener.java

@@ -1,27 +0,0 @@
-package com.yc.database.listener;
-
-import android.database.sqlite.SQLiteDatabase;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 数据库监听空实现
- *     revise:
- * </pre>
- */
-public class SimpleDBListener implements InterDBListener {
-
-	@Override
-	public void onUpgradeHandler(SQLiteDatabase db, int oldVersion, int newVersion) {
-
-	}
-
-	@Override
-	public void onDbCreateHandler(SQLiteDatabase db) {
-
-	}
-
-}

+ 0 - 270
VideoSqlHelper/src/main/java/com/yc/database/manager/EntityTableManager.java

@@ -1,270 +0,0 @@
-package com.yc.database.manager;
-
-import android.database.Cursor;
-
-import java.io.Serializable;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-
-import com.yc.database.sql.SQLBuilder;
-import com.yc.database.annotation.Column;
-import com.yc.database.annotation.NotDBColumn;
-import com.yc.database.annotation.PrimaryKey;
-import com.yc.database.bean.EntityTable;
-import com.yc.database.bean.Property;
-import com.yc.database.utils.CursorUtil;
-import com.yc.database.utils.ValueUtil;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 实体类管理对象
- *     revise:
- * </pre>
- */
-public final class EntityTableManager implements Serializable {
-	/**
-	 * uid
-	 */
-	private static final long serialVersionUID = 1L;
-	/**
-	 * 每张表的相关信息缓存集合<实体类{@link}Class, {@link}Entity>
-	 */
-	private static HashMap<Class<?>, EntityTable> mTableMap = new HashMap<Class<?>, EntityTable>();
-	
-	/**
-	 * 获取EntityTable对象
-	 * @param entity
-	 * @return
-	 */
-	public static <T> EntityTable getEntityTable(T entity) {
-		return getEntityTable(entity.getClass());
-	}
-	
-	/**
-	 * 获取EntityTable对象
-	 * @param mClass
-	 * @return
-	 */
-	public static EntityTable getEntityTable(Class<?> mClass) {
-		if(mTableMap.containsKey(mClass)) {
-			return mTableMap.get(mClass);
-		} else {
-			return createEntityTable(mClass);
-		}
-	}
-
-	/**
-	 * 检查实体类表是否存在,不存在则创建该实体表,线程安全
-	 * @param entity
-	 */
-	public synchronized static <T> void checkOrCreateTable(SQLExecuteManager sqlExecuteManager, T entity) {
-		Class<?> aClass = entity.getClass();
-		checkOrCreateTable(sqlExecuteManager, aClass);
-	}
-	
-	/**
-	 * 检查指定类所表示的表是否存在,不存在则创建该实体表,线程安全
-	 * @param sqlExecuteManager
-	 * @param mClass
-	 */
-	public synchronized static void checkOrCreateTable(SQLExecuteManager sqlExecuteManager, Class<?> mClass) {
-		if(!mTableMap.containsKey(mClass)) {//先在缓存中查找,缓存中不存在
-			EntityTable entityTable = createEntityTable(mClass);
-			mTableMap.put(mClass, entityTable);
-			if(!checkTableIsInDB(sqlExecuteManager, entityTable.getTableName())) {//数据库中不存在
-				createTable(sqlExecuteManager, entityTable);
-			} else {//数据库中存在该表
-				//对已存在表的字段与最新的实体对象进行比较,看是否需要更新表的字段信息
-				checkOrAlterTableColumn(sqlExecuteManager, entityTable);
-			}
-		} else {//缓存中存在实体表映射关系,检查当前数据库中是否存在该表,不存在创建该表
-			if(!checkTableIsInDB(sqlExecuteManager, mTableMap.get(mClass).getTableName())) {//数据库中不存在
-				createTable(sqlExecuteManager, mTableMap.get(mClass));
-			}
-		}
-	}
-	
-	/**
-	 * 检查表的字段信息,实体中有新增字段,则给表添加相应的字段
-	 * @param sqlExecuteManager
-	 * @param entityTable
-	 */
-	public static void checkOrAlterTableColumn(SQLExecuteManager sqlExecuteManager, EntityTable entityTable) {
-		Cursor cursor = sqlExecuteManager.query(SQLBuilder.getTableAllColumnSQL(entityTable.getTableName()));
-		LinkedHashMap<String, Property> propertys = entityTable.getColumnMap();
-		//数据表中已有的字段信息
-		List<String> columns = Arrays.asList(cursor.getColumnNames());
-		
-		List<Property> addColumns = new ArrayList<Property>();
-		for(String key : propertys.keySet()) {
-			Property property = propertys.get(key);
-			if (property!=null){
-				if(!columns.contains(property.getColumn())) {
-					//数据表中不包含当前实体属性字段信息,说明当前实体属性字段需要新增到数据表中
-					addColumns.add(propertys.get(key));
-				}
-			}
-		}
-		
-		if(addColumns.size() > 0) {
-			try {
-				sqlExecuteManager.beginTransaction();
-				for(Property column : addColumns) {
-					sqlExecuteManager.execSQL(SQLBuilder.getAlterTableSQL(entityTable.getTableName(), column));
-				}
-				sqlExecuteManager.successTransaction();
-			} finally {
-				sqlExecuteManager.endTransaction();
-			}
-		}
-	}
-	
-	/**
-	 * 创建实体类
-	 * @param mClass
-	 */
-	public static EntityTable createEntityTable(Class<?> mClass) {
-		EntityTable entity = new EntityTable(mClass);
-		entity.setTableName(SQLBuilder.getTableName(mClass));
-
-		Class<?> claxx = mClass;
-		while(claxx != Object.class) {
-			setEntityTableField(entity, claxx);
-			claxx = claxx.getSuperclass();
-		}
-		
-		if(entity.getPrimaryKey() == null) {
-			throw new RuntimeException("必须为实体" + mClass.getName() + "设置主键---[在要设置主键的字段上添加注解PrimaryKey来设置主键]");
-		}
-		return entity;
-	}
-
-	private static void setEntityTableField(EntityTable entity, Class claxx) {
-		/*
-		 * 获取Class下声明的所有字段信息(包括:public,protected,private,默认级别, 四种访问级别的字段信息)
-		 * 如果该Class没有声明任何字段或是Class代表一个基本类型、数组或void,则返回数组长度为0
-		 * */
-		Field[] fields = claxx.getDeclaredFields();
-		String columnName = "";//字段列名
-		for(int i = 0; i < fields.length; i++) {
-			Field field = fields[i];
-
-			if (Modifier.isStatic(field.getModifiers())) {//过滤掉static静态字段
-				continue;
-			}
-
-			if(FieldTypeManager.getFieldType(field) == FieldTypeManager.NOT_BASE_TYPE) {//过滤掉非基本类型字段
-				continue;
-			}
-
-			if(entity.getPrimaryKey() == null) {//主键设置过后即不再遍历主键注解
-				PrimaryKey key = field.getAnnotation(PrimaryKey.class);
-				if(key != null) {//声明了主键字段
-					if(key.isAutoGenerate() && !FieldTypeManager.isAutoIncrementType(field)) {
-						throw new RuntimeException("自增长主键字段类型不正确,请设置自增长字段类型为long");
-					}
-					if(ValueUtil.isEmpty(key.columnName())) {//没有通过注解设置列名,默认取字段名称为列名
-						columnName = field.getName();
-					} else {
-						columnName = key.columnName();
-					}
-					if(Arrays.binarySearch(SQLExecuteManager.SQLITE_KEYWORDS, columnName.toUpperCase()) >= 0) {
-						throw new IllegalArgumentException("字段名或注解columnName属性不能为SQLite关键字:" + columnName);
-					}
-					com.yc.database.bean.PrimaryKey primaryKey = new com.yc.database.bean.PrimaryKey();
-					primaryKey.setField(field);
-					primaryKey.setColumn(columnName);
-					primaryKey.setAutoGenerate(key.isAutoGenerate());//获取是否自动增长
-					entity.setPrimaryKey(primaryKey);
-					continue;
-				}
-			}
-
-			Property property = new Property();
-			property.setField(field);
-
-			Column column = field.getAnnotation(Column.class);
-			if(column != null) {//声明了 字段  注解
-				if(ValueUtil.isEmpty(column.columnName())) {//没有通过注解设置列名,默认取字段名称为列名
-					columnName = field.getName();
-				} else {
-					columnName = column.columnName();
-				}
-				if(Arrays.binarySearch(SQLExecuteManager.SQLITE_KEYWORDS, columnName.toUpperCase()) >= 0) {
-					throw new IllegalArgumentException("字段名或注解columnName属性不能为SQLite关键字:" + columnName);
-				}
-				if(!ValueUtil.isEmpty(column.defaultValue())) {//设置了字段默认值
-					property.setDefaultValue(column.defaultValue());
-				}
-				property.setColumn(columnName);
-				entity.getColumnMap().put(property.getColumn(), property);
-				continue;
-			}
-
-			NotDBColumn notDbColumn = field.getAnnotation(NotDBColumn.class);
-			if(notDbColumn != null) {//非数据库字段不作处理
-				continue;
-			}
-
-			if(Arrays.binarySearch(SQLExecuteManager.SQLITE_KEYWORDS, field.getName().toUpperCase()) >= 0) {
-				throw new IllegalArgumentException("注解字段名不能为SQLite关键字:" + columnName);
-			}
-
-			//没有设置注解的字段,以字段名为数据库列名
-			property.setColumn(field.getName());
-			entity.getColumnMap().put(property.getColumn(), property);
-		}
-	}
-	
-	/**
-	 * 根据实体类创建数据库表
-	 * @param sqlExecuteManager
-	 * @param entity
-	 */
-	public static void createTable(SQLExecuteManager sqlExecuteManager, EntityTable entity) {
-		dropTable(sqlExecuteManager, entity);//先删除表
-		String createTableSQL = SQLBuilder.getCreateTableSQL(entity);//构造建表语句
-		sqlExecuteManager.execSQL(createTableSQL);//建表
-	}
-	
-	/**
-	 * 删除实体类对应的数据库表
-	 * @param sqlExecuteManager
-	 * @param entity
-	 */
-	public static void dropTable(SQLExecuteManager sqlExecuteManager, EntityTable entity) {
-		sqlExecuteManager.dropTable(entity.getTableName());
-		mTableMap.remove(entity.getClass());
-	}
-	
-	/**
-	 * 清除实体表缓存对象
-	 */
-	public static void clear() {
-		if (mTableMap!=null){
-			mTableMap.clear();
-		}
-	}
-	
-	/**
-	 * 检查数据库中是否存在指定表
-	 * @param sqlExecuteManager
-	 * @param tableName
-	 * @return
-	 */
-	public static boolean checkTableIsInDB(SQLExecuteManager sqlExecuteManager, String tableName) {
-		Cursor cursor = null;
-		cursor = sqlExecuteManager.query(SQLBuilder.getCheckTableExistSQL(tableName));
-		long total = CursorUtil.parseCursorTotal(cursor);
-		return total > 0 ? true : false;
-	}
-}

+ 0 - 191
VideoSqlHelper/src/main/java/com/yc/database/manager/FieldTypeManager.java

@@ -1,191 +0,0 @@
-package com.yc.database.manager;
-
-import java.lang.reflect.Field;
-import java.util.Date;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 字段类型
- *     revise:
- * </pre>
- */
-public final class FieldTypeManager {
-	/**
-	 * 空值
-	 */
-	public static final int VALUE_TYPE_NULL = -1;
-	/**
-	 * 非数据库支持基本类型
-	 */
-	public static final int NOT_BASE_TYPE = 0;
-	/**
-	 * String
-	 */
-	public static final int BASE_TYPE_STRING = 1;
-	/**
-	 * int
-	 */
-	public static final int BASE_TYPE_INT = 2;
-	/**
-	 * short
-	 */
-	public static final int BASE_TYPE_SHORT = 3;
-	/**
-	 * float
-	 */
-	public static final int BASE_TYPE_FLOAT = 4;
-	/**
-	 * double
-	 */
-	public static final int BASE_TYPE_DOUBLE = 5;
-	/**
-	 * long
-	 */
-	public static final int BASE_TYPE_LONG = 6;
-	/**
-	 * char
-	 */
-	public static final int BASE_TYPE_CHAR = 7;
-	/**
-	 * boolean
-	 */
-	public static final int BASE_TYPE_BOOLEAN = 8;
-	/**
-	 * byte[]
-	 */
-	public static final int BASE_TYPE_BYTE_ARRAY = 9;
-	/**
-	 * Date
-	 */
-	public static final int BASE_TYPE_DATE = 10;
-	
-	/**
-	 * 该字段是否为基本字段类型
-	 * @param field
-	 * @return
-	 */
-	public static int getFieldType(Field field) {
-		Class<?> fieldType = field.getType();
-		if (fieldType == String.class) {
-			return FieldTypeManager.BASE_TYPE_STRING;
-		}
-		if(fieldType == Date.class || fieldType == java.sql.Date.class) {
-			return FieldTypeManager.BASE_TYPE_DATE;
-		}
-		if (fieldType == boolean.class || fieldType == Boolean.class) {
-			return FieldTypeManager.BASE_TYPE_BOOLEAN;
-		}
-		if (fieldType == short.class || fieldType == Short.class) {
-			return FieldTypeManager.BASE_TYPE_SHORT;
-		} 
-		if (fieldType == int.class || fieldType == Integer.class) {
-			return FieldTypeManager.BASE_TYPE_INT;
-		}
-		if (fieldType == long.class || fieldType == Long.class) {
-			return FieldTypeManager.BASE_TYPE_LONG;
-		}
-		if (fieldType == float.class || fieldType == Float.class) {
-			return FieldTypeManager.BASE_TYPE_FLOAT;
-		}
-		if (fieldType == double.class || fieldType == Double.class) {
-			return FieldTypeManager.BASE_TYPE_DOUBLE;
-		}
-		if (fieldType == byte[].class || fieldType == Byte[].class) {
-			return FieldTypeManager.BASE_TYPE_BYTE_ARRAY;
-		}
-		if(fieldType == char.class || fieldType == Character.class) {
-			return FieldTypeManager.BASE_TYPE_CHAR;
-		}
-		return FieldTypeManager.NOT_BASE_TYPE;
-	}
-	
-	/**
-	 * 获取某个值的类型
-	 * @param obj
-	 * @return
-	 */
-	public static int getValueType(Object obj) {
-		if(obj == null) {
-			return FieldTypeManager.VALUE_TYPE_NULL;
-		}
-		if (obj instanceof String) {
-			return FieldTypeManager.BASE_TYPE_STRING;
-		}
-		if(obj instanceof Date || obj instanceof java.sql.Date) {
-			return FieldTypeManager.BASE_TYPE_DATE;
-		}
-		if (obj instanceof Boolean) {
-			return FieldTypeManager.BASE_TYPE_BOOLEAN;
-		}
-		if (obj instanceof Short) {
-			return FieldTypeManager.BASE_TYPE_SHORT;
-		} 
-		if (obj instanceof Integer) {
-			return FieldTypeManager.BASE_TYPE_INT;
-		}
-		if (obj instanceof Long) {
-			return FieldTypeManager.BASE_TYPE_LONG;
-		}
-		if (obj instanceof Float) {
-			return FieldTypeManager.BASE_TYPE_FLOAT;
-		}
-		if (obj instanceof Double) {
-			return FieldTypeManager.BASE_TYPE_DOUBLE;
-		}
-		if (obj instanceof byte[] || obj instanceof Byte[]) {
-			return FieldTypeManager.BASE_TYPE_BYTE_ARRAY;
-		}
-		if(obj instanceof Character) {
-			return FieldTypeManager.BASE_TYPE_CHAR;
-		}
-		return FieldTypeManager.NOT_BASE_TYPE;
-	}
-	
-	/**
-	 * 根据字段类型获取数据库支持的字段类型
-	 * @param field
-	 * @return
-	 */
-	public static String getColumnTypeValue(Field field) {
-		String type = "TEXT";
-		int fieldType = FieldTypeManager.getFieldType(field);
-		switch(fieldType) {
-			case FieldTypeManager.BASE_TYPE_CHAR:
-			case FieldTypeManager.BASE_TYPE_STRING:
-			case FieldTypeManager.BASE_TYPE_DATE:
-				type = "TEXT";
-				break;
-			case FieldTypeManager.BASE_TYPE_BOOLEAN:
-			case FieldTypeManager.BASE_TYPE_INT:
-			case FieldTypeManager.BASE_TYPE_SHORT:
-			case FieldTypeManager.BASE_TYPE_LONG:
-				type = "INTEGER";
-				break;
-			case FieldTypeManager.BASE_TYPE_DOUBLE:
-			case FieldTypeManager.BASE_TYPE_FLOAT:
-				type = "REAL";
-				break;
-			case FieldTypeManager.BASE_TYPE_BYTE_ARRAY:
-				type = "BLOB";
-				break;
-		}
-		return type;
-	}
-	
-	/**
-	 * 当前字段是否为自增长字段类型
-	 * @param field
-	 * @return
-	 */
-	public static boolean isAutoIncrementType(Field field) {
-		int type = getFieldType(field);
-		if(type != BASE_TYPE_LONG) {
-			return false;
-		}
-		return true;
-	}
-}

+ 0 - 286
VideoSqlHelper/src/main/java/com/yc/database/manager/SQLExecuteManager.java

@@ -1,286 +0,0 @@
-package com.yc.database.manager;
-
-import android.annotation.SuppressLint;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteStatement;
-
-import java.io.Serializable;
-import java.util.Date;
-
-import com.yc.database.bean.BindSQL;
-import com.yc.database.utils.DBLog;
-import com.yc.database.utils.DateUtil;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : SQL语句执行器
- *     revise:
- * </pre>
- */
-public class SQLExecuteManager implements Serializable {
-
-	/**
-	 * uid
-	 */
-	private static final long serialVersionUID = 1L;
-	/**
-	 * SQLite中的关键字 
-	 */
-	public static final String[] SQLITE_KEYWORDS = { "ABORT", "ACTION",
-		"ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", "ASC",
-		"ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY",
-		"CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT",
-		"CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
-		"CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT",
-		"DEFERRABLE", "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT",
-		"DROP", "EACH", "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE",
-		"EXISTS", "EXPLAIN", "FAIL", "FOR", "FOREIGN", "FROM", "FULL",
-		"GLOB", "GROUP", "HAVING", "IF", "IGNORE", "IMMEDIATE", "IN",
-		"INDEX", "INDEXED", "INITIALLY", "INNER", "INSERT", "INSTEAD",
-		"INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", "LEFT", "LIKE",
-		"LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", "NULL", "OF",
-		"OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA",
-		"PRIMARY", "QUERY", "RAISE", "REFERENCES", "REGEXP", "REINDEX",
-		"RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", "ROLLBACK",
-		"ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", "TEMPORARY",
-		"THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
-		"UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN",
-		"WHERE" };
-	
-	/**
-	 * 数据库操作类
-	 */
-	private SQLiteDatabase mSQLiteDataBase;
-
-	public SQLExecuteManager(SQLiteDatabase mSQLiteDataBase) {
-		super();
-		this.mSQLiteDataBase = mSQLiteDataBase;
-	}
-	
-	/**
-	 * 开启一个事务(事务开始)
-	 * 在事务代码执行完成后,必须要执行successTransaction()将事务标记为成功
-	 * 在代码的最后必须要执行endTransaction()来结束当前事务,如果事务成功则提交事务,否则回滚事务
-	 * <pre>
-	 *   db.beginTransaction();
-	 *   try {
-	 *     ...
-	 *     db.setTransactionSuccessful();
-	 *   } finally {
-	 *     db.endTransaction();
-	 *   }
-	 * </pre>
-	 */
-	public void beginTransaction() {
-		this.mSQLiteDataBase.beginTransaction();
-	}
-	
-	/**
-	 * 标记当前事务成功
-	 */
-	public void successTransaction() {
-		this.mSQLiteDataBase.setTransactionSuccessful();
-	}
-	
-	/**
-	 * 结束当前事务,当事物被标记成功后,此操作会提交事务,否则会回滚事务
-	 */
-	public void endTransaction() {
-		this.mSQLiteDataBase.endTransaction();
-	}
-
-	/**
-	 * 执行指定无返回值的单条SQL语句,如建表、创建数据库等
-	 * @param sql						执行sql
-	 */
-	public void execSQL(String sql) {
-		DBLog.debug(sql);
-		this.mSQLiteDataBase.execSQL(sql);
-	}
-	
-	/**
-	 * 插入一条记录,返回该记录的rowId
-	 * @param sql
-	 * @param args
-	 * @return				插入失败返回-1,成功返回rowId
-	 */
-	public long insert(String sql, Object[] args) {
-		long rowId = -1;
-		SQLiteStatement statement = this.mSQLiteDataBase.compileStatement(sql);
-		try {
-			if(args != null) {
-				for(int i = 0; i < args.length; i++) {
-					bindArgs(statement, i + 1, args[i]);
-				}
-			}
-			rowId = statement.executeInsert();
-			DBLog.debug(sql, args);
-		} finally {
-			statement.close();
-		}
-		return rowId;
-	}
-	
-	/**
-	 * 根据BindSQL进行插入数据
-	 * @param bindSQL
-	 * @return
-	 * @throws Exception
-	 */
-	public long insert(BindSQL bindSQL) {
-		if (bindSQL==null){
-			return -1;
-		}
-		String sql = bindSQL.getSql();
-		Object[] bindArgs = bindSQL.getBindArgs();
-		return insert(sql, bindArgs);
-	}
-	
-	/**
-	 * 绑定参数
-	 * @param statement
-	 * @param position
-	 * @param args
-	 */
-	private void bindArgs(SQLiteStatement statement, int position, Object args) {
-		int type = FieldTypeManager.getValueType(args);
-		switch(type) {
-			case FieldTypeManager.VALUE_TYPE_NULL:
-				statement.bindNull(position);
-				break;
-			case FieldTypeManager.BASE_TYPE_BYTE_ARRAY:
-				statement.bindBlob(position, (byte[])args);
-				break;
-			case FieldTypeManager.BASE_TYPE_CHAR:
-			case FieldTypeManager.BASE_TYPE_STRING:
-				statement.bindString(position, args.toString());
-				break;
-			case FieldTypeManager.BASE_TYPE_DATE:
-				statement.bindString(position, DateUtil.formatDatetime((Date) args));
-				break;
-			case FieldTypeManager.BASE_TYPE_DOUBLE:
-			case FieldTypeManager.BASE_TYPE_FLOAT:
-				statement.bindDouble(position, Double.parseDouble(args.toString()));
-				break;
-			case FieldTypeManager.BASE_TYPE_INT:
-			case FieldTypeManager.BASE_TYPE_LONG:
-			case FieldTypeManager.BASE_TYPE_SHORT:
-				statement.bindLong(position, Long.parseLong(args.toString()));
-				break;
-			case FieldTypeManager.NOT_BASE_TYPE:
-				throw new IllegalArgumentException("未知参数类型,请检查绑定参数");
-		}
-	}
-	
-	/**
-	 * 删除指定表
-	 * @param tableName
-	 * @throws Exception
-	 */
-	public void dropTable(String tableName) {
-		String sql = "DROP TABLE IF EXISTS " + tableName;
-		execSQL(sql);
-	}
-	
-	/**
-	 * 删除,表名不能使用占位符
-	 * @param bindSQL	
-	 */
-	public void delete(BindSQL bindSQL) {
-		updateOrDelete(bindSQL.getSql(), bindSQL.getBindArgs());
-	}
-	
-	/**
-	 * 删除,表名不能使用占位符
-	 * @param sql		删除语句(参数使用占位符)
-	 * @param args		占位符参数
-	 */
-	@SuppressLint("NewApi")
-	public void updateOrDelete(String sql, Object[] args) {
-		SQLiteStatement statement = mSQLiteDataBase.compileStatement(sql);
-		try {
-			if(args != null) {
-				for(int i = 0; i < args.length; i++) {
-					bindArgs(statement, i + 1, args[i]);
-				}
-			}
-			DBLog.debug(sql, args);
-			statement.executeUpdateDelete();
-		} finally {
-			statement.close();
-		}
-	}
-	
-	/**
-	 * 删除(对于表名需要动态获取的,此方法非常适合)
-	 * @param tableName			要删除的数据表
-	 * @param whereClause		where后面的条件句(delete from XXX where XXX),参数使用占位符
-	 * @param whereArgs			where子句后面的占位符参数
-	 */
-	public void delete(String tableName, String whereClause, String[] whereArgs) {
-		DBLog.debug("{SQL:DELETE FROM " + tableName + " WHERE " + whereClause + ",PARAMS:" + whereArgs + "}");
-		mSQLiteDataBase.delete(tableName, whereClause, whereArgs);
-	}
-	
-	/**
-	 * 更新
-	 * @param bindSQL
-	 */
-	public void update(BindSQL bindSQL) {
-		updateOrDelete(bindSQL.getSql(), bindSQL.getBindArgs());
-	}
-	
-	/**
-	 * 根据SQL进行查询
-	 * @param sql
-	 * @return
-	 */
-	public Cursor query(String sql) {
-		return query(sql, null);
-	}
-	
-	/**
-	 * 执行绑定语句
-	 * 运行一个预置的SQL语句,返回带游标的数据集(与query的语句最大的区别 = 防止SQL注入)
-	 * @param sql								sql语句
-	 * @param whereArgs							搜索条件
-	 * @return
-	 */
-	public Cursor query(String sql, String[] whereArgs) {
-		DBLog.debug("{SQL:" + sql + ",PARAMS:" + whereArgs + "}");
-		return this.mSQLiteDataBase.rawQuery(sql, whereArgs); 
-	}
-
-	/**
-	 * 根据BindSQL查询
-	 * @param bindSQL
-	 * @return
-	 */
-	public Cursor query(BindSQL bindSQL) {
-		return query(bindSQL.getSql(), (String[])bindSQL.getBindArgs());
-	}
-
-	@Deprecated
-	public Cursor query(boolean distinct, String table, String[] columns,
-						String selection, String[] selectionArgs, String groupBy,
-						String having, String orderBy, String limit) {
-		// 查询指定的数据表返回一个带游标的数据集。
-		// 各参数说明:
-		// table:表名称
-		// colums:列名称数组
-		// selection:条件子句,相当于where
-		// selectionArgs:条件语句的参数数组
-		// groupBy:分组
-		// having:分组条件
-		// orderBy:排序类
-		// limit:分页查询的限制
-		return this.mSQLiteDataBase.query(distinct, table, columns, selection,
-				selectionArgs, groupBy, having, orderBy, limit);
-	}
-
-}

+ 0 - 382
VideoSqlHelper/src/main/java/com/yc/database/sql/SQLBuilder.java

@@ -1,382 +0,0 @@
-package com.yc.database.sql;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-
-import com.yc.database.bean.BindSQL;
-import com.yc.database.bean.EntityTable;
-import com.yc.database.bean.Property;
-import com.yc.database.manager.EntityTableManager;
-import com.yc.database.manager.FieldTypeManager;
-import com.yc.database.utils.ValueUtil;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : SQL语句构造器
- *     revise:
- * </pre>
- */
-public class SQLBuilder {
-	
-	/**
-	 * 获取当前实体类的表名
-	 * @param mClass
-	 * @return
-	 */
-	public static String getTableName(Class<?> mClass) {
-		com.yc.database.annotation.Table anno = mClass.getAnnotation(com.yc.database.annotation.Table.class);
-		if(anno == null || ValueUtil.isEmpty(anno.name())) {
-			return mClass.getSimpleName();
-		}
-		return anno.name();
-	}
-	
-	/**
-	 * 根据实体对象构造建表语句
-	 * @param entity
-	 * @return
-	 */
-	public static String getCreateTableSQL(EntityTable entity) {
-		StringBuilder createTableSql = new StringBuilder();
-		createTableSql.append("CREATE TABLE IF NOT EXISTS ");
-		createTableSql.append(entity.getTableName());//表名
-		createTableSql.append("(");
-		createTableSql.append(entity.getPrimaryKey().getColumn());//主键字段
-		createTableSql.append(" ");
-		createTableSql.append(FieldTypeManager.getColumnTypeValue(entity.getPrimaryKey().getField()));//主键字段类型
-		createTableSql.append(" PRIMARY KEY ");//主键
-		if(entity.getPrimaryKey().isAutoGenerate()) {
-			createTableSql.append(" AUTOINCREMENT ");
-		}
-		LinkedHashMap<String, Property> columnMap = entity.getColumnMap();
-		for(String key : columnMap.keySet()) {
-			createTableSql.append(",");
-			createTableSql.append(columnMap.get(key).getColumn()).append(" ");//字段名
-			createTableSql.append(FieldTypeManager.getColumnTypeValue(columnMap.get(key).getField()));//字段类型
-			if(!ValueUtil.isEmpty(columnMap.get(key).getDefaultValue())) {
-				createTableSql.append(" ").append("DEFAULT ").append(columnMap.get(key).getDefaultValue());
-			}
-		}
-		createTableSql.append(")");
-		return createTableSql.toString();
-	}
-	
-	/**
-	 * 检查表是否存在语句
-	 * @param tableName
-	 * @return
-	 */
-	public static String getCheckTableExistSQL(String tableName) {
-		return "SELECT COUNT(*) TOTALCOUNT FROM SQLITE_MASTER WHERE UPPER(TYPE) ='TABLE' AND NAME = '" + tableName + "'";
-	}
-	
-	/**
-	 * 查询某个表中所有的字段
-	 * @param tableName
-	 * @return
-	 */
-	public static String getTableAllColumnSQL(String tableName) {
-		return "SELECT * FROM "  + tableName + " LIMIT 0";
-	}
-	
-	/**
-	 * 更新表结构SQL(SQLite不支持删除列)
-	 * @param tableName
-	 * @param property
-	 * @return
-	 */
-	public static String getAlterTableSQL(String tableName, Property property) {
-		return "ALTER TABLE " + tableName + 
-			   " ADD COLUMN " + property.getColumn() + " " + FieldTypeManager.getColumnTypeValue(property.getField()) +
-			   (ValueUtil.isEmpty(property.getDefaultValue()) ? "" : " DEFAULT " + property.getDefaultValue());
-	}
-	
-	/**
-	 * 构造插入语句
-	 * @param entity	要插入的实体对象
-	 * @return
-	 */
-	public static <T> BindSQL getInsertSQL(T entity) {
-		EntityTable entityTable = EntityTableManager.getEntityTable(entity);
-		
-		boolean isAutoIncrement = entityTable.getPrimaryKey().isAutoGenerate();
-		
-		String tableName = entityTable.getTableName();
-		Collection<Property> propertys = entityTable.getColumnMap().values();
-		Object[] bindArgs = null;
-		if(isAutoIncrement) {//如果为自增长主键,则在构造插入语句的时候不需要构造主键列,数据库会自动为自增长主键设置值
-			bindArgs = new Object[propertys.size()];
-		} else {
-			bindArgs = new Object[propertys.size() + 1];
-		}
-
-		StringBuilder sqlBuilder = new StringBuilder();
-		StringBuilder argsBuidler = new StringBuilder();
-		int i = 0;
-		
-		sqlBuilder.append("INSERT INTO ").append(tableName).append("(");
-		argsBuidler.append(" VALUES(");
-		
-		if(!isAutoIncrement) {//主键不是自增长列,需要自己设置主键值
-			sqlBuilder.append(entityTable.getPrimaryKey().getColumn()).append(",");//主键
-			argsBuidler.append("?").append(",");
-			if(ValueUtil.isEmpty(entityTable.getPrimaryKey().getValue(entity))) {//判断主键值是否为空
-				throw new IllegalArgumentException("非自增长主键必须手动设置主键值");
-			}
-			bindArgs[i++] = entityTable.getPrimaryKey().getValue(entity);
-		}
-		
-		Iterator<Property> iterator = propertys.iterator();
-		Property property;
-		while(iterator.hasNext()) {
-			property = iterator.next();
-			
-			sqlBuilder.append(property.getColumn());
-			argsBuidler.append("?");
-			
-			bindArgs[i++] = getPropertyValue(property, entity);
-			
-			sqlBuilder.append(",");
-			argsBuidler.append(",");
-		}
-		sqlBuilder.deleteCharAt(sqlBuilder.length() - 1);
-		argsBuidler.deleteCharAt(argsBuidler.length() - 1);
-		sqlBuilder.append(")");
-		argsBuidler.append(")");
-		sqlBuilder.append(argsBuidler);
-		
-		BindSQL bindSQL = new BindSQL(sqlBuilder.toString());
-		bindSQL.setBindArgs(bindArgs);
-		return bindSQL;
-	}
-	
-	private static <T> String getPropertyValue(Property property, T entity) {
-		String value = null;
-		Object obj = property.getValue(entity);//此值的类型为多种基本类型,如果为int、long  直接赋值给value会运行报错
-		switch(FieldTypeManager.getFieldType(property.getField())) {
-			case FieldTypeManager.BASE_TYPE_DOUBLE:
-			case FieldTypeManager.BASE_TYPE_FLOAT:
-			case FieldTypeManager.BASE_TYPE_INT:
-			case FieldTypeManager.BASE_TYPE_LONG:
-			case FieldTypeManager.BASE_TYPE_SHORT:
-				if(Double.parseDouble(obj.toString()) == 0 && !ValueUtil.isEmpty(property.getDefaultValue())) {
-					value = property.getDefaultValue();
-				} else {
-					value = obj.toString();
-				}
-				break;
-			case FieldTypeManager.BASE_TYPE_BOOLEAN:
-				if(Boolean.parseBoolean(obj.toString()) == false && !ValueUtil.isEmpty(property.getDefaultValue())) {
-					value = property.getDefaultValue();
-				} else {
-					value = obj.toString();
-				}
-				break;
-			case FieldTypeManager.BASE_TYPE_CHAR:
-			case FieldTypeManager.BASE_TYPE_STRING:
-			case FieldTypeManager.BASE_TYPE_DATE:
-				if(!ValueUtil.isEmpty(obj)) {
-					value = obj.toString();
-				} else {
-					if(!ValueUtil.isEmpty(property.getDefaultValue())) {
-						value = property.getDefaultValue();
-					}
-				}
-				break;
-		}
-		return value;
-	}
-	
-	/**
-	 * 构造删除语句
-	 * @param entity	要删除的实体
-	 * @return
-	 */
-	public static <T> BindSQL getDeleteSQL(T entity) {
-		EntityTable entityTable = EntityTableManager.getEntityTable(entity);
-		StringBuilder sqlBuilder = new StringBuilder();
-		StringBuilder argsBuilder = new StringBuilder();
-		
-		sqlBuilder.append("DELETE FROM ").append(entityTable.getTableName());
-		sqlBuilder.append(" WHERE ").append(entityTable.getPrimaryKey().getColumn()).append(" = ?");
-		if(ValueUtil.isEmpty(entityTable.getPrimaryKey().getValue(entity))) {
-			throw new IllegalArgumentException("未设置要删除实体的主键");
-		}
-		argsBuilder.append(entityTable.getPrimaryKey().getValue(entity));
-		
-		return new BindSQL(sqlBuilder.toString(), new String[]{argsBuilder.toString()});
-	}
-	
-	/**
-	 * 构造要删除的语句
-	 * @param mClass				要删除的实体类
-	 * @param primaryKeyValue		要删除的实体的主键,主键为空,则删除所有的数据
-	 * @return
-	 */
-	public static BindSQL getDeleteSQL(Class<?> mClass, String primaryKeyValue) {
-		EntityTable entityTable = EntityTableManager.getEntityTable(mClass);
-		StringBuilder sqlBuilder = new StringBuilder();
-		
-		sqlBuilder.append("DELETE FROM ").append(entityTable.getTableName());
-		String[] bindArgs = null;
-		if(!ValueUtil.isEmpty(primaryKeyValue)) {
-			sqlBuilder.append(" WHERE ").append(entityTable.getPrimaryKey().getColumn()).append(" = ?");
-			bindArgs = new String[]{primaryKeyValue};
-		}
-		
-		return new BindSQL(sqlBuilder.toString(), bindArgs);
-	}
-	
-	/**
-	 * 构造更新数据
-	 * @param entity
-	 * @return
-	 */
-	public static <T> BindSQL getUpdateSQL(T entity) {
-		EntityTable entityTable = EntityTableManager.getEntityTable(entity);
-		
-		if(ValueUtil.isEmpty(entityTable.getPrimaryKey().getValue(entity))) {
-			throw new IllegalArgumentException("未设置要删除实体的主键");
-		}
-		
-		StringBuilder sqlBuilder = new StringBuilder();
-		
-		sqlBuilder.append("UPDATE ");
-		sqlBuilder.append(entityTable.getTableName());
-		sqlBuilder.append(" SET ");
-		
-		Collection<Property> propertys = entityTable.getColumnMap().values();
-		Object[] bindArgs = new Object[propertys.size() + 1];
-		int i = 0;
-		
-		Iterator<Property> iterator = propertys.iterator();
-		Property property;
-		while(iterator.hasNext()) {
-			property = iterator.next();
-			
-			sqlBuilder.append(property.getColumn());
-			sqlBuilder.append(" = ?,");
-			bindArgs[i++] = property.getValue(entity);
-		}
-		sqlBuilder.deleteCharAt(sqlBuilder.length() - 1);
-		sqlBuilder.append(" WHERE ");
-		sqlBuilder.append(entityTable.getPrimaryKey().getColumn());
-		sqlBuilder.append(" = ?");
-		bindArgs[i++] = entityTable.getPrimaryKey().getValue(entity);
-		
-		return new BindSQL(sqlBuilder.toString(), bindArgs);
-	}
-	
-	/**
-	 * 查询指定实体的全部数据
-	 * @param mClass	要查询的实体类
-	 * @return
-	 */
-	public static String getQuerySQL(Class<?> mClass) {
-		String tableName = EntityTableManager.getEntityTable(mClass).getTableName();
-		return "SELECT * FROM " + tableName;
-	}
-	
-	/**
-	 * 查询指定实体的全部数据
-	 * @param mClass	要查询的实体类
-	 * @return
-	 */
-	public static BindSQL getQuerySQLById(Class<?> mClass, String primaryValue) {
-		EntityTable entityTable = EntityTableManager.getEntityTable(mClass);
-		StringBuilder sqlBuilder = new StringBuilder();
-		sqlBuilder.append("SELECT * FROM ");
-		sqlBuilder.append(entityTable.getTableName());
-		sqlBuilder.append(" WHERE ");
-		sqlBuilder.append(entityTable.getPrimaryKey().getColumn());
-		sqlBuilder.append(" = ?");
-		return new BindSQL(sqlBuilder.toString(), new String[]{primaryValue});
-	}
-	
-	/**
-	 * 查询指定实体的全部数据
-	 * @param mClass		要查询的实体类
-	 * @param whereClause	where子句
-	 * @param whereArgs		where字句绑定参数
-	 * @return
-	 */
-	public static BindSQL getQuerySQL(Class<?> mClass, String whereClause, String[] whereArgs) {
-		EntityTable entityTable = EntityTableManager.getEntityTable(mClass);
-		StringBuilder sqlBuilder = new StringBuilder();
-		sqlBuilder.append("SELECT * FROM ");
-		sqlBuilder.append(entityTable.getTableName());
-		sqlBuilder.append(" WHERE ");
-		sqlBuilder.append(whereClause);
-		return new BindSQL(sqlBuilder.toString(), whereArgs);
-	}
-	
-	/**
-	 * 查询实体类数据总条数
-	 * @param mClass
-	 * @return
-	 */
-	public static BindSQL getTotalSQL(Class<?> mClass, String whereClause, String[] whereArgs) {
-		String tableName = EntityTableManager.getEntityTable(mClass).getTableName();
-		String sql = "SELECT COUNT(*) TOTALCOUNT FROM " + tableName;
-		if(!ValueUtil.isEmpty(whereClause)) {
-			sql = sql + " WHERE " + whereClause;
-		}
-		return new BindSQL(sql, whereArgs);
-	}
-	
-	/**
-	 * 获取分页查询语句
-	 * @param mClass		要查询的实体类
-	 * @param curPage		查询的当前页码
-	 * @param pageSize		每页数据数
-	 * @return
-	 */
-	public static BindSQL getQueryPageSQL(Class<?> mClass, int curPage, int pageSize) {
-		EntityTable entityTable = EntityTableManager.getEntityTable(mClass);
-		StringBuilder sqlBuilder = new StringBuilder();
-		sqlBuilder.append("SELECT * FROM ");
-		sqlBuilder.append(entityTable.getTableName());
-		sqlBuilder.append(" LIMIT ? OFFSET ? * ? ");
-		String cur = String.valueOf(curPage - 1);
-		String size = String.valueOf(pageSize);
-		return new BindSQL(sqlBuilder.toString(), new String[]{size, cur, size});
-	}
-	
-	/**
-	 * 获取分页查询语句
-	 * @param mClass		要查询的实体类
-	 * @param whereClause	查询where子句
-	 * @param whereArgs		where子句参数
-	 * @param curPage		查询的当前页码
-	 * @param pageSize		每页数据数
-	 * @return
-	 */
-	public static BindSQL getQueryPageSQL(Class<?> mClass, String whereClause, String[] whereArgs, int curPage, int pageSize) {
-		EntityTable entityTable = EntityTableManager.getEntityTable(mClass);
-		StringBuilder sqlBuilder = new StringBuilder();
-		sqlBuilder.append("SELECT * FROM ");
-		sqlBuilder.append(entityTable.getTableName());
-		if(!ValueUtil.isEmpty(whereClause)) {
-			sqlBuilder.append(" WHERE ");
-			sqlBuilder.append(whereClause);
-		}
-		sqlBuilder.append(" LIMIT ? OFFSET ? * ? ");
-		String cur = String.valueOf(curPage - 1);
-		String size = String.valueOf(pageSize);
-		
-		int length = whereArgs == null ? 0 : whereArgs.length;
-		String[] newWhereArgs = new String[length + 3];
-		if(length > 0) {
-			System.arraycopy(whereArgs, 0, newWhereArgs, 0, whereArgs.length);
-		}
-		newWhereArgs[length] = size;
-		newWhereArgs[length + 1] = cur;
-		newWhereArgs[length + 2] = size;
-		return new BindSQL(sqlBuilder.toString(), newWhereArgs);
-	}
-}

+ 0 - 122
VideoSqlHelper/src/main/java/com/yc/database/sql/SQLiteContext.java

@@ -1,122 +0,0 @@
-package com.yc.database.sql;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.database.DatabaseErrorHandler;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-import android.os.Environment;
-
-import java.io.File;
-
-import com.yc.database.utils.ValueUtil;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 自定义数据库创建容器(设置数据库创建的自定义目录)
- *     revise:
- * </pre>
- */
-public class SQLiteContext extends ContextWrapper {
-
-	private SQLiteDBConfig config;
-	
-	public SQLiteContext(Context base, SQLiteDBConfig config) {
-		super(base);
-		this.config = config;
-	}
-	
-	@Override
-	public File getDatabasePath(String name) {
-		if (ValueUtil.isEmpty(config.getDbDirectoryPath())) {
-			return super.getDatabasePath(name);
-		}
-		String phoneRootPath = getPhoneRootPath();
-		String[] files = null;
-		if(phoneRootPath.startsWith("/")) {
-			files = phoneRootPath.substring(1).split("/");
-		} else {
-			files = phoneRootPath.split("/");
-		}
-		boolean flag = false;
-		for(int i = 0; i < files.length; i++) {
-			if(config.getDbDirectoryPath().contains(files[i])) {
-				flag = true;
-				break;
-			}
-		}
-		String dbPath = config.getDbDirectoryPath();
-		if(flag == false) {
-			dbPath = phoneRootPath + config.getDbDirectoryPath();
-		}
-		if(!config.getDbDirectoryPath().endsWith("/")) {
-			dbPath = dbPath + "/";
-		}
-		dbPath = dbPath + config.getDbName();
-		makeParentDir(dbPath);
-		return new File(dbPath);
-	}
-	
-	/**
-	 * 判断其父目录是否存在,不存在则创建
-	 * @param path
-	 */
-	private void makeParentDir(String path) {
-		String parentPath = getParentPath(path);
-		File file = new File(parentPath);
-		if(!file.exists()) {
-			makeParentDir(parentPath);
-			file.mkdir();
-		}
-	}
-	
-	/**
-	 * 获取父级目录
-	 * @param path
-	 * @return
-	 */
-	public static String getParentPath(String path) {
-		if (path.equals("/")) {
-			return path;
-		}
-		if (path.endsWith("/")) {
-			path = path.substring(0, path.length() - 1);
-		}
-		path = path.substring(0, path.lastIndexOf("/"));
-		return path.equals("") ? "/" : path;
-	}
-	
-	@Override
-	public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
-		if (ValueUtil.isEmpty(config.getDbDirectoryPath())) {
-			return super.openOrCreateDatabase(name, mode, factory);
-		}
-		return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
-	}
-	
-	@SuppressLint("NewApi")
-	@Override
-	public SQLiteDatabase openOrCreateDatabase(String name, int mode,
-                                               CursorFactory factory, DatabaseErrorHandler errorHandler) {
-		if (ValueUtil.isEmpty(config.getDbDirectoryPath())) {
-			return super.openOrCreateDatabase(name, mode, factory, errorHandler);
-		}
-		return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
-	}
-	
-	/**
-	 * 获取手机根目录
-	 * @return
-	 */
-	public String getPhoneRootPath() {
-		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
-			return Environment.getExternalStorageDirectory().getPath();
-		}
-		return Environment.getDataDirectory().getAbsolutePath();
-	}
-}

+ 0 - 462
VideoSqlHelper/src/main/java/com/yc/database/sql/SQLiteDB.java

@@ -1,462 +0,0 @@
-package com.yc.database.sql;
-
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-
-import java.sql.SQLException;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-import com.yc.database.bean.BindSQL;
-import com.yc.database.bean.EntityTable;
-import com.yc.database.bean.PrimaryKey;
-import com.yc.database.manager.EntityTableManager;
-import com.yc.database.manager.SQLExecuteManager;
-import com.yc.database.utils.CursorUtil;
-import com.yc.database.utils.ValueUtil;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 数据库操作类
- *     revise: 注:所有操作的实体必须实现无参构造函数
- * </pre>
- */
-public class SQLiteDB {
-
-	/**
-	 * 数据库配置
-	 */
-	private SQLiteDBConfig mConfig;
-	/**
-	 * 数据库操作类
-	 */
-	private SQLiteDatabase mDB;
-	/**
-	 * SQL语句执行管理器
-	 */
-	private SQLExecuteManager mSQLExecuteManager;
-	
-	public SQLExecuteManager getSQLExecuteManager() {
-		return mSQLExecuteManager;
-	}
-
-	public SQLiteDBConfig getConfig() {
-		return mConfig;
-	}
-	
-	public SQLiteDB(SQLiteDBConfig mConfig) {
-		super();
-		this.mConfig = mConfig;
-		createDB();
-	}
-	
-	/**
-	 * 创建数据库
-	 */
-	private void createDB() {
-		SQLiteHelper sqLiteHelper = new SQLiteHelper(mConfig);
-		mDB = sqLiteHelper.getWritableDatabase();
-		if(mDB == null) {
-			throw new NullPointerException("创建数据库对象失败");
-		}
-		mSQLExecuteManager = new SQLExecuteManager(mDB);
-	}
-	
-	/**
-	 * 关闭当前数据库
-	 */
-	public void close() {
-		this.mDB.close();
-	}
-	
-	/**
-	 * 判断当前数据库是否打开
-	 * @return
-	 */
-	public boolean isOpen() {
-		return this.mDB.isOpen();
-	}
-	
-	/**
-	 * 重新打开数据库
-	 */
-	public void reOpen() {
-		if(!isOpen()) {
-			createDB();
-		}
-	}
-
-	/**
-	 * 保存一个实体
-	 * 当主键设置为自增长时,手动设置的主键值不会起作用,同时会自动加保存之后最新的主键值填充到对象中,并返回
-	 * @param entity							对象
-	 * @return
-	 */
-	public <T> long save(T entity) {
-		if (entity==null){
-			return -1;
-		}
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, entity);
-		BindSQL insertSQL = SQLBuilder.getInsertSQL(entity);
-		long rowid = mSQLExecuteManager.insert(insertSQL);
-		EntityTable entityTable = EntityTableManager.getEntityTable(entity);
-		PrimaryKey key = entityTable.getPrimaryKey();
-		if(key.isAutoGenerate()) {
-			key.getField().setAccessible(true);
-			try {
-				key.setValue(entity, rowid);
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		}
-		return rowid;
-	}
-	
-	/**
-	 * 保存集合实体
-	 * @param collection						集合
-	 * @return									如果集合为空或者批量保存失败则返回-1,保存成功返回集合大小
-	 */
-	public <T> long save(Collection<T> collection) {
-		long rowId = -1;
-		if(ValueUtil.isEmpty(collection)) {
-			return rowId;
-		}
-		try {
-			mSQLExecuteManager.beginTransaction();
-			Iterator<T> iterator = collection.iterator();
-			while(iterator.hasNext()) {
-				rowId = save(iterator.next());
-				if(rowId == -1) {
-					throw new SQLException("删除实体失败");
-				}
-			}
-			mSQLExecuteManager.successTransaction();
-			rowId = collection.size();
-		} catch (SQLException e) {
-			e.printStackTrace();
-			rowId = -1;
-		} finally {
-			mSQLExecuteManager.endTransaction();
-		}
-		return rowId;
-	}
-	
-	/**
-	 * 删除指定实体(根据主键删除)
-	 * @param entity	要删除的实体
-	 */
-	public <T> void delete(T entity) {
-		if(ValueUtil.isEmpty(entity)) {
-			return ;
-		}
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, entity);
-		mSQLExecuteManager.delete(SQLBuilder.getDeleteSQL(entity));
-	}
-	
-	/**
-	 * 删除集合中的实体(有事务控制),每个实体根据主键删除
-	 * @param collection	要删除的实体集合
-	 */
-	public <T> void delete(Collection<T> collection) {
-		if(ValueUtil.isEmpty(collection)) {
-			return;
-		}
-		
-		try {
-			Iterator<T> iterator = collection.iterator();
-			this.mSQLExecuteManager.beginTransaction();
-			while(iterator.hasNext()) {
-				delete(iterator.next());
-			}
-			this.mSQLExecuteManager.successTransaction();
-		} finally {
-			this.mSQLExecuteManager.endTransaction();
-		}
-	}
-	
-	/**
-	 * 删除实体类中指定主键的实体
-	 * @param mClass				要删除的实体类
-	 * @param primaryKeyValue		要删除的实体的主键值
-	 */
-	public void delete(Class<?> mClass, String primaryKeyValue) {
-		if(ValueUtil.isEmpty(primaryKeyValue)) {
-			throw new IllegalArgumentException("要删除的实体的主键不能为空");
-		}
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		mSQLExecuteManager.delete(SQLBuilder.getDeleteSQL(mClass, primaryKeyValue));
-	}
-	
-	/**
-	 * 根据指定条件删除指定的实体
-	 * @param mClass		要删除的实体类
-	 * @param whereClause	where后面的条件句(delete from XXX where XXX),参数使用占位符
-	 * @param whereArgs		占位符参数
-	 */
-	public void delete(Class<?> mClass, String whereClause, String[] whereArgs) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		EntityTable entityTable = EntityTableManager.getEntityTable(mClass);
-		delete(entityTable.getTableName(), whereClause, whereArgs);
-	}
-	
-	/**
-	 * 根据where条件句删除相关实体
-	 * @param tableName			要删除的数据表
-	 * @param whereClause		where后面的条件句(delete from XXX where XXX),参数使用占位符
-	 * @param whereArgs			占位符参数
-	 * @return
-	 */
-	public void delete(String tableName, String whereClause, String[] whereArgs) {
-		mSQLExecuteManager.delete(tableName, whereClause, whereArgs);
-	}
-	
-	/**
-	 * 删除,表名不能使用占位符
-	 * @param sql			删除语句(参数使用占位符)
-	 * @param bindArgs		占位符参数
-	 */
-	public void delete(String sql, String[] bindArgs) {
-		mSQLExecuteManager.updateOrDelete(sql, bindArgs);
-	}
-	
-	/**
-	 * 删除实体类所有数据
-	 * @param mClass
-	 */
-	public void deleteAll(Class<?> mClass) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		mSQLExecuteManager.delete(SQLBuilder.getDeleteSQL(mClass, null));
-	}
-	
-	/**
-	 * 更新指定实体(必须设置主键,根据主键更新)
-	 * @param entity
-	 * @return
-	 */
-	public <T> void update(T entity) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, entity);
-		mSQLExecuteManager.update(SQLBuilder.getUpdateSQL(entity));
-	}
-	
-	/**
-	 * 更新指定集合数据(每个实体必须设置主键,根据主键更新)
-	 * @param collection
-	 */
-	public <T> void update(Collection<T> collection) {
-		if(ValueUtil.isEmpty(collection)) {
-			return;
-		}
-		try {
-			Iterator<T> iterator = collection.iterator();
-			this.mSQLExecuteManager.beginTransaction();
-			while(iterator.hasNext()) {
-				update(iterator.next());
-			}
-			this.mSQLExecuteManager.successTransaction();
-		} finally {
-			this.mSQLExecuteManager.endTransaction();
-		}
-	}
-	
-	/**
-	 * 更新
-	 * @param sql
-	 * @param bindArgs
-	 */
-	public void update(String sql, String[] bindArgs) {
-		mSQLExecuteManager.updateOrDelete(sql, bindArgs);
-	}
-	
-	/**
-	 * 查询实体类全部数据
-	 * @param mClass	要查询的实体类
-	 * @return			实体列表
-	 */
-	public <T> List<T> queryAll(Class<T> mClass) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		Cursor cursor = mSQLExecuteManager.query(SQLBuilder.getQuerySQL(mClass));
-		return CursorUtil.parseCursor(cursor, mClass);
-	}
-	
-	/**
-	 * 根据主键查询指定实体
-	 * @param primaryKeyValue
-	 * @return
-	 */
-	public <T> T query(Class<T> mClass, String primaryKeyValue) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		Cursor cursor = mSQLExecuteManager.query(SQLBuilder.getQuerySQLById(mClass, primaryKeyValue));
-		return CursorUtil.parseCursorOneResult(cursor, mClass);
-	}
-	
-	/**
-	 * 根据条件查询实体类
-	 * @param mClass		查询的实体类
-	 * @param whereClause	查询条件where子句
-	 * @param whereArgs		where子句参数
-	 * @return
-	 */
-	public <T> List<T> query(Class<T> mClass, String whereClause, String[] whereArgs) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		Cursor cursor = mSQLExecuteManager.query(SQLBuilder.getQuerySQL(mClass, whereClause, whereArgs));
-		return CursorUtil.parseCursor(cursor, mClass);
-	}
-	
-	/**
-	 * 根据条件查询符合条件的第一条实体类
-	 * @param mClass		查询的实体类
-	 * @param whereClause	查询条件where子句
-	 * @param whereArgs		where子句参数
-	 * @return	存在返回第一条实体类,不存在返回null
-	 */
-	public <T> T queryOne(Class<T> mClass, String whereClause, String[] whereArgs) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		Cursor cursor = mSQLExecuteManager.query(SQLBuilder.getQuerySQL(mClass, whereClause, whereArgs));
-		List<T> list = CursorUtil.parseCursor(cursor, mClass);
-		return list.size() > 0 ? list.get(0) : null;
-	}
-	
-	/**
-	 * 根据SQL语句查询实体类
-	 * @param mClass		查询的实体类
-	 * @param sql			查询条件where子句
-	 * @param whereArgs		where子句参数
-	 * @return
-	 */
-	public <T> List<T> queryBySQL(Class<T> mClass, String sql, String[] whereArgs) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		Cursor cursor = mSQLExecuteManager.query(new BindSQL(sql, whereArgs));
-		return CursorUtil.parseCursor(cursor, mClass);
-	}
-	
-	/**
-	 * 分页查询
-	 * @param mClass	查询实体类
-	 * @param curPage	当前页码
-	 * @param pageSize	每页数据条数
-	 * @return
-	 */
-	public <T> List<T> queryPage(Class<T> mClass, int curPage, int pageSize) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		Cursor cursor = mSQLExecuteManager.query(SQLBuilder.getQueryPageSQL(mClass, curPage, pageSize));
-		return CursorUtil.parseCursor(cursor, mClass);
-	}
-	
-	/**
-	 * 分页查询
-	 * @param mClass	查询实体类,返回实体类型
-	 * @param curPage	当前页码
-	 * @param pageSize	每页数据条数
-	 * @return
-	 */
-	/**
-	 * 分页查询
-	 * @param mClass				查询实体类,返回实体类型
-	 * @param whereClause			查询语句
-	 * @param whereArgs				查询语句中的参数
-	 * @param curPage				当前页码
-	 * @param pageSize				每页数据条数
-	 * @return
-	 */
-	public <T> List<T> queryPage(Class<T> mClass, String whereClause, String[] whereArgs, int curPage, int pageSize) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		Cursor cursor = mSQLExecuteManager.query(SQLBuilder.getQueryPageSQL(mClass, whereClause, whereArgs, curPage, pageSize));
-		return CursorUtil.parseCursor(cursor, mClass);
-	}
-	
-	/**
-	 * 查询实体类的总数据条数
-	 * @param mClass	查询实体类
-	 * @return
-	 */
-	public long queryTotal(Class<?> mClass) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		return queryTotal(mClass, null, null);
-	}
-	
-	/**
-	 * 查询实体类指定条件下的数据总数
-	 * @param mClass			查询实体类
-	 * @param whereClause		查询条件
-	 * @param whereArgs			查询条件中的占位符参数
-	 * @return
-	 */
-	public long queryTotal(Class<?> mClass, String whereClause, String[] whereArgs) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		Cursor cursor = mSQLExecuteManager.query(SQLBuilder.getTotalSQL(mClass, whereClause, whereArgs));
-		return CursorUtil.parseCursorTotal(cursor);
-	}
-	
-	/**
-	 * 根据SQL语句查询数据条数(解析结果为第一列值)
-	 * @param sql			查询SQL
-	 * @param bindArgs		占位符参数值
-	 * @return
-	 */
-	public long queryTotal(String sql, String[] bindArgs) {
-		Cursor cursor = mSQLExecuteManager.query(sql, bindArgs);
-		return CursorUtil.parseCursorTotal(cursor);
-	}
-	
-	/**
-	 * 查询指定实体类中是否存在指定主键值的实体对象
-	 * @param mClass			查询实体类
-	 * @param primaryKeyValue	实体主键值
-	 * @return	存在返回true,不存在返回false
-	 */
-	public boolean queryIfExist(Class<?> mClass, String primaryKeyValue) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		EntityTable entityTable = EntityTableManager.getEntityTable(mClass);
-		String whereClause = entityTable.getPrimaryKey().getColumn() + "=?";
-		String[] whereArgs = {primaryKeyValue};
-		long count = queryTotal(mClass, whereClause, whereArgs);
-		return count > 0 ? true : false;
-	}
-	
-	/**
-	 * 根据查询条件判断是否存在指定的数据
-	 * @param mClass		查询实体类
-	 * @param whereClause	查询条件
-	 * @param whereArgs		查询参数
-	 * @return				存在返回true,不存在返回false
-	 */
-	public boolean queryIfExist(Class<?> mClass, String whereClause, String[] whereArgs) {
-		long count = queryTotal(mClass, whereClause, whereArgs);
-		return count > 0 ? true : false;
-	}
-	
-	/**
-	 * 根据SQL语句查询
-	 * @param sql
-	 * @param bindArgs
-	 * @return
-	 */
-	public Cursor query(String sql, String[] bindArgs) {
-		return mSQLExecuteManager.query(sql, bindArgs);
-	}
-	
-
-	/**
-	 * 根据查询条件查询指定实体的指定字段信息
-	 * @param mClass		要查询的实体
-	 * @param selectCols	要查询的数据库字段,多个查询字段间使用逗号隔开
-	 * @param whereClause	查询条件(无查询条件时,可以传值null)
-	 * @param whereArgs		查询条件参数值
-	 * @return
-	 */
-	public <T> Cursor query(Class<T> mClass, String selectCols, String whereClause, String[] whereArgs) {
-		EntityTableManager.checkOrCreateTable(mSQLExecuteManager, mClass);
-		String tableName = EntityTableManager.getEntityTable(mClass).getTableName();
-		String sql = "SELECT " + selectCols + " FROM " + tableName;
-		if(!ValueUtil.isEmpty(whereClause)) {
-			sql += " WHERE " + whereClause;
-		}
-		return query(sql, whereArgs);
-	}
-}

+ 0 - 119
VideoSqlHelper/src/main/java/com/yc/database/sql/SQLiteDBConfig.java

@@ -1,119 +0,0 @@
-package com.yc.database.sql;
-
-import android.content.Context;
-
-import com.yc.database.listener.InterDBListener;
-import com.yc.database.listener.SimpleDBListener;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 数据库相关配置
- *     revise:
- * </pre>
- */
-public final class SQLiteDBConfig {
-	/**
-	 * 数据文件的默认存储目录(不包含SDCard目录部分,自动添加),可手动设置多个数据库的默认目录
-	 */
-	public static String DEFAULT_DB_DIRECTORY_PATH = "/TigerDB/";
-	/**
-	 * 默认数据库名,可修改
-	 */
-	public static String DEFAULT_DB_NAME = "Tiger.db";
-	/**
-	 * 默认版本号,可修改
-	 */
-	public static int DEFAULT_VERSION = 1;
-	/**
-	 * 数据库上下文
-	 */
-	private Context mContext;
-	/**
-	 * 当前数据库文件所在目录路径(绝对路径)
-	 */
-	private String mDbDirectoryPath = DEFAULT_DB_DIRECTORY_PATH;
-	/**
-	 * 数据库文件名,默认为:Tiger.db
-	 */
-	private String mDbName = DEFAULT_DB_NAME;
-	/**
-	 * 当前数据库版本号
-	 */
-	private int mVersion = DEFAULT_VERSION;
-	/**
-	 * 数据库监听
-	 */
-	private InterDBListener mDbListener;
-	
-	public SQLiteDBConfig(Context context) {
-		this.mContext = context;
-		mDbListener = new SimpleDBListener();
-	}
-	
-	public SQLiteDBConfig(Context context, String dbName) {
-		super();
-		this.mContext = context;
-		this.mDbName = dbName;
-		mDbListener = new SimpleDBListener();
-	}
-	
-	public SQLiteDBConfig(Context context, String dbDirectoryPath, String dbName) {
-		super();
-		this.mContext = context;
-		this.mDbDirectoryPath = dbDirectoryPath;
-		this.mDbName = dbName;
-		mDbListener = new SimpleDBListener();
-	}
-
-	/**
-	 * 获取数据库所在的上下文
-	 * @return
-	 */
-	public Context getContext() {
-		return mContext;
-	}
-	
-	/**
-	 * 设置数据库所在的上下文
-	 * @param mContext
-	 */
-	public void setContext(Context mContext) {
-		this.mContext = mContext;
-	}
-	
-	public String getDbDirectoryPath() {
-		return mDbDirectoryPath;
-	}
-	
-	public void setDbDirectoryPath(String mDbDirectoryPath) {
-		this.mDbDirectoryPath = mDbDirectoryPath;
-	}
-	
-	public String getDbName() {
-		return mDbName;
-	}
-	
-	public void setDbName(String mDbName) {
-		this.mDbName = mDbName;
-	}
-	
-	public int getVersion() {
-		return mVersion;
-	}
-	
-	public void setVersion(int mVersion) {
-		this.mVersion = mVersion;
-	}
-
-	public InterDBListener getDbListener() {
-		return mDbListener;
-	}
-
-	public void setDbListener(InterDBListener mDbListener) {
-		this.mDbListener = mDbListener;
-	}
-}

+ 0 - 73
VideoSqlHelper/src/main/java/com/yc/database/sql/SQLiteDBFactory.java

@@ -1,73 +0,0 @@
-package com.yc.database.sql;
-
-import android.content.Context;
-
-import java.util.HashMap;
-
-import com.yc.database.utils.ValueUtil;
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 数据库管理工厂
- *     revise:
- * </pre>
- */
-public class SQLiteDBFactory {
-	/**
-	 * 多个数据库集合对象<dbName, {@link}SQLiteDB>
-	 */
-	private static HashMap<String, SQLiteDB> dbMap = new HashMap<String, SQLiteDB>();
-	
-	/**
-	 * 生成一个名为dnName的数据库,目录为默认目录(参考SQLiteDBConfig里面的目录设置)}
-	 * @param context
-	 * @param dbName		要生成的数据库名称
-	 * @return
-	 */
-	public static SQLiteDB createSQLiteDB(Context context, String dbName) {
-		SQLiteDBConfig confing = new SQLiteDBConfig(context);
-		confing.setDbName(dbName);
-		return createSQLiteDB(confing);
-	}
-	
-	/**
-	 * 在默认目录下生成默认名称的数据库
-	 * @param context
-	 * @return
-	 */
-	public static SQLiteDB createSQLiteDB(Context context) {
-		return createSQLiteDB(new SQLiteDBConfig(context));
-	}
-	
-	/**
-	 * 根据自定义配置生成数据库
-	 * @param config
-	 * @return
-	 */
-	public static SQLiteDB createSQLiteDB(SQLiteDBConfig config) {
-		if(config.getVersion() < 0) {
-			config.setVersion(SQLiteDBConfig.DEFAULT_VERSION);
-		}
-		if(ValueUtil.isEmpty(config.getDbName())) {
-			config.setDbName(SQLiteDBConfig.DEFAULT_DB_NAME);
-		}
-		if(ValueUtil.isEmpty(config.getDbDirectoryPath())) {
-			config.setDbDirectoryPath(SQLiteDBConfig.DEFAULT_DB_DIRECTORY_PATH);
-		}
-		if(!dbMap.containsKey(config.getDbName())) {
-			synchronized (SQLiteDBFactory.class) {
-				if(!dbMap.containsKey(config.getDbName())) {
-					dbMap.put(config.getDbName(), new SQLiteDB(config));
-				}
-			}
-		}
-		SQLiteDB db = dbMap.get(config.getDbName());
-		if(!db.isOpen()) {
-			db.reOpen();
-		}
-		return dbMap.get(config.getDbName());
-	}
-}

+ 0 - 136
VideoSqlHelper/src/main/java/com/yc/database/sql/SQLiteHelper.java

@@ -1,136 +0,0 @@
-package com.yc.database.sql;
-
-import android.content.Context;
-import android.database.DatabaseErrorHandler;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 继承自SQLiteOpenHelper,扩展实现自定义db的生成路径
- *     revise: 用作sql存取数据的基础功能库,暂时不想依赖greenDao(插件+100kb库)或者realm(2M)数据库【对于视频播放器库,避免组件体积过大】
- * </pre>
- */
-public class SQLiteHelper extends SQLiteOpenHelper {
-
-	/**
-	 * 默认db,解决在onCreate,onUpgrade中执行其他操作数据库操作时出现的异常
-	 * (java.lang.IllegalStateException: getDatabase called recursively)
-	 */
-	private SQLiteDatabase mDefaultSQLiteDatabase = null;
-	/**
-	 * 数据库配置
-	 */
-	private SQLiteDBConfig mConfig;
-	
-	public SQLiteHelper(SQLiteDBConfig config) {
-		this(new SQLiteContext(config.getContext(), config), config.getDbName(), null, config.getVersion());
-		this.mConfig = config;
-	}
-
-	/**
-	 * 创建数据库对象
-	 * @param context							上下文
-	 * @param name								名称
-	 * @param factory							factory
-	 * @param version							版本号
-	 */
-	public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
-		// 参数说明
-		// context:上下文对象
-		// name:数据库名称
-		// param:一个可选的游标工厂(通常是 Null)
-		// version:当前数据库的版本,值必须是整数并且是递增的状态
-
-		// 必须通过super调用父类的构造函数
-		super(context, name, factory, version);
-	}
-
-	/**
-	 * 创建数据库对象
-	 * @param context							上下文
-	 * @param name								名称
-	 * @param factory							factory
-	 * @param version							版本号
-	 * @param errorHandler						errorHandler
-	 */
-	public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
-						int version, DatabaseErrorHandler errorHandler) {
-		super(context, name, factory, version, errorHandler);
-	}
-
-	/**
-	 * 创建 or 打开 可读/写的数据库(通过 返回的SQLiteDatabase对象 进行操作)
-	 * 对于操作 = “增、删、改(更新)”,需获得 可"读 / 写"的权限:getWritableDatabase()
-	 * @return									SQLiteDatabase对象
-	 */
-	@Override
-	public SQLiteDatabase getWritableDatabase() {
-		if(mDefaultSQLiteDatabase != null) {
-			return mDefaultSQLiteDatabase;
-		}
-		return super.getWritableDatabase();
-	}
-
-	/**
-	 * 创建 or 打开 可读的数据库(通过 返回的SQLiteDatabase对象 进行操作
-	 * 对于操作 = “查询”,需获得 可"读 "的权限getReadableDatabase()
-	 * @return
-	 */
-	@Override
-	public SQLiteDatabase getReadableDatabase() {
-		return super.getReadableDatabase();
-	}
-
-	/**
-	 * 创建数据库调用该方法
-	 * 数据库第1次创建时 则会调用,即 第1次调用 getWritableDatabase() / getReadableDatabase()时调用
-	 * 调用时刻:当数据库第1次创建时调用
-	 * 作用:创建数据库 表 & 初始化数据
-	 * SQLite数据库创建支持的数据类型: 整型数据、字符串类型、日期类型、二进制
-	 * @param db									db数据库
-	 */
-	@Override
-	public void onCreate(SQLiteDatabase db) {
-		this.mDefaultSQLiteDatabase = db;
-		if(mConfig.getDbListener() != null) {
-			mConfig.getDbListener().onDbCreateHandler(db);
-		}
-	}
-
-	/**
-	 * 关闭数据库
-	 */
-	@Override
-	public synchronized void close() {
-		super.close();
-	}
-
-	/**
-	 * 更新数据库
-	 * 数据库升级时自动调用
-	 * 调用时刻:当数据库升级时则自动调用(即 数据库版本 发生变化时)
-	 * 作用:更新数据库表结构
-	 * 注:创建SQLiteOpenHelper子类对象时,必须传入一个version参数,该参数 = 当前数据库版本, 若该版本高于之前版本, 就调用onUpgrade()
-	 * @param db									db数据库
-	 * @param oldVersion							老版本
-	 * @param newVersion							新版本
-	 */
-	@Override
-	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-		this.mDefaultSQLiteDatabase = db;
-		if(mConfig.getDbListener() != null) {
-			mConfig.getDbListener().onUpgradeHandler(db, oldVersion, newVersion);
-		}
-	}
-
-	@Override
-	public String getDatabaseName() {
-		//获取数据库名称
-		return super.getDatabaseName();
-	}
-}

+ 0 - 152
VideoSqlHelper/src/main/java/com/yc/database/utils/CursorUtil.java

@@ -1,152 +0,0 @@
-package com.yc.database.utils;
-
-import android.database.Cursor;
-
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-
-import com.yc.database.bean.EntityTable;
-import com.yc.database.bean.Property;
-import com.yc.database.manager.EntityTableManager;
-
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : Cursor工具类
- *     revise:
- * </pre>
- */
-public class CursorUtil {
-	/**
-	 * 判断Cursor是否正确,即存在结果集
-	 * @param cursor
-	 * @return
-	 */
-	public static boolean isCursorRight(Cursor cursor) {
-		if(cursor == null || cursor.getCount() <= 0) {
-			return false;
-		}
-		return true;
-	}
-	
-	/**
-	 * 关闭某个Cursor
-	 * @param cursor
-	 */
-	public static void closeCursor(Cursor cursor) {
-		if(cursor != null && !cursor.isClosed()) {
-			cursor.close();
-		}
-		cursor = null;
-	}
-
-	/**
-	 * 解析查询游标结果集为指定实体类列表(解析完成之后会关闭游标)
-	 * @param cursor	游标结果集
-	 * @param mClass	查询实体类
-	 * @return
-	 */
-	public static <T> List<T> parseCursor(Cursor cursor, Class<T> mClass) {
-		List<T> list = new ArrayList<T>();
-		if(!isCursorRight(cursor)) {
-			return list;
-		}
-		long count = cursor.getCount();
-		EntityTable entityTable = EntityTableManager.getEntityTable(mClass);
-		LinkedHashMap<String, Property> propertys = entityTable.getColumnMap();
-		Property primaryKey = entityTable.getPrimaryKey();
-		
-		try { 
-			for(int i = 0; i < count; i++) {
-				cursor.moveToPosition(i);
-				T entity = (T) mClass.newInstance();
-				primaryKey.setValue(entity, cursor);
-				for(String key : propertys.keySet()) {
-					Property property = propertys.get(key);
-					if (property!=null){
-						property.setValue(entity, cursor);
-					}
-				}
-				list.add(entity);
-			}
-		} catch (Exception e) {
-			DBLog.debug("解析查询结果集出错", e);
-			throw new IllegalArgumentException(e);
-		} finally {
-			closeCursor(cursor);
-		}
-		return list;
-	}
-	
-	/**
-	 * 解析查询游标结果集第一条记录(解析完成之后会关闭游标)
-	 * Author: hyl
-	 * Time: 2015-8-21上午10:30:14
-	 * @param cursor	游标结果集
-	 * @param mClass	查询实体类
-	 * @return
-	 */
-	public static <T> T parseCursorOneResult(Cursor cursor, Class<T> mClass) {
-		if(!isCursorRight(cursor)) {
-			return null;
-		}
-		EntityTable entityTable = EntityTableManager.getEntityTable(mClass);
-		LinkedHashMap<String, Property> propertys = entityTable.getColumnMap();
-		Property primaryKey = entityTable.getPrimaryKey();
-		T entity = null;
-		try { 
-			entity = (T) mClass.newInstance();
-			cursor.moveToFirst();
-			primaryKey.setValue(entity, cursor);
-			for(String key : propertys.keySet()) {
-				propertys.get(key).setValue(entity, cursor);
-			}
-		} catch (Exception e) {
-			entity = null;
-			DBLog.debug("解析查询结果集出错", e);
-			throw new IllegalArgumentException(e);
-		} finally {
-			closeCursor(cursor);
-		}
-		return entity;
-	}
-
-	/**
-	 * 查询实体类总数解析
-	 * @param cursor
-	 * @return
-	 */
-	public static long parseCursorTotal(Cursor cursor) {
-		String value = parseCursorFirstCol(cursor);
-		if(value == null) {
-			value = "0";
-		}
-		return Long.parseLong(value);
-	}
-	
-	/**
-	 * 解析游标结果的第一条记录的第一列的字段值
-	 * @param cursor
-	 * @return
-	 */
-	public static String parseCursorFirstCol(Cursor cursor) {
-		String value = null;
-		if(!isCursorRight(cursor)) {
-			return value;
-		}
-		try {
-			cursor.moveToFirst();
-			value = cursor.getString(0);
-		} catch (Exception e) {
-			value = null;
-			DBLog.debug("解析实体类第一列结果出错", e);
-		} finally {
-			closeCursor(cursor);
-		}
-		return value;
-	}
-}

+ 0 - 81
VideoSqlHelper/src/main/java/com/yc/database/utils/DBLog.java

@@ -1,81 +0,0 @@
-package com.yc.database.utils;
-
-import android.util.Log;
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 日志工具类
- *     revise:
- * </pre>
- */
-public class DBLog {
-	/**
-	 * 日志标签
-	 */
-	private static final String TAG = "YCSqlLog";
-	/**
-	 * 是否调试模式
-	 */
-	private static boolean IS_DEBUG = true;
-	
-	public static boolean isDebug() {
-		return IS_DEBUG;
-	}
-	
-	/**
-	 * 是否开启调试模式
-	 * @param enable
-	 */
-	public static final void debugEnable(boolean enable) {
-		IS_DEBUG = enable;
-	}
-	
-	public static final void debug(Object msg) {
-		debug(msg.toString());
-	}
-	
-	public static final void debug(String msg) {
-		if(IS_DEBUG) {
-			Log.i(TAG, msg);
-		}
-	}
-	
-	public static final void debug(String msg, Throwable e) {
-		if(IS_DEBUG) {
-			Log.i(TAG, msg, e);
-		}
-	}
-	
-	public static final void debugSql(String sql, Object[] params) {
-		if(IS_DEBUG) {
-			StringBuilder sb = new StringBuilder();
-			for(int i = 0; i < params.length; i++) {
-				if(sb.length() <= 0) {
-					sb.append(",");
-				}
-				sb.append(params.toString());
-			}
-			Log.i(TAG, "{SQL:" + sql + ",PARAMS:" + sb.toString() + "}");
-		}
-	}
-	
-	public static final void debugSql(String sql, Object[] params, Throwable e) {
-		if(IS_DEBUG) {
-			StringBuilder sb = new StringBuilder();
-			for(int i = 0; i < params.length; i++) {
-				if(sb.length() <= 0) {
-					sb.append(",");
-				}
-				sb.append(params.toString());
-			}
-			Log.i(TAG, "{SQL:" + sql + ",PARAMS:" + sb.toString() + "}", e);
-		}
-	}
-	
-	public static final void debug(String format, Object...objects) {
-		debug(String.format(format, objects));
-	}
-}

+ 0 - 407
VideoSqlHelper/src/main/java/com/yc/database/utils/DateUtil.java

@@ -1,407 +0,0 @@
-package com.yc.database.utils;
-
-import android.annotation.SuppressLint;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : 时间工具类
- *     revise:
- * </pre>
- */
-@SuppressLint("SimpleDateFormat")
-public class DateUtil {
-
-	private static final SimpleDateFormat datetimeFormat = new SimpleDateFormat(
-            "yyyy-MM-dd HH:mm:ss");  
-    private static final SimpleDateFormat dateFormat = new SimpleDateFormat(
-            "yyyy-MM-dd");  
-    private static final SimpleDateFormat timeFormat = new SimpleDateFormat(
-            "HH:mm:ss");  
-  
-    /** 
-     * 获得当前日期时间 
-     * <p> 
-     * 日期时间格式yyyy-MM-dd HH:mm:ss 
-     *  
-     * @return 
-     */  
-    public static String currentDatetime() {
-        return datetimeFormat.format(now());  
-    }  
-  
-    /** 
-     * 格式化日期时间 
-     * <p> 
-     * 日期时间格式yyyy-MM-dd HH:mm:ss 
-     *  
-     * @return 
-     */  
-    public static String formatDatetime(Date date) {
-        return datetimeFormat.format(date);  
-    }  
-  
-    /** 
-     * 格式化日期时间 
-     *  
-     * @param date 
-     * @param pattern 
-     *            格式化模式,详见{@link SimpleDateFormat}构造器
-     *            <code>SimpleDateFormat(String pattern)</code> 
-     * @return 
-     */  
-    public static String formatDatetime(Date date, String pattern) {
-        SimpleDateFormat customFormat = (SimpleDateFormat) datetimeFormat
-                .clone();  
-        customFormat.applyPattern(pattern);  
-        return customFormat.format(date);  
-    }  
-  
-    /** 
-     * 获得当前日期 
-     * <p> 
-     * 日期格式yyyy-MM-dd 
-     *  
-     * @return 
-     */  
-    public static String currentDate() {
-        return dateFormat.format(now());  
-    }  
-  
-    /** 
-     * 格式化日期 
-     * <p> 
-     * 日期格式yyyy-MM-dd 
-     *  
-     * @return 
-     */  
-    public static String formatDate(Date date) {
-        return dateFormat.format(date);  
-    }  
-  
-    /** 
-     * 获得当前时间 
-     * <p> 
-     * 时间格式HH:mm:ss 
-     *  
-     * @return 
-     */  
-    public static String currentTime() {
-        return timeFormat.format(now());  
-    }  
-  
-    /** 
-     * 格式化时间 
-     * <p> 
-     * 时间格式HH:mm:ss 
-     *  
-     * @return 
-     */  
-    public static String formatTime(Date date) {
-        return timeFormat.format(date);  
-    }  
-  
-    /** 
-     * 获得当前时间的<code>java.util.Date</code>对象 
-     *  
-     * @return 
-     */  
-    public static Date now() {
-        return new Date();
-    }  
-  
-    public static Calendar calendar() {
-        Calendar cal = GregorianCalendar.getInstance(Locale.CHINESE);
-        cal.setFirstDayOfWeek(Calendar.MONDAY);
-        return cal;  
-    }  
-  
-    /** 
-     * 获得当前时间的毫秒数 
-     * <p> 
-     * 详见{@link System#currentTimeMillis()}
-     *  
-     * @return 
-     */  
-    public static long millis() {  
-        return System.currentTimeMillis();
-    }  
-  
-    
-    
-    /** 
-     *  
-     * 获得当前Chinese月份 
-     *  
-     * @return 
-     */  
-    public static int month() {  
-        return calendar().get(Calendar.MONTH) + 1;
-    }  
-    
-    /** 
-     *  
-     * 获得当前Chinese年份 
-     *  
-     * @return 
-     */ 
-    public static int year() {
-    	return calendar().get(Calendar.YEAR);
-    }
-  
-    /** 
-     * 获得月份中的第几天 
-     *  
-     * @return 
-     */  
-    public static int dayOfMonth() {  
-        return calendar().get(Calendar.DAY_OF_MONTH);
-    }  
-  
-    /** 
-     * 今天是星期的第几天 
-     *  
-     * @return 
-     */  
-    public static int dayOfWeek() {  
-        return calendar().get(Calendar.DAY_OF_WEEK);
-    }  
-  
-    /** 
-     * 今天是年中的第几天 
-     *  
-     * @return 
-     */  
-    public static int dayOfYear() {  
-        return calendar().get(Calendar.DAY_OF_YEAR);
-    }  
-  
-    /** 
-     *判断原日期是否在目标日期之前 
-     *  
-     * @param src 
-     * @param dst 
-     * @return 
-     */  
-    public static boolean isBefore(Date src, Date dst) {
-        return src.before(dst);  
-    }  
-  
-    /** 
-     *判断原日期是否在目标日期之后 
-     *  
-     * @param src 
-     * @param dst 
-     * @return 
-     */  
-    public static boolean isAfter(Date src, Date dst) {
-        return src.after(dst);  
-    }  
-  
-    /** 
-     *判断两日期是否相同 
-     *  
-     * @param date1 
-     * @param date2 
-     * @return 
-     */  
-    public static boolean isEqual(Date date1, Date date2) {
-        return date1.compareTo(date2) == 0;  
-    }  
-  
-    /** 
-     * 判断某个日期是否在某个日期范围 
-     *  
-     * @param beginDate 
-     *            日期范围开始 
-     * @param endDate 
-     *            日期范围结束 
-     * @param src 
-     *            需要判断的日期 
-     * @return 
-     */  
-    public static boolean between(Date beginDate, Date endDate, Date src) {
-        return beginDate.before(src) && endDate.after(src);  
-    }  
-  
-    /** 
-     * 获得当前月的最后一天 
-     * <p> 
-     * HH:mm:ss为0,毫秒为999 
-     *  
-     * @return 
-     */  
-    public static Date lastDayOfMonth() {
-        Calendar cal = calendar();
-        cal.set(Calendar.DAY_OF_MONTH, 0); // M月置零
-        cal.set(Calendar.HOUR_OF_DAY, 0);// H置零
-        cal.set(Calendar.MINUTE, 0);// m置零
-        cal.set(Calendar.SECOND, 0);// s置零
-        cal.set(Calendar.MILLISECOND, 0);// S置零
-        cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1);// 月份+1
-        cal.set(Calendar.MILLISECOND, -1);// 毫秒-1
-        return cal.getTime();  
-    }  
-  
-    /** 
-     * 获得当前月的第一天 
-     * <p> 
-     * HH:mm:ss SS为零 
-     *  
-     * @return 
-     */  
-    public static Date firstDayOfMonth() {
-        Calendar cal = calendar();
-        cal.set(Calendar.DAY_OF_MONTH, 1); // M月置1
-        cal.set(Calendar.HOUR_OF_DAY, 0);// H置零
-        cal.set(Calendar.MINUTE, 0);// m置零
-        cal.set(Calendar.SECOND, 0);// s置零
-        cal.set(Calendar.MILLISECOND, 0);// S置零
-        return cal.getTime();  
-    }  
-  
-    private static Date weekDay(int week) {
-        Calendar cal = calendar();
-        cal.set(Calendar.DAY_OF_WEEK, week);
-        return cal.getTime();  
-    }  
-  
-    /** 
-     * 获得周五日期 
-     * <p> 
-     * 注:日历工厂方法{@link #calendar()}设置类每个星期的第一天为Monday,US等每星期第一天为sunday 
-     *  
-     * @return 
-     */  
-    public static Date friday() {
-        return weekDay(Calendar.FRIDAY);
-    }  
-  
-    /** 
-     * 获得周六日期 
-     * <p> 
-     * 注:日历工厂方法{@link #calendar()}设置类每个星期的第一天为Monday,US等每星期第一天为sunday 
-     *  
-     * @return 
-     */  
-    public static Date saturday() {
-        return weekDay(Calendar.SATURDAY);
-    }  
-  
-    /** 
-     * 获得周日日期 
-     * <p> 
-     * 注:日历工厂方法{@link #calendar()}设置类每个星期的第一天为Monday,US等每星期第一天为sunday 
-     *  
-     * @return 
-     */  
-    public static Date sunday() {
-        return weekDay(Calendar.SUNDAY);
-    }  
-  
-    /** 
-     * 将字符串日期时间转换成java.util.Date类型 
-     * <p> 
-     * 日期时间格式yyyy-MM-dd HH:mm:ss 
-     *  
-     * @param datetime 
-     * @return 
-     */  
-    public static Date parseDatetime(String datetime) throws ParseException {
-        return datetimeFormat.parse(datetime);  
-    }  
-  
-    /** 
-     * 将字符串日期转换成java.util.Date类型 
-     *<p> 
-     * 日期时间格式yyyy-MM-dd 
-     *  
-     * @param date 
-     * @return 
-     * @throws ParseException
-     */  
-    public static Date parseDate(String date) throws ParseException {
-        return dateFormat.parse(date);  
-    }  
-  
-    /** 
-     * 将字符串日期转换成java.util.Date类型 
-     *<p> 
-     * 时间格式 HH:mm:ss 
-     *  
-     * @param time 
-     * @return 
-     * @throws ParseException
-     */  
-    public static Date parseTime(String time) throws ParseException {
-        return timeFormat.parse(time);  
-    }  
-  
-    /** 
-     * 根据自定义pattern将字符串日期转换成java.util.Date类型 
-     *  
-     * @param datetime 
-     * @param pattern 
-     * @return 
-     * @throws ParseException
-     */  
-    public static Date parseDatetime(String datetime, String pattern)
-            throws ParseException {
-        SimpleDateFormat format = (SimpleDateFormat) datetimeFormat.clone();
-        format.applyPattern(pattern);  
-        return format.parse(datetime);  
-    }
-    
-    /** 
-	 * 得到几天前的时间 
-	 * @param d 
-	 * @param day 
-	 * @return 
-	 */  
-	public static Date getDateBefore(Date d, int day){
-		 Calendar now = Calendar.getInstance();
-		 now.setTime(d);  
-		 now.set(Calendar.DATE, now.get(Calendar.DATE) - day);
-		 return now.getTime();  
-	}
-	
-	/**
-	 * 描述:得到几天前的时间 
-	 * @author:huyongli
-	 * @time:2014-7-31下午05:04:43
-	 * @param date		时间字符串
-	 * @param pattern	该时间字符串的格式
-	 * @param day		天数
-	 * @return
-	 * @throws ParseException
-	 */
-	public static Date getDateBefore(String date, String pattern, int day) throws ParseException {
-		Date d = DateUtil.parseDatetime(date, pattern);
-		Calendar now = Calendar.getInstance();
-		now.setTime(d);  
-		now.set(Calendar.DATE, now.get(Calendar.DATE) - day);
-		return now.getTime();  
-	}
-	
-	/** 
-	   * 得到几天后的时间 
-	   * @param d 
-	   * @param day 
-	   * @return 
-	   */  
-	  public static Date getDateAfter(Date d, int day){
-		   Calendar now = Calendar.getInstance();
-		   now.setTime(d);  
-		   now.set(Calendar.DATE, now.get(Calendar.DATE) + day);
-		   return now.getTime();  
-	  }
-}

+ 0 - 119
VideoSqlHelper/src/main/java/com/yc/database/utils/FieldUtil.java

@@ -1,119 +0,0 @@
-package com.yc.database.utils;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-import com.yc.database.manager.FieldTypeManager;
-/**
- * <pre>
- *     @author yangchong
- *     email  : yangchong211@163.com
- *     time  : 2017/8/6
- *     desc  : Field工具类
- *     revise:
- * </pre>
- */
-public class FieldUtil {
-	
-	/**
-	 * 获取任意类型字段的get方法
-	 * Author: hyl
-	 * Time: 2015-8-16下午10:12:48
-	 * @param mClass
-	 * @param field
-	 * @return
-	 */
-	public static Method getFieldGetMethod(Class<?> mClass, Field field) {
-		if(FieldTypeManager.getFieldType(field) == FieldTypeManager.BASE_TYPE_BOOLEAN) {//boolean类型
-			return getBooleanFieldGetMethod(mClass, field);
-		}
-		try {
-			String methodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
-			return mClass.getDeclaredMethod(methodName);
-		} catch (NoSuchMethodException e) {
-			throw new NullPointerException("没有为字段[" + field.getName() + "]按照Java代码规范定义get方法,同时请严格按照驼峰命名法进行变量命名");
-		}
-	}
-	
-	/**
-	 * 获取Boolean类型字段的get方法
-	 * Author: hyl
-	 * Time: 2015-8-16下午10:13:01
-	 * @param mClass
-	 * @param field
-	 * @return
-	 */
-	public static Method getBooleanFieldGetMethod(Class<?> mClass, Field field) {
-		try {
-			String methodName = "";
-			if(isFieldStartWithIs(field.getName())) {
-				methodName = field.getName();
-			} else {
-				methodName = "is" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
-			}
-			return mClass.getDeclaredMethod(methodName);
-		} catch (NoSuchMethodException e) {
-			throw new NullPointerException("没有为字段[" + field.getName() + "]按照Java代码规范定义get方法,同时请严格按照驼峰命名法进行变量命名");
-		}
-	}
-	
-	/**
-	 * 获取任意类型字段的set方法
-	 * Author: hyl
-	 * Time: 2015-8-16下午10:13:32
-	 * @param mClass
-	 * @param field
-	 * @return
-	 */
-	public static Method getFieldSetMethod(Class<?> mClass, Field field) {
-		if(FieldTypeManager.getFieldType(field) == FieldTypeManager.BASE_TYPE_BOOLEAN) {//boolean类型
-			return getBooleanFieldSetMethod(mClass, field);
-		}
-		try {
-			String methodName = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
-			return mClass.getDeclaredMethod(methodName, field.getType());
-		} catch (NoSuchMethodException e) {
-			throw new NullPointerException("没有为字段[" + field.getName() + "]按照Java代码规范定义set方法,同时请严格按照驼峰命名法进行变量命名");
-		}
-	}
-	
-	/**
-	 * 获取Boolean类型字段的set方法
-	 * Author: hyl
-	 * Time: 2015-8-16下午10:13:43
-	 * @param mClass
-	 * @param field
-	 * @return
-	 */
-	public static Method getBooleanFieldSetMethod(Class<?> mClass, Field field) {
-		try {
-			String methodName = "";
-			if(isFieldStartWithIs(field.getName())) {
-				methodName = "set" + field.getName().substring(2, 3).toUpperCase() + field.getName().substring(3);
-			} else {
-				methodName = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
-			}
-			return mClass.getDeclaredMethod(methodName, field.getType());
-		} catch (NoSuchMethodException e) {
-			throw new NullPointerException("没有为字段[" + field.getName() + "]按照Java代码规范定义set方法,同时请严格按照驼峰命名法进行变量命名");
-		}
-	}
-
-	/**
-	 * 判断某个字段是否为is开头
-	 * Author: hyl
-	 * Time: 2015-8-16下午10:13:56
-	 * @param fieldName
-	 * @return
-	 */
-	public static boolean isFieldStartWithIs(String fieldName) {
-		if(ValueUtil.isEmpty(fieldName) || fieldName.length() < 3) {
-			return false;
-		}
-		//必须以 is 开头,并且is之后的第一个字母为大写,比如:isAuto,该字段的get、set分别为:isAuto,setAuto
-		if(fieldName.startsWith("is") && Character.isUpperCase(fieldName.charAt(2))) {
-			return true;
-		}
-		return false;
-	}
-}

+ 0 - 18
VideoSqlHelper/src/main/java/com/yc/database/utils/ValueUtil.java

@@ -1,18 +0,0 @@
-package com.yc.database.utils;
-
-public class ValueUtil {
-
-	public static boolean isEmpty(String value) {
-		if(value == null || value.length() == 0) {
-			return true;
-		}
-		return false;
-	}
-	
-	public static boolean isEmpty(Object value) {
-		if(value == null) {
-			return true;
-		}
-		return isEmpty(value.toString());
-	}
-}

+ 1 - 1
VideoSqlLite/build.gradle

@@ -21,5 +21,5 @@ android {
 
 dependencies {
     implementation fileTree(dir: "libs", include: ["*.jar"])
-    implementation project(':VideoSqlHelper')
+    implementation 'androidx.annotation:annotation:1.1.0'
 }

+ 0 - 12
VideoSqlLite/src/main/java/com/yc/videosqllite/dao/SqlLiteCache.java

@@ -1,12 +0,0 @@
-package com.yc.videosqllite.dao;
-
-import com.yc.videosqllite.manager.CacheConfig;
-
-public class SqlLiteCache {
-
-    public SqlLiteCache(CacheConfig cacheConfig) {
-
-    }
-
-
-}

+ 249 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskFileUtils.java

@@ -0,0 +1,249 @@
+package com.yc.videosqllite.disk;
+
+import android.content.Context;
+import android.os.Environment;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     email  : yangchong211@163.com
+ *     time  : 2020/7/10
+ *     desc  : 保存日志的工具类
+ *     revise:
+ * </pre>
+ */
+public class DiskFileUtils {
+
+    /**
+     * 目录地址
+     * SDCard/Android/data/<application package>/cache
+     * data/data/<application package>/cache
+     */
+    public static String getPath(Context context) {
+        String path = getCachePath(context) + File.separator + "disk";
+        return path;
+    }
+
+    public static String getPath(Context context , String pathName) {
+        String path = getCachePath(context) + File.separator + pathName;
+        return path;
+    }
+
+    public static File getFilePath(Context context){
+        String path = getPath(context);
+        File file = new File(path);
+        return file;
+    }
+
+    /**
+     * 获取app缓存路径
+     * SDCard/Android/data/<application package>/cache
+     * data/data/<application package>/cache
+     *
+     * @param context
+     * @return
+     */
+    public static String getCachePath(Context context) {
+        String cachePath;
+        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
+                || !Environment.isExternalStorageRemovable()) {
+            //外部存储可用
+            if (context.getExternalCacheDir()!=null){
+                cachePath = context.getExternalCacheDir().getAbsolutePath();
+            } else {
+                cachePath = context.getCacheDir().getAbsolutePath();
+            }
+        } else {
+            //外部存储不可用
+            cachePath = context.getCacheDir().getAbsolutePath();
+        }
+        return cachePath;
+    }
+
+    /**
+     * 获取list集合
+     * @param context                               上下文
+     * @return
+     */
+    public static List<File> getFileList(Context context) {
+        File file = new File(DiskFileUtils.getPath(context));
+        List<File> mFileList = new ArrayList<>();
+        File[] fileArray = file.listFiles();
+        if (fileArray == null || fileArray.length <= 0) {
+            return mFileList;
+        }
+        for (File f : fileArray) {
+            if (f.isFile()) {
+                mFileList.add(f);
+            }
+        }
+        return mFileList;
+    }
+
+    /**
+     * 删除单个文件
+     *
+     * @param fileName 要删除的文件的文件名
+     * @return 单个文件删除成功返回true,否则返回false
+     */
+    public static boolean deleteFile(String fileName) {
+        File file = new File(fileName);
+        // 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
+        if (file.exists() && file.isFile()) {
+            if (file.delete()) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+
+    /**
+     * 删除所有的文件
+     * @param root                          root目录
+     */
+    public static void deleteAllFiles(File root) {
+        File files[] = root.listFiles();
+        if (files != null)
+            for (File f : files) {
+                if (f.isDirectory()) { // 判断是否为文件夹
+                    deleteAllFiles(f);
+                    try {
+                        f.delete();
+                    } catch (Exception e) {
+                        //不要在for循环中打印e
+                    }
+                } else {
+                    if (f.exists()) { // 判断是否存在
+                        deleteAllFiles(f);
+                        try {
+                            f.delete();
+                        } catch (Exception e) {
+                            //不要在for循环中打印e
+                        }
+                    }
+                }
+            }
+    }
+
+    /**
+     * 获取文件的内容
+     * @param fileName                      文件名称
+     * @return
+     */
+    public static String readFile2String(String fileName) {
+        String res = "";
+        try {
+            FileInputStream inputStream = new FileInputStream(fileName);
+            InputStreamReader inputStreamReader = null;
+            try {
+                inputStreamReader = new InputStreamReader(inputStream, "utf-8");
+            } catch (UnsupportedEncodingException e1) {
+                e1.printStackTrace();
+            }
+            BufferedReader reader = new BufferedReader(inputStreamReader);
+            StringBuilder sb = new StringBuilder("");
+            String line;
+            try {
+                while ((line = reader.readLine()) != null) {
+                    sb.append(line);
+                    sb.append("\n");
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            res = sb.toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return res;
+    }
+
+    /**
+     * 重命名文件
+     *
+     * @param oldPath 原来的文件地址
+     * @param newPath 新的文件地址
+     */
+    public static void renameFile(String oldPath, String newPath) {
+        File oleFile = new File(oldPath);
+        File newFile = new File(newPath);
+        //执行重命名
+        oleFile.renameTo(newFile);
+    }
+
+    /**
+     * 根据文件路径拷贝文件
+     *
+     * @param src                           源文件
+     * @param dest                          目标文件
+     * @return                              boolean 成功true、失败false
+     */
+    public static boolean copyFile(File src, File dest) {
+        boolean result = false;
+        if ((src == null) || (dest == null)) {
+            return result;
+        }
+        if (dest.exists()) {
+            dest.delete(); // delete file
+        }
+        if (!createOrExistsDir(dest.getParentFile())) {
+            return false;
+        }
+        try {
+            dest.createNewFile();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        FileChannel srcChannel = null;
+        FileChannel dstChannel = null;
+
+        try {
+            srcChannel = new FileInputStream(src).getChannel();
+            dstChannel = new FileOutputStream(dest).getChannel();
+            srcChannel.transferTo(0, srcChannel.size(), dstChannel);
+            result = true;
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            return result;
+        } catch (IOException e) {
+            e.printStackTrace();
+            return result;
+        }
+        try {
+            srcChannel.close();
+            dstChannel.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    public static boolean deleteFile(final File file) {
+        return file != null && (!file.exists() || file.isFile() && file.delete());
+    }
+
+
+    public static boolean createOrExistsDir(final File file) {
+        return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
+    }
+
+
+}

+ 836 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskLruCache.java

@@ -0,0 +1,836 @@
+package com.yc.videosqllite.disk;
+
+import java.io.BufferedWriter;
+import java.io.Closeable;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     email  : yangchong211@163.com
+ *     time  : 2020/8/6
+ *     desc  : 磁盘缓存类
+ *     revise:
+ * </pre>
+ */
+public final class DiskLruCache implements Closeable {
+
+    static final String JOURNAL_FILE = "journal";
+    static final String JOURNAL_FILE_TEMP = "journal.tmp";
+    static final String JOURNAL_FILE_BACKUP = "journal.bkp";
+    static final String MAGIC = "libcore.io.DiskLruCache";
+    static final String VERSION_1 = "1";
+    static final long ANY_SEQUENCE_NUMBER = -1;
+    private static final String CLEAN = "CLEAN";
+    private static final String DIRTY = "DIRTY";
+    private static final String REMOVE = "REMOVE";
+    private static final String READ = "READ";
+
+    private final File directory;
+    private final File journalFile;
+    private final File journalFileTmp;
+    private final File journalFileBackup;
+    private final int appVersion;
+    private long maxSize;
+    private final int valueCount;
+    private long size = 0;
+    private Writer journalWriter;
+    private final LinkedHashMap<String, Entry> lruEntries =
+            new LinkedHashMap<String, Entry>(0, 0.75f, true);
+    private int redundantOpCount;
+
+    /**
+     * To differentiate between old and current snapshots, each entry is given
+     * a sequence number each time an edit is committed. A snapshot is stale if
+     * its sequence number is not equal to its entry's sequence number.
+     */
+    private long nextSequenceNumber = 0;
+
+    /**
+     * This cache uses a single background thread to evict entries.
+     */
+    final ThreadPoolExecutor executorService =
+            new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(),
+                    new DiskLruCacheThreadFactory());
+    private final Callable<Void> cleanupCallable = new Callable<Void>() {
+        public Void call() throws Exception {
+            synchronized (DiskLruCache.this) {
+                if (journalWriter == null) {
+                    return null; // Closed.
+                }
+                trimToSize();
+                if (journalRebuildRequired()) {
+                    rebuildJournal();
+                    redundantOpCount = 0;
+                }
+            }
+            return null;
+        }
+    };
+
+    private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) {
+        this.directory = directory;
+        this.appVersion = appVersion;
+        this.journalFile = new File(directory, JOURNAL_FILE);
+        this.journalFileTmp = new File(directory, JOURNAL_FILE_TEMP);
+        this.journalFileBackup = new File(directory, JOURNAL_FILE_BACKUP);
+        this.valueCount = valueCount;
+        this.maxSize = maxSize;
+    }
+
+    /**
+     * Opens the cache in {@code directory}, creating a cache if none exists
+     * there.
+     * 第一个参数表示磁盘缓存在文件系统中的存储路径。
+     * 第二个参数表示应用的版本号,一般设为 1 即可。当版本号发生改变时 DiskLruCache 会清空之前所有的缓存文件,
+     *      而这个特性在实际开发中作用并不大,很多情况下即使应用的版本号发生了改变缓存文件却仍然是有效的,因此这个参数设为 1 比较好。
+     * 第三个参数表示同一个 key 可以对应多少个缓存文件,一般设为 1 即可。
+     * 第四个参数表示缓存的总大小,比如 50MB,当缓存大小超出这个设定值后,DiskLruCache 会清除一些缓存从而保证总大小不大于这个设定值。
+     * @param directory  a writable directory
+     * @param valueCount the number of values per cache entry. Must be positive.
+     * @param maxSize    the maximum number of bytes this cache should use to store
+     * @throws IOException if reading or writing the cache directory fails
+     */
+    public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
+            throws IOException {
+        if (maxSize <= 0) {
+            throw new IllegalArgumentException("maxSize <= 0");
+        }
+        if (valueCount <= 0) {
+            throw new IllegalArgumentException("valueCount <= 0");
+        }
+
+        // If a bkp file exists, use it instead.
+        File backupFile = new File(directory, JOURNAL_FILE_BACKUP);
+        if (backupFile.exists()) {
+            File journalFile = new File(directory, JOURNAL_FILE);
+            // If journal file also exists just delete backup file.
+            if (journalFile.exists()) {
+                backupFile.delete();
+            } else {
+                renameTo(backupFile, journalFile, false);
+            }
+        }
+
+        // Prefer to pick up where we left off.
+        DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
+        if (cache.journalFile.exists()) {
+            try {
+                cache.readJournal();
+                cache.processJournal();
+                return cache;
+            } catch (IOException journalIsCorrupt) {
+                System.out
+                        .println("DiskLruCache "
+                                + directory
+                                + " is corrupt: "
+                                + journalIsCorrupt.getMessage()
+                                + ", removing");
+                cache.delete();
+            }
+        }
+
+        // Create a new empty cache.
+        directory.mkdirs();
+        cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
+        cache.rebuildJournal();
+        return cache;
+    }
+
+    private void readJournal() throws IOException {
+        StrictLineReader reader = new StrictLineReader(new FileInputStream(journalFile), DiskUtils.US_ASCII);
+        try {
+            String magic = reader.readLine();
+            String version = reader.readLine();
+            String appVersionString = reader.readLine();
+            String valueCountString = reader.readLine();
+            String blank = reader.readLine();
+            if (!MAGIC.equals(magic)
+                    || !VERSION_1.equals(version)
+                    || !Integer.toString(appVersion).equals(appVersionString)
+                    || !Integer.toString(valueCount).equals(valueCountString)
+                    || !"".equals(blank)) {
+                throw new IOException("unexpected journal header: [" + magic + ", " + version + ", "
+                        + valueCountString + ", " + blank + "]");
+            }
+
+            int lineCount = 0;
+            while (true) {
+                try {
+                    readJournalLine(reader.readLine());
+                    lineCount++;
+                } catch (EOFException endOfJournal) {
+                    break;
+                }
+            }
+            redundantOpCount = lineCount - lruEntries.size();
+
+            // If we ended on a truncated line, rebuild the journal before appending to it.
+            if (reader.hasUnterminatedLine()) {
+                rebuildJournal();
+            } else {
+                journalWriter = new BufferedWriter(new OutputStreamWriter(
+                        new FileOutputStream(journalFile, true), DiskUtils.US_ASCII));
+            }
+        } finally {
+            DiskUtils.closeQuietly(reader);
+        }
+    }
+
+    private void readJournalLine(String line) throws IOException {
+        int firstSpace = line.indexOf(' ');
+        if (firstSpace == -1) {
+            throw new IOException("unexpected journal line: " + line);
+        }
+
+        int keyBegin = firstSpace + 1;
+        int secondSpace = line.indexOf(' ', keyBegin);
+        final String key;
+        if (secondSpace == -1) {
+            key = line.substring(keyBegin);
+            if (firstSpace == REMOVE.length() && line.startsWith(REMOVE)) {
+                lruEntries.remove(key);
+                return;
+            }
+        } else {
+            key = line.substring(keyBegin, secondSpace);
+        }
+
+        Entry entry = lruEntries.get(key);
+        if (entry == null) {
+            entry = new Entry(key);
+            lruEntries.put(key, entry);
+        }
+
+        if (secondSpace != -1 && firstSpace == CLEAN.length() && line.startsWith(CLEAN)) {
+            String[] parts = line.substring(secondSpace + 1).split(" ");
+            entry.readable = true;
+            entry.currentEditor = null;
+            entry.setLengths(parts);
+        } else if (secondSpace == -1 && firstSpace == DIRTY.length() && line.startsWith(DIRTY)) {
+            entry.currentEditor = new Editor(entry);
+        } else if (secondSpace == -1 && firstSpace == READ.length() && line.startsWith(READ)) {
+            // This work was already done by calling lruEntries.get().
+        } else {
+            throw new IOException("unexpected journal line: " + line);
+        }
+    }
+
+    /**
+     * Computes the initial size and collects garbage as a part of opening the
+     * cache. Dirty entries are assumed to be inconsistent and will be deleted.
+     */
+    private void processJournal() throws IOException {
+        deleteIfExists(journalFileTmp);
+        for (Iterator<Entry> i = lruEntries.values().iterator(); i.hasNext(); ) {
+            Entry entry = i.next();
+            if (entry.currentEditor == null) {
+                for (int t = 0; t < valueCount; t++) {
+                    size += entry.lengths[t];
+                }
+            } else {
+                entry.currentEditor = null;
+                for (int t = 0; t < valueCount; t++) {
+                    deleteIfExists(entry.getCleanFile(t));
+                    deleteIfExists(entry.getDirtyFile(t));
+                }
+                i.remove();
+            }
+        }
+    }
+
+    /**
+     * Creates a new journal that omits redundant information. This replaces the
+     * current journal if it exists.
+     */
+    private synchronized void rebuildJournal() throws IOException {
+        if (journalWriter != null) {
+            journalWriter.close();
+        }
+
+        Writer writer = new BufferedWriter(
+                new OutputStreamWriter(new FileOutputStream(journalFileTmp), DiskUtils.US_ASCII));
+        try {
+            writer.write(MAGIC);
+            writer.write("\n");
+            writer.write(VERSION_1);
+            writer.write("\n");
+            writer.write(Integer.toString(appVersion));
+            writer.write("\n");
+            writer.write(Integer.toString(valueCount));
+            writer.write("\n");
+            writer.write("\n");
+
+            for (Entry entry : lruEntries.values()) {
+                if (entry.currentEditor != null) {
+                    writer.write(DIRTY + ' ' + entry.key + '\n');
+                } else {
+                    writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
+                }
+            }
+        } finally {
+            writer.close();
+        }
+
+        if (journalFile.exists()) {
+            renameTo(journalFile, journalFileBackup, true);
+        }
+        renameTo(journalFileTmp, journalFile, false);
+        journalFileBackup.delete();
+
+        journalWriter = new BufferedWriter(
+                new OutputStreamWriter(new FileOutputStream(journalFile, true), DiskUtils.US_ASCII));
+    }
+
+    private static void deleteIfExists(File file) throws IOException {
+        if (file.exists() && !file.delete()) {
+            throw new IOException();
+        }
+    }
+
+    private static void renameTo(File from, File to, boolean deleteDestination) throws IOException {
+        if (deleteDestination) {
+            deleteIfExists(to);
+        }
+        if (!from.renameTo(to)) {
+            throw new IOException();
+        }
+    }
+
+    /**
+     * Returns a snapshot of the entry named {@code key}, or null if it doesn't
+     * exist is not currently readable. If a value is returned, it is moved to
+     * the head of the LRU queue.
+     */
+    public synchronized Value get(String key) throws IOException {
+        checkNotClosed();
+        Entry entry = lruEntries.get(key);
+        if (entry == null) {
+            return null;
+        }
+
+        if (!entry.readable) {
+            return null;
+        }
+
+        for (File file : entry.cleanFiles) {
+            // A file must have been deleted manually!
+            if (!file.exists()) {
+                return null;
+            }
+        }
+
+        redundantOpCount++;
+        journalWriter.append(READ);
+        journalWriter.append(' ');
+        journalWriter.append(key);
+        journalWriter.append('\n');
+        if (journalRebuildRequired()) {
+            executorService.submit(cleanupCallable);
+        }
+
+        return new Value(key, entry.sequenceNumber, entry.cleanFiles, entry.lengths);
+    }
+
+    /**
+     * Returns an editor for the entry named {@code key}, or null if another
+     * edit is in progress.
+     */
+    public Editor edit(String key) throws IOException {
+        return edit(key, ANY_SEQUENCE_NUMBER);
+    }
+
+    private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException {
+        checkNotClosed();
+        Entry entry = lruEntries.get(key);
+        if (expectedSequenceNumber != ANY_SEQUENCE_NUMBER && (entry == null
+                || entry.sequenceNumber != expectedSequenceNumber)) {
+            return null; // Value is stale.
+        }
+        if (entry == null) {
+            entry = new Entry(key);
+            lruEntries.put(key, entry);
+        } else if (entry.currentEditor != null) {
+            return null; // Another edit is in progress.
+        }
+
+        Editor editor = new Editor(entry);
+        entry.currentEditor = editor;
+
+        // Flush the journal before creating files to prevent file leaks.
+        journalWriter.append(DIRTY);
+        journalWriter.append(' ');
+        journalWriter.append(key);
+        journalWriter.append('\n');
+        journalWriter.flush();
+        return editor;
+    }
+
+    /**
+     * Returns the directory where this cache stores its data.
+     */
+    public File getDirectory() {
+        return directory;
+    }
+
+    /**
+     * Returns the maximum number of bytes that this cache should use to store
+     * its data.
+     */
+    public synchronized long getMaxSize() {
+        return maxSize;
+    }
+
+    /**
+     * Changes the maximum number of bytes the cache can store and queues a job
+     * to trim the existing store, if necessary.
+     */
+    public synchronized void setMaxSize(long maxSize) {
+        this.maxSize = maxSize;
+        executorService.submit(cleanupCallable);
+    }
+
+    /**
+     * Returns the number of bytes currently being used to store the values in
+     * this cache. This may be greater than the max size if a background
+     * deletion is pending.
+     */
+    public synchronized long size() {
+        return size;
+    }
+
+    private synchronized void completeEdit(Editor editor, boolean success) throws IOException {
+        Entry entry = editor.entry;
+        if (entry.currentEditor != editor) {
+            throw new IllegalStateException();
+        }
+
+        // If this edit is creating the entry for the first time, every index must have a value.
+        if (success && !entry.readable) {
+            for (int i = 0; i < valueCount; i++) {
+                if (!editor.written[i]) {
+                    editor.abort();
+                    throw new IllegalStateException("Newly created entry didn't create value for index " + i);
+                }
+                if (!entry.getDirtyFile(i).exists()) {
+                    editor.abort();
+                    return;
+                }
+            }
+        }
+
+        for (int i = 0; i < valueCount; i++) {
+            File dirty = entry.getDirtyFile(i);
+            if (success) {
+                if (dirty.exists()) {
+                    File clean = entry.getCleanFile(i);
+                    dirty.renameTo(clean);
+                    long oldLength = entry.lengths[i];
+                    long newLength = clean.length();
+                    entry.lengths[i] = newLength;
+                    size = size - oldLength + newLength;
+                }
+            } else {
+                deleteIfExists(dirty);
+            }
+        }
+
+        redundantOpCount++;
+        entry.currentEditor = null;
+        if (entry.readable | success) {
+            entry.readable = true;
+            journalWriter.append(CLEAN);
+            journalWriter.append(' ');
+            journalWriter.append(entry.key);
+            journalWriter.append(entry.getLengths());
+            journalWriter.append('\n');
+
+            if (success) {
+                entry.sequenceNumber = nextSequenceNumber++;
+            }
+        } else {
+            lruEntries.remove(entry.key);
+            journalWriter.append(REMOVE);
+            journalWriter.append(' ');
+            journalWriter.append(entry.key);
+            journalWriter.append('\n');
+        }
+        journalWriter.flush();
+
+        if (size > maxSize || journalRebuildRequired()) {
+            executorService.submit(cleanupCallable);
+        }
+    }
+
+    /**
+     * We only rebuild the journal when it will halve the size of the journal
+     * and eliminate at least 2000 ops.
+     */
+    private boolean journalRebuildRequired() {
+        final int redundantOpCompactThreshold = 2000;
+        return redundantOpCount >= redundantOpCompactThreshold //
+                && redundantOpCount >= lruEntries.size();
+    }
+
+    /**
+     * Drops the entry for {@code key} if it exists and can be removed. Entries
+     * actively being edited cannot be removed.
+     *
+     * @return true if an entry was removed.
+     */
+    public synchronized boolean remove(String key) throws IOException {
+        checkNotClosed();
+        Entry entry = lruEntries.get(key);
+        if (entry == null || entry.currentEditor != null) {
+            return false;
+        }
+
+        for (int i = 0; i < valueCount; i++) {
+            File file = entry.getCleanFile(i);
+            if (file.exists() && !file.delete()) {
+                throw new IOException("failed to delete " + file);
+            }
+            size -= entry.lengths[i];
+            entry.lengths[i] = 0;
+        }
+
+        redundantOpCount++;
+        journalWriter.append(REMOVE);
+        journalWriter.append(' ');
+        journalWriter.append(key);
+        journalWriter.append('\n');
+
+        lruEntries.remove(key);
+
+        if (journalRebuildRequired()) {
+            executorService.submit(cleanupCallable);
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns true if this cache has been closed.
+     */
+    public synchronized boolean isClosed() {
+        return journalWriter == null;
+    }
+
+    private void checkNotClosed() {
+        if (journalWriter == null) {
+            throw new IllegalStateException("cache is closed");
+        }
+    }
+
+    /**
+     * Force buffered operations to the filesystem.
+     */
+    public synchronized void flush() throws IOException {
+        checkNotClosed();
+        trimToSize();
+        journalWriter.flush();
+    }
+
+    /**
+     * Closes this cache. Stored values will remain on the filesystem.
+     */
+    public synchronized void close() throws IOException {
+        if (journalWriter == null) {
+            return; // Already closed.
+        }
+        for (Entry entry : new ArrayList<Entry>(lruEntries.values())) {
+            if (entry.currentEditor != null) {
+                entry.currentEditor.abort();
+            }
+        }
+        trimToSize();
+        journalWriter.close();
+        journalWriter = null;
+    }
+
+    private void trimToSize() throws IOException {
+        while (size > maxSize) {
+            Map.Entry<String, Entry> toEvict = lruEntries.entrySet().iterator().next();
+            remove(toEvict.getKey());
+        }
+    }
+
+    /**
+     * Closes the cache and deletes all of its stored values. This will delete
+     * all files in the cache directory including files that weren't created by
+     * the cache.
+     */
+    public void delete() throws IOException {
+        close();
+        DiskUtils.deleteContents(directory);
+    }
+
+    private static String inputStreamToString(InputStream in) throws IOException {
+        return DiskUtils.readFully(new InputStreamReader(in, DiskUtils.UTF_8));
+    }
+
+    /**
+     * A snapshot of the values for an entry.
+     */
+    public final class Value {
+        private final String key;
+        private final long sequenceNumber;
+        private final long[] lengths;
+        private final File[] files;
+
+        private Value(String key, long sequenceNumber, File[] files, long[] lengths) {
+            this.key = key;
+            this.sequenceNumber = sequenceNumber;
+            this.files = files;
+            this.lengths = lengths;
+        }
+
+        /**
+         * Returns an editor for this snapshot's entry, or null if either the
+         * entry has changed since this snapshot was created or if another edit
+         * is in progress.
+         */
+        public Editor edit() throws IOException {
+            return DiskLruCache.this.edit(key, sequenceNumber);
+        }
+
+        public File getFile(int index) {
+            return files[index];
+        }
+
+        /**
+         * Returns the string value for {@code index}.
+         */
+        public String getString(int index) throws IOException {
+            InputStream is = new FileInputStream(files[index]);
+            return inputStreamToString(is);
+        }
+
+        /**
+         * Returns the byte length of the value for {@code index}.
+         */
+        public long getLength(int index) {
+            return lengths[index];
+        }
+    }
+
+    /**
+     * Edits the values for an entry.
+     */
+    public final class Editor {
+        private final Entry entry;
+        private final boolean[] written;
+        private boolean committed;
+
+        private Editor(Entry entry) {
+            this.entry = entry;
+            this.written = (entry.readable) ? null : new boolean[valueCount];
+        }
+
+        /**
+         * Returns an unbuffered input stream to read the last committed value,
+         * or null if no value has been committed.
+         */
+        private InputStream newInputStream(int index) throws IOException {
+            synchronized (DiskLruCache.this) {
+                if (entry.currentEditor != this) {
+                    throw new IllegalStateException();
+                }
+                if (!entry.readable) {
+                    return null;
+                }
+                try {
+                    return new FileInputStream(entry.getCleanFile(index));
+                } catch (FileNotFoundException e) {
+                    return null;
+                }
+            }
+        }
+
+        /**
+         * Returns the last committed value as a string, or null if no value
+         * has been committed.
+         */
+        public String getString(int index) throws IOException {
+            InputStream in = newInputStream(index);
+            return in != null ? inputStreamToString(in) : null;
+        }
+
+        public File getFile(int index) throws IOException {
+            synchronized (DiskLruCache.this) {
+                if (entry.currentEditor != this) {
+                    throw new IllegalStateException();
+                }
+                if (!entry.readable) {
+                    written[index] = true;
+                }
+                File dirtyFile = entry.getDirtyFile(index);
+                if (!directory.exists()) {
+                    directory.mkdirs();
+                }
+                return dirtyFile;
+            }
+        }
+
+        /**
+         * Sets the value at {@code index} to {@code value}.
+         */
+        public void set(int index, String value) throws IOException {
+            Writer writer = null;
+            try {
+                OutputStream os = new FileOutputStream(getFile(index));
+                writer = new OutputStreamWriter(os, DiskUtils.UTF_8);
+                writer.write(value);
+            } finally {
+                DiskUtils.closeQuietly(writer);
+            }
+        }
+
+        /**
+         * Commits this edit so it is visible to readers.  This releases the
+         * edit lock so another edit may be started on the same key.
+         */
+        public void commit() throws IOException {
+            // The object using this Editor must catch and handle any errors
+            // during the write. If there is an error and they call commit
+            // anyway, we will assume whatever they managed to write was valid.
+            // Normally they should call abort.
+            completeEdit(this, true);
+            committed = true;
+        }
+
+        /**
+         * Aborts this edit. This releases the edit lock so another edit may be
+         * started on the same key.
+         */
+        public void abort() throws IOException {
+            completeEdit(this, false);
+        }
+
+        public void abortUnlessCommitted() {
+            if (!committed) {
+                try {
+                    abort();
+                } catch (IOException ignored) {
+                }
+            }
+        }
+    }
+
+    private final class Entry {
+        private final String key;
+
+        /**
+         * Lengths of this entry's files.
+         */
+        private final long[] lengths;
+
+        /**
+         * Memoized File objects for this entry to avoid char[] allocations.
+         */
+        File[] cleanFiles;
+        File[] dirtyFiles;
+
+        /**
+         * True if this entry has ever been published.
+         */
+        private boolean readable;
+
+        /**
+         * The ongoing edit or null if this entry is not being edited.
+         */
+        private Editor currentEditor;
+
+        /**
+         * The sequence number of the most recently committed edit to this entry.
+         */
+        private long sequenceNumber;
+
+        private Entry(String key) {
+            this.key = key;
+            this.lengths = new long[valueCount];
+            cleanFiles = new File[valueCount];
+            dirtyFiles = new File[valueCount];
+
+            // The names are repetitive so re-use the same builder to avoid allocations.
+            StringBuilder fileBuilder = new StringBuilder(key).append('.');
+            int truncateTo = fileBuilder.length();
+            for (int i = 0; i < valueCount; i++) {
+                fileBuilder.append(i);
+                cleanFiles[i] = new File(directory, fileBuilder.toString());
+                fileBuilder.append(".tmp");
+                dirtyFiles[i] = new File(directory, fileBuilder.toString());
+                fileBuilder.setLength(truncateTo);
+            }
+        }
+
+        public String getLengths() throws IOException {
+            StringBuilder result = new StringBuilder();
+            for (long size : lengths) {
+                result.append(' ').append(size);
+            }
+            return result.toString();
+        }
+
+        /**
+         * Set lengths using decimal numbers like "10123".
+         */
+        private void setLengths(String[] strings) throws IOException {
+            if (strings.length != valueCount) {
+                throw invalidLengths(strings);
+            }
+
+            try {
+                for (int i = 0; i < strings.length; i++) {
+                    lengths[i] = Long.parseLong(strings[i]);
+                }
+            } catch (NumberFormatException e) {
+                throw invalidLengths(strings);
+            }
+        }
+
+        private IOException invalidLengths(String[] strings) throws IOException {
+            throw new IOException("unexpected journal line: " + java.util.Arrays.toString(strings));
+        }
+
+        public File getCleanFile(int i) {
+            return cleanFiles[i];
+        }
+
+        public File getDirtyFile(int i) {
+            return dirtyFiles[i];
+        }
+    }
+
+    /**
+     * A {@link ThreadFactory} that builds a thread with a specific thread name
+     * and with minimum priority.
+     */
+    private static final class DiskLruCacheThreadFactory implements ThreadFactory {
+        @Override
+        public synchronized Thread newThread(Runnable runnable) {
+            Thread result = new Thread(runnable, "glide-disk-lru-cache-thread");
+            result.setPriority(Thread.MIN_PRIORITY);
+            return result;
+        }
+    }
+}

+ 70 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/DiskUtils.java

@@ -0,0 +1,70 @@
+package com.yc.videosqllite.disk;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.nio.charset.Charset;
+
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     email  : yangchong211@163.com
+ *     time  : 2020/8/6
+ *     desc  : 磁盘缓存工具类
+ *     revise:
+ * </pre>
+ */
+final class DiskUtils {
+    static final Charset US_ASCII = Charset.forName("US-ASCII");
+    static final Charset UTF_8 = Charset.forName("UTF-8");
+
+    private DiskUtils() {
+    }
+
+    static String readFully(Reader reader) throws IOException {
+        try {
+            StringWriter writer = new StringWriter();
+            char[] buffer = new char[1024];
+            int count;
+            while ((count = reader.read(buffer)) != -1) {
+                writer.write(buffer, 0, count);
+            }
+            return writer.toString();
+        } finally {
+            reader.close();
+        }
+    }
+
+    /**
+     * Deletes the contents of {@code dir}. Throws an IOException if any file
+     * could not be deleted, or if {@code dir} is not a readable directory.
+     */
+    static void deleteContents(File dir) throws IOException {
+        File[] files = dir.listFiles();
+        if (files == null) {
+            throw new IOException("not a readable directory: " + dir);
+        }
+        for (File file : files) {
+            if (file.isDirectory()) {
+                deleteContents(file);
+            }
+            if (!file.delete()) {
+                throw new IOException("failed to delete file: " + file);
+            }
+        }
+    }
+
+    static void closeQuietly(/*Auto*/Closeable closeable) {
+        if (closeable != null) {
+            try {
+                closeable.close();
+            } catch (RuntimeException rethrown) {
+                throw rethrown;
+            } catch (Exception ignored) {
+            }
+        }
+    }
+}

+ 180 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/SqlLiteCache.java

@@ -0,0 +1,180 @@
+package com.yc.videosqllite.disk;
+
+import com.yc.videosqllite.manager.CacheConfig;
+import com.yc.videosqllite.model.VideoLocation;
+import com.yc.videosqllite.utils.CacheLogUtils;
+import com.yc.videosqllite.utils.VideoMd5Utils;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     email  : yangchong211@163.com
+ *     time  : 2020/8/6
+ *     desc  : 磁盘缓存工具
+ *     revise:
+ * </pre>
+ */
+public class SqlLiteCache {
+
+    private CacheConfig cacheConfig;
+    private DiskLruCache diskLruCache;
+
+    public SqlLiteCache(CacheConfig cacheConfig) {
+        this.cacheConfig = cacheConfig;
+        File path = DiskFileUtils.getFilePath(cacheConfig.getContext());
+        String pathString = path.getPath();
+        CacheLogUtils.d("SqlLiteCache-----pathString-"+pathString);
+        try {
+            diskLruCache = DiskLruCache.open(path,1,1,cacheConfig.getCacheMax());
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 存数据
+     * @param url                           链接
+     * @param location                      视频数据
+     */
+    public synchronized void put(String url , VideoLocation location){
+        if (url==null || url.length()==0){
+            return;
+        }
+        if (location==null){
+            return;
+        }
+
+        if (diskLruCache!=null){
+            try {
+                String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
+                CacheLogUtils.d("SqlLiteCache-----put--key--"+key);
+                DiskLruCache.Editor editor = diskLruCache.edit(key);
+                if (editor!=null){
+                    String json = location.toJson();
+                    editor.set(0,json);
+                    CacheLogUtils.d("SqlLiteCache-----put--json--"+json);
+                    editor.commit();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    diskLruCache.flush();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * 取数据
+     * @param url                           链接
+     * @return
+     */
+    public synchronized long get(String url){
+        if (url==null || url.length()==0){
+            return -1;
+        }
+        if (diskLruCache!=null){
+            String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
+            CacheLogUtils.d("SqlLiteCache-----get--key-"+key);
+            try {
+                DiskLruCache.Value value = diskLruCache.get(key);
+                if (value != null) {
+                    File file = value.getFile(0);
+                    long length = value.getLength(0);
+                    String string = value.getString(0);
+                    VideoLocation location = VideoLocation.toObject(string);
+                    long position = location.getPosition();
+                    CacheLogUtils.d("SqlLiteCache-----get---"+file+"-------"+length+"-------"+string+"-----"+position);
+                    return position;
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    diskLruCache.flush();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * 移除数据
+     * @param url                           链接
+     * @return
+     */
+    public synchronized boolean remove(String url){
+        if (diskLruCache!=null){
+            String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
+            try {
+                boolean remove = diskLruCache.remove(key);
+                return remove;
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    diskLruCache.flush();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 是否包含
+     * @param url                           链接
+     * @return
+     */
+    public synchronized boolean containsKey(String url){
+        if (diskLruCache!=null){
+            String key = VideoMd5Utils.encryptMD5ToString(url, cacheConfig.getSalt());
+            try {
+                DiskLruCache.Value value = diskLruCache.get(key);
+                return value != null;
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    diskLruCache.flush();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * 清楚所有数据
+     * @return                              是否清楚完毕
+     */
+    public synchronized boolean clearAll(){
+        if (diskLruCache!=null){
+            try {
+                diskLruCache.delete();
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    diskLruCache.flush();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return false;
+    }
+
+
+}

+ 196 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/StrictLineReader.java

@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.yc.videosqllite.disk;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+
+/**
+ * Buffers input from an {@link InputStream} for reading lines.
+ *
+ * <p>This class is used for buffered reading of lines. For purposes of this class, a line ends
+ * with "\n" or "\r\n". End of input is reported by throwing {@code EOFException}. Unterminated
+ * line at end of input is invalid and will be ignored, the caller may use {@code
+ * hasUnterminatedLine()} to detect it after catching the {@code EOFException}.
+ *
+ * <p>This class is intended for reading input that strictly consists of lines, such as line-based
+ * cache entries or cache journal. Unlike the {@link java.io.BufferedReader} which in conjunction
+ * with {@link java.io.InputStreamReader} provides similar functionality, this class uses different
+ * end-of-input reporting and a more restrictive definition of a line.
+ *
+ * <p>This class supports only charsets that encode '\r' and '\n' as a single byte with value 13
+ * and 10, respectively, and the representation of no other character contains these values.
+ * We currently check in constructor that the charset is one of US-ASCII, UTF-8 and ISO-8859-1.
+ * The default charset is US_ASCII.
+ */
+class StrictLineReader implements Closeable {
+    private static final byte CR = (byte) '\r';
+    private static final byte LF = (byte) '\n';
+
+    private final InputStream in;
+    private final Charset charset;
+
+    /*
+     * Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end
+     * and the data in the range [pos, end) is buffered for reading. At end of input, if there is
+     * an unterminated line, we set end == -1, otherwise end == pos. If the underlying
+     * {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1.
+     */
+    private byte[] buf;
+    private int pos;
+    private int end;
+
+    /**
+     * Constructs a new {@code LineReader} with the specified charset and the default capacity.
+     *
+     * @param in      the {@code InputStream} to read data from.
+     * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
+     *                supported.
+     * @throws NullPointerException     if {@code in} or {@code charset} is null.
+     * @throws IllegalArgumentException if the specified charset is not supported.
+     */
+    public StrictLineReader(InputStream in, Charset charset) {
+        this(in, 8192, charset);
+    }
+
+    /**
+     * Constructs a new {@code LineReader} with the specified capacity and charset.
+     *
+     * @param in       the {@code InputStream} to read data from.
+     * @param capacity the capacity of the buffer.
+     * @param charset  the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
+     *                 supported.
+     * @throws NullPointerException     if {@code in} or {@code charset} is null.
+     * @throws IllegalArgumentException if {@code capacity} is negative or zero
+     *                                  or the specified charset is not supported.
+     */
+    public StrictLineReader(InputStream in, int capacity, Charset charset) {
+        if (in == null || charset == null) {
+            throw new NullPointerException();
+        }
+        if (capacity < 0) {
+            throw new IllegalArgumentException("capacity <= 0");
+        }
+        if (!(charset.equals(DiskUtils.US_ASCII))) {
+            throw new IllegalArgumentException("Unsupported encoding");
+        }
+
+        this.in = in;
+        this.charset = charset;
+        buf = new byte[capacity];
+    }
+
+    /**
+     * Closes the reader by closing the underlying {@code InputStream} and
+     * marking this reader as closed.
+     *
+     * @throws IOException for errors when closing the underlying {@code InputStream}.
+     */
+    public void close() throws IOException {
+        synchronized (in) {
+            if (buf != null) {
+                buf = null;
+                in.close();
+            }
+        }
+    }
+
+    /**
+     * Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"},
+     * this end of line marker is not included in the result.
+     *
+     * @return the next line from the input.
+     * @throws IOException  for underlying {@code InputStream} errors.
+     * @throws EOFException for the end of source stream.
+     */
+    public String readLine() throws IOException {
+        synchronized (in) {
+            if (buf == null) {
+                throw new IOException("LineReader is closed");
+            }
+
+            // Read more data if we are at the end of the buffered data.
+            // Though it's an error to read after an exception, we will let {@code fillBuf()}
+            // throw again if that happens; thus we need to handle end == -1 as well as end == pos.
+            if (pos >= end) {
+                fillBuf();
+            }
+            // Try to find LF in the buffered data and return the line if successful.
+            for (int i = pos; i != end; ++i) {
+                if (buf[i] == LF) {
+                    int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i;
+                    String res = new String(buf, pos, lineEnd - pos, charset.name());
+                    pos = i + 1;
+                    return res;
+                }
+            }
+
+            // Let's anticipate up to 80 characters on top of those already read.
+            ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) {
+                @Override
+                public String toString() {
+                    int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count;
+                    try {
+                        return new String(buf, 0, length, charset.name());
+                    } catch (UnsupportedEncodingException e) {
+                        throw new AssertionError(e); // Since we control the charset this will never happen.
+                    }
+                }
+            };
+
+            while (true) {
+                out.write(buf, pos, end - pos);
+                // Mark unterminated line in case fillBuf throws EOFException or IOException.
+                end = -1;
+                fillBuf();
+                // Try to find LF in the buffered data and return the line if successful.
+                for (int i = pos; i != end; ++i) {
+                    if (buf[i] == LF) {
+                        if (i != pos) {
+                            out.write(buf, pos, i - pos);
+                        }
+                        pos = i + 1;
+                        return out.toString();
+                    }
+                }
+            }
+        }
+    }
+
+    public boolean hasUnterminatedLine() {
+        return end == -1;
+    }
+
+    /**
+     * Reads new input data into the buffer. Call only with pos == end or end == -1,
+     * depending on the desired outcome if the function throws.
+     */
+    private void fillBuf() throws IOException {
+        int result = in.read(buf, 0, buf.length);
+        if (result == -1) {
+            throw new EOFException();
+        }
+        pos = 0;
+        end = result;
+    }
+}
+

+ 73 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCache.java

@@ -0,0 +1,73 @@
+package com.yc.videosqllite.disk.wrapper;
+
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.io.File;
+
+/**
+ * An interface for writing to and reading from a disk cache.
+ */
+public interface DiskCache {
+
+  /**
+   * An interface for lazily creating a disk cache.
+   */
+  interface Factory {
+    /** 250 MB of cache. */
+    int DEFAULT_DISK_CACHE_SIZE = 250 * 1024 * 1024;
+    String DEFAULT_DISK_CACHE_DIR = "image_manager_disk_cache";
+
+    /** Returns a new disk cache, or {@code null} if no disk cache could be created. */
+    DiskCache build();
+  }
+
+  /**
+   * An interface to actually write data to a key in the disk cache.
+   */
+  interface Writer {
+    /**
+     * Writes data to the file and returns true if the write was successful and should be committed,
+     * and false if the write should be aborted.
+     *
+     * @param file The File the Writer should write to.
+     */
+    boolean write(@NonNull File file);
+  }
+
+  /**
+   * Get the cache for the value at the given key.
+   *
+   * <p> Note - This is potentially dangerous, someone may write a new value to the file at any
+   * point in time and we won't know about it. </p>
+   *
+   * @param key The key in the cache.
+   * @return An InputStream representing the data at key at the time get is called.
+   */
+  @Nullable
+  File get(Key key);
+
+  /**
+   * Write to a key in the cache. {@link Writer} is used so that the cache implementation can
+   * perform actions after the write finishes, like commit (via atomic file rename).
+   *
+   * @param key    The key to write to.
+   * @param writer An interface that will write data given an OutputStream for the key.
+   */
+  void put(Key key, Writer writer);
+
+  /**
+   * Remove the key and value from the cache.
+   *
+   * @param key The key to remove.
+   */
+  // Public API.
+  @SuppressWarnings("unused")
+  void delete(Key key);
+
+  /**
+   * Clear the cache.
+   */
+  void clear();
+}

+ 29 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCacheAdapter.java

@@ -0,0 +1,29 @@
+package com.yc.videosqllite.disk.wrapper;
+
+import java.io.File;
+
+/**
+ * A simple class that returns null for all gets and ignores all writes.
+ */
+public class DiskCacheAdapter implements DiskCache {
+  @Override
+  public File get(Key key) {
+    // no op, default for overriders
+    return null;
+  }
+
+  @Override
+  public void put(Key key, Writer writer) {
+    // no op, default for overriders
+  }
+
+  @Override
+  public void delete(Key key) {
+    // no op, default for overriders
+  }
+
+  @Override
+  public void clear() {
+      // no op, default for overriders
+  }
+}

+ 97 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskCacheWriteLocker.java

@@ -0,0 +1,97 @@
+package com.yc.videosqllite.disk.wrapper;
+
+
+import java.util.ArrayDeque;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Keeps a map of keys to locks that allows locks to be removed from the map when no longer in use
+ * so the size of the collection is bounded.
+ *
+ * <p> This class will be accessed by multiple threads in a thread pool and ensures that the
+ *  number of threads interested in each lock is updated atomically so that when the count reaches
+ *  0, the lock can safely be removed from the map. </p>
+ */
+final class DiskCacheWriteLocker {
+  private final Map<String, WriteLock> locks = new HashMap<>();
+  private final WriteLockPool writeLockPool = new WriteLockPool();
+
+  void acquire(String safeKey) {
+    WriteLock writeLock;
+    synchronized (this) {
+      writeLock = locks.get(safeKey);
+      if (writeLock == null) {
+        writeLock = writeLockPool.obtain();
+        locks.put(safeKey, writeLock);
+      }
+      writeLock.interestedThreads++;
+    }
+
+    writeLock.lock.lock();
+  }
+
+  void release(String safeKey) {
+    WriteLock writeLock;
+    synchronized (this) {
+      writeLock = Preconditions.checkNotNull(locks.get(safeKey));
+      if (writeLock.interestedThreads < 1) {
+        throw new IllegalStateException("Cannot release a lock that is not held"
+            + ", safeKey: " + safeKey
+            + ", interestedThreads: " + writeLock.interestedThreads);
+      }
+
+      writeLock.interestedThreads--;
+      if (writeLock.interestedThreads == 0) {
+        WriteLock removed = locks.remove(safeKey);
+        if (!removed.equals(writeLock)) {
+          throw new IllegalStateException("Removed the wrong lock"
+              + ", expected to remove: " + writeLock
+              + ", but actually removed: " + removed
+              + ", safeKey: " + safeKey);
+        }
+        writeLockPool.offer(removed);
+      }
+    }
+
+    writeLock.lock.unlock();
+  }
+
+  private static class WriteLock  {
+    final Lock lock = new ReentrantLock();
+    int interestedThreads;
+
+    @Synthetic
+    WriteLock() { }
+  }
+
+  private static class WriteLockPool {
+    private static final int MAX_POOL_SIZE = 10;
+    private final Queue<WriteLock> pool = new ArrayDeque<>();
+
+    @Synthetic
+    WriteLockPool() { }
+
+    WriteLock obtain() {
+      WriteLock result;
+      synchronized (pool) {
+        result = pool.poll();
+      }
+      if (result == null) {
+        result = new WriteLock();
+      }
+      return result;
+    }
+
+    void offer(WriteLock writeLock) {
+      synchronized (pool) {
+        if (pool.size() < MAX_POOL_SIZE) {
+          pool.offer(writeLock);
+        }
+      }
+    }
+  }
+}

+ 72 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskLruCacheFactory.java

@@ -0,0 +1,72 @@
+package com.yc.videosqllite.disk.wrapper;
+
+import java.io.File;
+
+/**
+ * Creates an {@link com.bumptech.glide.disklrucache.DiskLruCache} based disk cache in the specified
+ * disk cache directory.
+ *
+ * <p>If you need to make I/O access before returning the cache directory use the {@link
+ * DiskLruCacheFactory#DiskLruCacheFactory(CacheDirectoryGetter, long)} constructor variant.
+ */
+// Public API.
+@SuppressWarnings("unused")
+public class DiskLruCacheFactory implements DiskCache.Factory {
+  private final long diskCacheSize;
+  private final CacheDirectoryGetter cacheDirectoryGetter;
+
+  /**
+   * Interface called out of UI thread to get the cache folder.
+   */
+  public interface CacheDirectoryGetter {
+    File getCacheDirectory();
+  }
+
+  public DiskLruCacheFactory(final String diskCacheFolder, long diskCacheSize) {
+    this(new CacheDirectoryGetter() {
+      @Override
+      public File getCacheDirectory() {
+        return new File(diskCacheFolder);
+      }
+    }, diskCacheSize);
+  }
+
+  public DiskLruCacheFactory(final String diskCacheFolder, final String diskCacheName,
+                             long diskCacheSize) {
+    this(new CacheDirectoryGetter() {
+      @Override
+      public File getCacheDirectory() {
+        return new File(diskCacheFolder, diskCacheName);
+      }
+    }, diskCacheSize);
+  }
+
+  /**
+   * When using this constructor {@link CacheDirectoryGetter#getCacheDirectory()} will be called out
+   * of UI thread, allowing to do I/O access without performance impacts.
+   *
+   * @param cacheDirectoryGetter Interface called out of UI thread to get the cache folder.
+   * @param diskCacheSize        Desired max bytes size for the LRU disk cache.
+   */
+  // Public API.
+  @SuppressWarnings("WeakerAccess")
+  public DiskLruCacheFactory(CacheDirectoryGetter cacheDirectoryGetter, long diskCacheSize) {
+    this.diskCacheSize = diskCacheSize;
+    this.cacheDirectoryGetter = cacheDirectoryGetter;
+  }
+
+  @Override
+  public DiskCache build() {
+    File cacheDir = cacheDirectoryGetter.getCacheDirectory();
+
+    if (cacheDir == null) {
+      return null;
+    }
+
+    if (!cacheDir.mkdirs() && (!cacheDir.exists() || !cacheDir.isDirectory())) {
+      return null;
+    }
+
+    return DiskLruCacheWrapper.create(cacheDir, diskCacheSize);
+  }
+}

+ 182 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/DiskLruCacheWrapper.java

@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2013. Bump Technologies Inc. All Rights Reserved.
+ */
+
+package com.yc.videosqllite.disk.wrapper;
+
+import android.util.Log;
+
+import com.yc.videosqllite.disk.DiskLruCache;
+import com.yc.videosqllite.disk.DiskLruCache.Value;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * The default DiskCache implementation. There must be no more than one active instance for a given
+ * directory at a time.
+ *
+ * @see #get(File, long)
+ */
+public class DiskLruCacheWrapper implements DiskCache {
+  private static final String TAG = "DiskLruCacheWrapper";
+
+  private static final int APP_VERSION = 1;
+  private static final int VALUE_COUNT = 1;
+  private static DiskLruCacheWrapper wrapper;
+
+  private final SafeKeyGenerator safeKeyGenerator;
+  private final File directory;
+  private final long maxSize;
+  private final DiskCacheWriteLocker writeLocker = new DiskCacheWriteLocker();
+  private DiskLruCache diskLruCache;
+
+  /**
+   * Get a DiskCache in the given directory and size. If a disk cache has already been created with
+   * a different directory and/or size, it will be returned instead and the new arguments will be
+   * ignored.
+   *
+   * @param directory The directory for the disk cache
+   * @param maxSize   The max size for the disk cache
+   * @return The new disk cache with the given arguments, or the current cache if one already exists
+   *
+   * @deprecated Use {@link #create(File, long)} to create a new cache with the specified arguments.
+   */
+  @SuppressWarnings("deprecation")
+  @Deprecated
+  public static synchronized DiskCache get(File directory, long maxSize) {
+    // TODO calling twice with different arguments makes it return the cache for the same
+    // directory, it's public!
+    if (wrapper == null) {
+      wrapper = new DiskLruCacheWrapper(directory, maxSize);
+    }
+    return wrapper;
+  }
+
+  /**
+   * Create a new DiskCache in the given directory with a specified max size.
+   *
+   * @param directory The directory for the disk cache
+   * @param maxSize   The max size for the disk cache
+   * @return The new disk cache with the given arguments
+   */
+  @SuppressWarnings("deprecation")
+  public static DiskCache create(File directory, long maxSize) {
+    return new DiskLruCacheWrapper(directory, maxSize);
+  }
+
+  /**
+   * @deprecated Do not extend this class.
+   */
+  @Deprecated
+  // Deprecated public API.
+  @SuppressWarnings({"WeakerAccess", "DeprecatedIsStillUsed"})
+  protected DiskLruCacheWrapper(File directory, long maxSize) {
+    this.directory = directory;
+    this.maxSize = maxSize;
+    this.safeKeyGenerator = new SafeKeyGenerator();
+  }
+
+  private synchronized DiskLruCache getDiskCache() throws IOException {
+    if (diskLruCache == null) {
+      diskLruCache = DiskLruCache.open(directory, APP_VERSION, VALUE_COUNT, maxSize);
+    }
+    return diskLruCache;
+  }
+
+  @Override
+  public File get(Key key) {
+    String safeKey = safeKeyGenerator.getSafeKey(key);
+    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+      Log.v(TAG, "Get: Obtained: " + safeKey + " for for Key: " + key);
+    }
+    File result = null;
+    try {
+      // It is possible that the there will be a put in between these two gets. If so that shouldn't
+      // be a problem because we will always put the same value at the same key so our input streams
+      // will still represent the same data.
+      Value value = getDiskCache().get(safeKey);
+      if (value != null) {
+        result = value.getFile(0);
+      }
+    } catch (IOException e) {
+      if (Log.isLoggable(TAG, Log.WARN)) {
+        Log.w(TAG, "Unable to get from disk cache", e);
+      }
+    }
+    return result;
+  }
+
+  @Override
+  public void put(Key key, Writer writer) {
+    // We want to make sure that puts block so that data is available when put completes. We may
+    // actually not write any data if we find that data is written by the time we acquire the lock.
+    String safeKey = safeKeyGenerator.getSafeKey(key);
+    writeLocker.acquire(safeKey);
+    try {
+      if (Log.isLoggable(TAG, Log.VERBOSE)) {
+        Log.v(TAG, "Put: Obtained: " + safeKey + " for for Key: " + key);
+      }
+      try {
+        // We assume we only need to put once, so if data was written while we were trying to get
+        // the lock, we can simply abort.
+        DiskLruCache diskCache = getDiskCache();
+        DiskLruCache.Value current = diskCache.get(safeKey);
+        if (current != null) {
+          return;
+        }
+
+        DiskLruCache.Editor editor = diskCache.edit(safeKey);
+        if (editor == null) {
+          throw new IllegalStateException("Had two simultaneous puts for: " + safeKey);
+        }
+        try {
+          File file = editor.getFile(0);
+          if (writer.write(file)) {
+            editor.commit();
+          }
+        } finally {
+          editor.abortUnlessCommitted();
+        }
+      } catch (IOException e) {
+        if (Log.isLoggable(TAG, Log.WARN)) {
+          Log.w(TAG, "Unable to put to disk cache", e);
+        }
+      }
+    } finally {
+      writeLocker.release(safeKey);
+    }
+  }
+
+  @Override
+  public void delete(Key key) {
+    String safeKey = safeKeyGenerator.getSafeKey(key);
+    try {
+      getDiskCache().remove(safeKey);
+    } catch (IOException e) {
+      if (Log.isLoggable(TAG, Log.WARN)) {
+        Log.w(TAG, "Unable to delete from disk cache", e);
+      }
+    }
+  }
+
+  @Override
+  public synchronized void clear() {
+    try {
+      getDiskCache().delete();
+    } catch (IOException e) {
+      if (Log.isLoggable(TAG, Log.WARN)) {
+        Log.w(TAG, "Unable to clear disk cache or disk cache cleared externally", e);
+      }
+    } finally {
+      // Delete can close the cache but still throw. If we don't null out the disk cache here, every
+      // subsequent request will try to act on a closed disk cache and fail. By nulling out the disk
+      // cache we at least allow for attempts to open the cache in the future. See #2465.
+      resetDiskCache();
+    }
+  }
+
+  private synchronized void resetDiskCache() {
+    diskLruCache = null;
+  }
+}

+ 38 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/ExternalCacheDiskCacheFactory.java

@@ -0,0 +1,38 @@
+package com.yc.videosqllite.disk.wrapper;
+
+import android.content.Context;
+
+import java.io.File;
+
+
+// Public API.
+@SuppressWarnings({"unused", "WeakerAccess"})
+@Deprecated
+public final class ExternalCacheDiskCacheFactory extends DiskLruCacheFactory {
+
+  public ExternalCacheDiskCacheFactory(Context context) {
+    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR,
+        DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);
+  }
+
+  public ExternalCacheDiskCacheFactory(Context context, int diskCacheSize) {
+    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR, diskCacheSize);
+  }
+
+  public ExternalCacheDiskCacheFactory(final Context context, final String diskCacheName,
+      int diskCacheSize) {
+    super(new CacheDirectoryGetter() {
+      @Override
+      public File getCacheDirectory() {
+        File cacheDirectory = context.getExternalCacheDir();
+        if (cacheDirectory == null) {
+          return null;
+        }
+        if (diskCacheName != null) {
+          return new File(cacheDirectory, diskCacheName);
+        }
+        return cacheDirectory;
+      }
+    }, diskCacheSize);
+  }
+}

+ 67 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/ExternalPreferredCacheDiskCacheFactory.java

@@ -0,0 +1,67 @@
+package com.yc.videosqllite.disk.wrapper;
+
+import android.content.Context;
+
+import androidx.annotation.Nullable;
+
+import java.io.File;
+
+/**
+ * Creates an {@link com.bumptech.glide.disklrucache.DiskLruCache} based disk cache in the external
+ * disk cache directory, which falls back to the internal disk cache if no external storage is
+ * available. If ever fell back to the internal disk cache, will use that one from that moment on.
+ *
+ * <p><b>Images can be read by everyone when using external disk cache.</b>
+ */
+// Public API.
+@SuppressWarnings({"unused", "WeakerAccess"})
+public final class ExternalPreferredCacheDiskCacheFactory extends DiskLruCacheFactory {
+
+  public ExternalPreferredCacheDiskCacheFactory(Context context) {
+    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR,
+        DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);
+  }
+
+  public ExternalPreferredCacheDiskCacheFactory(Context context, long diskCacheSize) {
+    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR, diskCacheSize);
+  }
+
+  public ExternalPreferredCacheDiskCacheFactory(final Context context, final String diskCacheName,
+                                                final long diskCacheSize) {
+    super(new CacheDirectoryGetter() {
+      @Nullable
+      private File getInternalCacheDirectory() {
+        File cacheDirectory = context.getCacheDir();
+        if (cacheDirectory == null) {
+          return null;
+        }
+        if (diskCacheName != null) {
+          return new File(cacheDirectory, diskCacheName);
+        }
+        return cacheDirectory;
+      }
+
+      @Override
+      public File getCacheDirectory() {
+        File internalCacheDirectory = getInternalCacheDirectory();
+
+        // Already used internal cache, so keep using that one,
+        // thus avoiding using both external and internal with transient errors.
+        if ((null != internalCacheDirectory) && internalCacheDirectory.exists()) {
+          return internalCacheDirectory;
+        }
+
+        File cacheDirectory = context.getExternalCacheDir();
+
+        // Shared storage is not available.
+        if ((cacheDirectory == null) || (!cacheDirectory.canWrite())) {
+          return internalCacheDirectory;
+        }
+        if (diskCacheName != null) {
+          return new File(cacheDirectory, diskCacheName);
+        }
+        return cacheDirectory;
+      }
+    }, diskCacheSize);
+  }
+}

+ 40 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/InternalCacheDiskCacheFactory.java

@@ -0,0 +1,40 @@
+package com.yc.videosqllite.disk.wrapper;
+
+import android.content.Context;
+
+import java.io.File;
+
+/**
+ * Creates an {@link com.bumptech.glide.disklrucache.DiskLruCache} based disk cache in the internal
+ * disk cache directory.
+ */
+// Public API.
+@SuppressWarnings({"WeakerAccess", "unused"})
+public final class InternalCacheDiskCacheFactory extends DiskLruCacheFactory {
+
+  public InternalCacheDiskCacheFactory(Context context) {
+    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR,
+        DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);
+  }
+
+  public InternalCacheDiskCacheFactory(Context context, long diskCacheSize) {
+    this(context, DiskCache.Factory.DEFAULT_DISK_CACHE_DIR, diskCacheSize);
+  }
+
+  public InternalCacheDiskCacheFactory(final Context context, final String diskCacheName,
+                                       long diskCacheSize) {
+    super(new CacheDirectoryGetter() {
+      @Override
+      public File getCacheDirectory() {
+        File cacheDirectory = context.getCacheDir();
+        if (cacheDirectory == null) {
+          return null;
+        }
+        if (diskCacheName != null) {
+          return new File(cacheDirectory, diskCacheName);
+        }
+        return cacheDirectory;
+      }
+    }, diskCacheSize);
+  }
+}

+ 42 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/Key.java

@@ -0,0 +1,42 @@
+package com.yc.videosqllite.disk.wrapper;
+
+
+import androidx.annotation.NonNull;
+
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+
+/**
+ * An interface that uniquely identifies some put of data. Implementations must implement {@link
+ * Object#equals(Object)} and {@link Object#hashCode()}. Implementations are generally expected to
+ * add all uniquely identifying information used in in {@link Object#equals(Object)}} and
+ * {@link Object#hashCode()}} to the given {@link MessageDigest} in {@link
+ * #updateDiskCacheKey(MessageDigest)}}, although this requirement is not as strict
+ * for partial cache key signatures.
+ */
+public interface Key {
+  String STRING_CHARSET_NAME = "UTF-8";
+  Charset CHARSET = Charset.forName(STRING_CHARSET_NAME);
+
+  /**
+   * Adds all uniquely identifying information to the given digest.
+   *
+   * <p> Note - Using {@link MessageDigest#reset()} inside of this method will result
+   * in undefined behavior. </p>
+   */
+  void updateDiskCacheKey(@NonNull MessageDigest messageDigest);
+
+  /**
+   * For caching to work correctly, implementations <em>must</em> implement this method and
+   * {@link #hashCode()}.
+   */
+  @Override
+  boolean equals(Object o);
+
+  /**
+   * For caching to work correctly, implementations <em>must</em> implement this method and
+   * {@link #equals(Object)}.
+   */
+  @Override
+  int hashCode();
+}

+ 54 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/Preconditions.java

@@ -0,0 +1,54 @@
+package com.yc.videosqllite.disk.wrapper;
+
+
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.Collection;
+
+/**
+ * Contains common assertions.
+ */
+public final class Preconditions {
+
+  private Preconditions() {
+    // Utility class.
+  }
+
+  public static void checkArgument(boolean expression, @NonNull String message) {
+    if (!expression) {
+      throw new IllegalArgumentException(message);
+    }
+  }
+
+  @NonNull
+  public static <T> T checkNotNull(@Nullable T arg) {
+    return checkNotNull(arg, "Argument must not be null");
+  }
+
+  @NonNull
+  public static <T> T checkNotNull(@Nullable T arg, @NonNull String message) {
+    if (arg == null) {
+      throw new NullPointerException(message);
+    }
+    return arg;
+  }
+
+  @NonNull
+  public static String checkNotEmpty(@Nullable String string) {
+    if (TextUtils.isEmpty(string)) {
+      throw new IllegalArgumentException("Must not be null or empty");
+    }
+    return string;
+  }
+
+  @NonNull
+  public static <T extends Collection<Y>, Y> T checkNotEmpty(@NonNull T collection) {
+    if (collection.isEmpty()) {
+      throw new IllegalArgumentException("Must not be empty.");
+    }
+    return collection;
+  }
+}

+ 23 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/SafeKeyGenerator.java

@@ -0,0 +1,23 @@
+package com.yc.videosqllite.disk.wrapper;
+
+import com.yc.videosqllite.cache.VideoLruCache;
+
+
+public class SafeKeyGenerator {
+
+  private final VideoLruCache<Key, String> loadIdToSafeHash = new VideoLruCache<>(1000);
+
+  public String getSafeKey(Key key) {
+    String safeKey;
+    synchronized (loadIdToSafeHash) {
+      safeKey = loadIdToSafeHash.get(key);
+    }
+    synchronized (loadIdToSafeHash) {
+      loadIdToSafeHash.put(key, safeKey);
+    }
+    return safeKey;
+  }
+
+
+
+}

+ 14 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/disk/wrapper/Synthetic.java

@@ -0,0 +1,14 @@
+package com.yc.videosqllite.disk.wrapper;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that target's visibility can be relaxed to avoid synthetic methods.
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.TYPE})
+public @interface Synthetic {
+}

+ 25 - 2
VideoSqlLite/src/main/java/com/yc/videosqllite/manager/CacheConfig.java

@@ -1,7 +1,6 @@
 package com.yc.videosqllite.manager;
 
-import com.yc.videosqllite.cache.InterCache;
-import com.yc.videosqllite.model.VideoLocation;
+import android.content.Context;
 
 /**
  * <pre>
@@ -33,6 +32,14 @@ public class CacheConfig {
      * 2,表示内存缓存+磁盘缓存
      */
     private int type = 0;
+    /**
+     * 上下文
+     */
+    private Context context;
+    /**
+     * 是否开启日志
+     */
+    private boolean isLog = false;
 
 
     public boolean isEffective() {
@@ -69,4 +76,20 @@ public class CacheConfig {
     public void setType(int type) {
         this.type = type;
     }
+
+    public Context getContext() {
+        return context;
+    }
+
+    public void setContext(Context context) {
+        this.context = context;
+    }
+
+    public boolean isLog() {
+        return isLog;
+    }
+
+    public void setLog(boolean log) {
+        isLog = log;
+    }
 }

+ 149 - 9
VideoSqlLite/src/main/java/com/yc/videosqllite/manager/LocationManager.java

@@ -1,8 +1,15 @@
 package com.yc.videosqllite.manager;
 
+import android.content.Context;
+import android.os.Debug;
+
 import com.yc.videosqllite.cache.VideoMapCache;
-import com.yc.videosqllite.dao.SqlLiteCache;
+import com.yc.videosqllite.disk.DiskFileUtils;
+import com.yc.videosqllite.disk.SqlLiteCache;
 import com.yc.videosqllite.model.VideoLocation;
+import com.yc.videosqllite.utils.CacheLogUtils;
+
+import java.io.IOException;
 
 /**
  * <pre>
@@ -29,7 +36,6 @@ public class LocationManager {
      * 10.将sql执行sql语句给简化,避免手写sql语句,因为特别容易出问题。而且存取bean如果比较复杂那很难搞
      */
 
-    private CacheConfig cacheConfig;
     /**
      * 内存缓存
      */
@@ -38,6 +44,8 @@ public class LocationManager {
      * 磁盘缓存
      */
     private SqlLiteCache sqlLiteCache;
+    private CacheConfig cacheConfig;
+
 
     private static class ManagerHolder {
         private static final LocationManager INSTANCE = new LocationManager();
@@ -51,6 +59,7 @@ public class LocationManager {
         this.cacheConfig = cacheConfig;
         videoMapCache = new VideoMapCache(cacheConfig);
         sqlLiteCache = new SqlLiteCache(cacheConfig);
+        CacheLogUtils.setIsLog(cacheConfig.isLog());
     }
 
     /**
@@ -59,7 +68,27 @@ public class LocationManager {
      * @param location                      视频数据
      */
     public synchronized void put(String url , VideoLocation location){
-        videoMapCache.put(url,location);
+        /*
+         * type
+         * 0,表示内存缓存
+         * 1,表示磁盘缓存
+         * 2,表示内存缓存+磁盘缓存
+         */
+        if (cacheConfig.getType() ==1){
+            //存储到磁盘中
+            sqlLiteCache.put(url,location);
+        } else if (cacheConfig.getType() ==2){
+            //存储到内存中
+            videoMapCache.put(url,location);
+            //存储到磁盘中
+            sqlLiteCache.put(url,location);
+        } else if (cacheConfig.getType()==0){
+            //存储到内存中
+            videoMapCache.put(url,location);
+        } else {
+            //存储到内存中
+            videoMapCache.put(url,location);
+        }
     }
 
     /**
@@ -68,7 +97,30 @@ public class LocationManager {
      * @return
      */
     public synchronized long get(String url){
-        long position = videoMapCache.get(url);
+        /*
+         * type
+         * 0,表示内存缓存
+         * 1,表示磁盘缓存
+         * 2,表示内存缓存+磁盘缓存
+         */
+        long position;
+        if (cacheConfig.getType() ==1){
+            //从磁盘中查找
+            position = sqlLiteCache.get(url);
+        } else if (cacheConfig.getType() ==2){
+            //先从内存中找
+            position = videoMapCache.get(url);
+            if (position<0){
+                //内存找不到,则从磁盘中查找
+                position = sqlLiteCache.get(url);
+            }
+        } else if (cacheConfig.getType()==0){
+            //先从内存中找
+            position = videoMapCache.get(url);
+        } else {
+            //先从内存中找
+            position = videoMapCache.get(url);
+        }
         return position;
     }
 
@@ -78,8 +130,23 @@ public class LocationManager {
      * @return
      */
     public synchronized boolean remove(String url){
-        boolean remove = videoMapCache.remove(url);
-        return remove;
+        /*
+         * type
+         * 0,表示内存缓存
+         * 1,表示磁盘缓存
+         * 2,表示内存缓存+磁盘缓存
+         */
+        if (cacheConfig.getType() ==1){
+            return sqlLiteCache.remove(url);
+        } else if (cacheConfig.getType() ==2){
+            boolean remove = videoMapCache.remove(url);
+            boolean removeSql = sqlLiteCache.remove(url);
+            return remove || removeSql;
+        } else if (cacheConfig.getType()==0){
+            return videoMapCache.remove(url);
+        } else {
+            return videoMapCache.remove(url);
+        }
     }
 
     /**
@@ -88,7 +155,26 @@ public class LocationManager {
      * @return
      */
     public synchronized boolean containsKey(String url){
-        boolean containsKey = videoMapCache.containsKey(url);
+        /*
+         * type
+         * 0,表示内存缓存
+         * 1,表示磁盘缓存
+         * 2,表示内存缓存+磁盘缓存
+         */
+        boolean containsKey;
+        if (cacheConfig.getType() ==1){
+            containsKey = sqlLiteCache.containsKey(url);
+        } else if (cacheConfig.getType() ==2){
+            containsKey = videoMapCache.containsKey(url);
+            if (!containsKey){
+                containsKey = sqlLiteCache.containsKey(url);
+                return containsKey;
+            }
+        } else if (cacheConfig.getType()==0){
+            containsKey = videoMapCache.containsKey(url);
+        } else {
+            containsKey = videoMapCache.containsKey(url);
+        }
         return containsKey;
     }
 
@@ -97,8 +183,62 @@ public class LocationManager {
      * @return                              是否清楚完毕
      */
     public synchronized boolean clearAll(){
-        boolean clearAll = videoMapCache.clearAll();
-        return clearAll;
+        /*
+         * type
+         * 0,表示内存缓存
+         * 1,表示磁盘缓存
+         * 2,表示内存缓存+磁盘缓存
+         */
+        if (cacheConfig.getType() ==1){
+            return sqlLiteCache.clearAll();
+        } else if (cacheConfig.getType() ==2){
+            boolean clearAll = videoMapCache.clearAll();
+            boolean all = sqlLiteCache.clearAll();
+            return clearAll && all;
+        } else if (cacheConfig.getType()==0){
+            return videoMapCache.clearAll();
+        } else {
+            return videoMapCache.clearAll();
+        }
+    }
+
+    /**
+     * 获取当前应用使用的内存
+     * @return
+     */
+    public long getUseMemory(){
+        long totalMemory = Runtime.getRuntime().totalMemory();
+        long freeMemory = Runtime.getRuntime().freeMemory();
+        //long maxMemory = Runtime.getRuntime().maxMemory();
+        long useMemory = totalMemory - freeMemory;
+        return useMemory;
+    }
+
+    /**
+     * 设定内存的阈值
+     * @param proportion                    比例
+     * @return
+     */
+    public long setMemoryThreshold(int proportion){
+        if (proportion<0 || proportion>10){
+            proportion = 2;
+        }
+        long totalMemory = Runtime.getRuntime().totalMemory();
+        long threshold = totalMemory / proportion;
+        return threshold;
+    }
+
+    /**
+     * 获取Java内存快照文件
+     * @param context
+     */
+    public void dumpHprofData(Context context){
+        String dump = DiskFileUtils.getPath(context, "dump");
+        try {
+            Debug.dumpHprofData(dump);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
     }
 
 }

+ 89 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/model/VideoLocation.java

@@ -1,7 +1,14 @@
 package com.yc.videosqllite.model;
 
 
+import android.os.Build;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
 import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * <pre>
@@ -31,6 +38,10 @@ public class VideoLocation implements Serializable {
      */
     private long totalTime;
 
+    public VideoLocation(){
+
+    }
+
     public VideoLocation(String url, long position, long totalTime) {
         this.url = url;
         this.position = position;
@@ -76,6 +87,37 @@ public class VideoLocation implements Serializable {
         this.totalTime = totalTime;
     }
 
+
+
+    public String toJson() {
+        JSONObject jsonObject= new JSONObject();
+        try {
+            jsonObject.put("url", getUrl());
+            jsonObject.put("urlMd5", getUrlMd5());
+            jsonObject.put("position", getPosition());
+            jsonObject.put("totalTime", getTotalTime());
+            return jsonObject.toString();
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static VideoLocation toObject(String jsonStr) {
+        VideoLocation m =  new VideoLocation();
+        try {
+            JSONObject jsonObject = new JSONObject(jsonStr);
+            m.setUrl(jsonObject.has("url") ? jsonObject.getString("url"):null);
+            m.setUrlMd5(jsonObject.has("urlMd5") ? jsonObject.getString("urlMd5"):null);
+            m.setPosition(jsonObject.has("position") ? jsonObject.getLong("position"):0);
+            m.setTotalTime(jsonObject.has("totalTime") ? jsonObject.getLong("totalTime"):0);
+            return m;
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        return m;
+    }
+
     @Override
     public String toString() {
         return "VideoLocation{" +
@@ -86,5 +128,52 @@ public class VideoLocation implements Serializable {
                 '}';
     }
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o){
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        VideoLocation location = (VideoLocation) o;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            return position == location.position &&
+                    totalTime == location.totalTime &&
+                    Objects.equals(url, location.url) &&
+                    Objects.equals(urlMd5, location.urlMd5);
+        } else {
+            return position == location.position &&
+                    totalTime == location.totalTime &&
+                    equals(url,location.url) &&
+                    equals(urlMd5,location.urlMd5);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            return Objects.hash(url, urlMd5, position, totalTime);
+        }
+        return hash(url,urlMd5,position,totalTime);
+    }
 
+    /**
+     * 比较两个对象
+     * @param a                         a对象
+     * @param b                         b对象
+     * @return
+     */
+    private boolean equals(Object a, Object b) {
+        return (a == b) || (a != null && a.equals(b));
+    }
+
+    /**
+     * hash算法
+     * @param values                    参数
+     * @return
+     */
+    private int hash(Object... values) {
+        return Arrays.hashCode(values);
+    }
 }

+ 71 - 0
VideoSqlLite/src/main/java/com/yc/videosqllite/utils/CacheLogUtils.java

@@ -0,0 +1,71 @@
+/*
+Copyright 2017 yangchong211(github.com/yangchong211)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package com.yc.videosqllite.utils;
+
+import android.util.Log;
+
+/**
+ * <pre>
+ *     @author yangchong
+ *     blog  : https://github.com/yangchong211
+ *     time  : 2017/10/21
+ *     desc  : log工具
+ *     revise:
+ * </pre>
+ */
+public final class CacheLogUtils {
+
+    private static final String TAG = "CacheLogUtils";
+    private static boolean isLog = false;
+
+    /**
+     * 设置是否开启日志
+     * @param isLog                 是否开启日志
+     */
+    public static void setIsLog(boolean isLog) {
+        CacheLogUtils.isLog = isLog;
+    }
+
+    public static boolean isIsLog() {
+        return isLog;
+    }
+
+    public static void d(String message) {
+        if(isLog){
+            Log.d(TAG, message);
+        }
+    }
+
+    public static void i(String message) {
+        if(isLog){
+            Log.i(TAG, message);
+        }
+
+    }
+
+    public static void e(String msg) {
+        if (isLog) {
+            Log.e(TAG, msg);
+        }
+    }
+
+    public static void e(String message, Throwable throwable) {
+        if(isLog){
+            Log.e(TAG, message, throwable);
+        }
+    }
+
+}

+ 0 - 1
settings.gradle

@@ -1,4 +1,3 @@
-include ':VideoSqlHelper'
 include ':VideoSqlLite'
 include ':VideoM3u8'
 include ':MusicPlayer'