diff --git a/app/src/main/java/com/example/xrecyclerview/httphelper.java b/app/src/main/java/com/example/xrecyclerview/httphelper.java new file mode 100644 index 0000000..19a69fe --- /dev/null +++ b/app/src/main/java/com/example/xrecyclerview/httphelper.java @@ -0,0 +1,199 @@ +package com.example.xrecyclerview; + +import android.app.Activity; +import android.os.Handler; + +import com.squareup.okhttp.Cache; +import com.squareup.okhttp.CacheControl; +import com.squareup.okhttp.Call; +import com.squareup.okhttp.Callback; +import com.squareup.okhttp.FormEncodingBuilder; +import com.squareup.okhttp.Headers; +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.MultipartBuilder; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.RequestBody; +import com.squareup.okhttp.Response; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.CookieManager; +import java.net.CookiePolicy; +import java.net.Proxy; +import java.net.SocketAddress; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.concurrent.TimeUnit; + +import cu.DeviceUtil; +import cu.Preferences; +import cu.db.config.ConfigUtil; + +/** + * Created by wang on 15/12/20. + */ +public class httphelper { + + private final String TAG = "httphelper"; + + private static final String contentType = "application/json;charset=UTF-8"; + public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); + + public static String DEV_HOST = "api-test.365hr.com"; + public static String RELEASE_HOST = "api.365hr.com"; + + //public static String BASE_URL_DEV = "http://m.hrloo.com/hrloo.php?"; + public static String BASE_URL_DEV = "http://eebochina.oicp.net:18080/hrloo.php?"; + public static String BASE_URL_RELEASE = "http://m.hrloo.com/hrloo.php?"; + public static String BASE_URL = "http://m.hrloo.com/hrloo.php?"; + + private static httphelper httphelperInstance; + private OkHttpClient mOkHttpClient; + private Handler hd; + private Activity activity; + private DeviceUtil mDeviceUtil; + + private httphelper() {} + + private httphelper(Activity activity) { + this.activity = activity; + this.mDeviceUtil = new DeviceUtil(activity); + mOkHttpClient = new OkHttpClient(); + //cookie enabled + mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER)); + hd = new Handler(activity.getMainLooper()); + if (BuildConfig.DEBUG) { + BASE_URL = BASE_URL_DEV; + } else { + BASE_URL = BASE_URL_RELEASE; + } + } + + public static httphelper getInstance(Activity activity) + { + if (httphelperInstance == null) + { + synchronized (httphelper.class) + { + if (httphelperInstance == null) + { + httphelperInstance = new httphelper(activity); + } + } + } + return httphelperInstance; + } + + private String getUrlEnd() { + // token,devid这二个参数以GET方式放在每次请求的URL后面,登录成功后服务器返回token,未登录时token可为空值,devid设备ID要求唯一由APP产生 + return "&m=mapi2&token=" + encode(ConfigUtil.getConfigValue(Preferences.TOKEN)) + "&devid=" + mDeviceUtil.getAndroidId(); + } + + public String requestUrl(String module, String method) { + return BASE_URL + "c=" + module + "&a=" + method + getUrlEnd(); + } + + + private void testCode() throws IOException { + OkHttpClient okHttpClient = new OkHttpClient(); + RequestBody requestBody = new MultipartBuilder() // 多模块 + .type(MultipartBuilder.FORM) + .addPart( + Headers.of("", ""), + RequestBody.create(JSON, "") + ) + .addFormDataPart("k", "v") + .build(); + RequestBody requestBodyJson = RequestBody.create(JSON, "json..."); // json串 + RequestBody requestBodyKV = new FormEncodingBuilder() // 键值对 + .add("k1", "v1") + .addEncoded("k2", "v2") + .build(); + final Request request = new Request.Builder() + .url("") + .header("User-Agent", "OkHttp Headers.java") + .addHeader("Accept", contentType) + .cacheControl(CacheControl.FORCE_CACHE) + .put(requestBody) + .post(requestBodyJson) + .post(requestBodyKV) + .get() + .tag("1") // OkHttpClient.cancel(tag)来取消所有带有这个tag的call + .build(); + int cacheSize = 10 * 1024 * 1024; // 10 MiB + Cache cache = new Cache(new File("filename"), cacheSize); + + okHttpClient.setConnectTimeout(15, TimeUnit.SECONDS); + okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS); + okHttpClient.setReadTimeout(30, TimeUnit.SECONDS); + okHttpClient.setCache(cache); + okHttpClient.setProxy(new Proxy(Proxy.Type.SOCKS, new SocketAddress() { + @Override + protected Object clone() throws CloneNotSupportedException { + return super.clone(); + } + })); + okHttpClient.setRetryOnConnectionFailure(true); + + Call call = okHttpClient.newCall(request); + call.enqueue(new Callback() { // 异步 + @Override + public void onFailure(Request request, IOException e) { + } + @Override + public void onResponse(Response response) throws IOException { + if (response.isSuccessful()) { + String res = response.body().string(); + InputStream inputStream = response.body().byteStream(); + Headers responseHeaders = response.headers(); + for (int i = 0; i < responseHeaders.size(); i++) { + System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); + } + } + } + }); + Response response = call.execute(); // 阻塞式 + if(response.isSuccessful()) {} + okHttpClient.cancel("1"); + } + + + + /** + * 参数编码 + * + * @return + */ + public static String encode(String s) { + if (s == null) { + return ""; + } + try { + return URLEncoder.encode(s, "UTF-8").replace("+", "%20").replace("*", "%2A") + .replace("%7E", "~").replace("#", "%23"); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + /** + * 参数反编码 + * + * @param s + * @return + */ + public static String decode(String s) { + if (s == null) { + return ""; + } + try { + return URLDecoder.decode(s, "utf-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + +} diff --git a/app/src/main/java/cu/DeviceUtil.java b/app/src/main/java/cu/DeviceUtil.java new file mode 100644 index 0000000..93ff1ec --- /dev/null +++ b/app/src/main/java/cu/DeviceUtil.java @@ -0,0 +1,336 @@ +package cu; + +import android.content.Context; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Build; +import android.provider.Settings.Secure; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.view.Display; +import android.view.WindowManager; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * 设备信息 + */ +public class DeviceUtil { + private String manufacturer; + private String model; + private String releaseVersion; + private String sdkVersion; + + private int displayWidth; + private int displayHeight; + + private String deviceId; + private String networkOperatorName; + private String networkOperator; + private String networkCountryISO; + private String simOperator; + private String simCountryISO; + private String simSerialNumber; + private String subscriberId; + // private String phoneNumber; + private String androidId; + private int dpi; + + private String localMacAddress; + + public DeviceUtil(Context context) { + getSysinfo(context); + } + + private void getSysinfo(Context context) { + this.manufacturer = Build.MANUFACTURER; + this.model = Build.MODEL; + this.releaseVersion = Build.VERSION.RELEASE; + this.sdkVersion = Build.VERSION.SDK; + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display d = wm.getDefaultDisplay(); + this.displayWidth = d.getWidth(); + this.displayHeight = d.getHeight(); + this.dpi = context.getResources().getDisplayMetrics().densityDpi; + + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + this.deviceId = tm.getDeviceId(); + this.networkOperatorName = tm.getNetworkOperatorName(); + this.networkOperator = tm.getNetworkOperator(); + this.networkCountryISO = tm.getNetworkCountryIso(); + this.simOperator = tm.getSimOperator(); + this.simCountryISO = tm.getSimCountryIso(); + this.simSerialNumber = tm.getSimSerialNumber(); + this.subscriberId = tm.getSubscriberId(); + // this.phoneNumber = tm.getLine1Number(); + + WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + WifiInfo info = wifi.getConnectionInfo(); + this.localMacAddress = info.getMacAddress(); + + this.androidId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID); + } + + /** + * @return 厂商 + */ + public String getManufacturer() { + return manufacturer; + } + + /** + * @return 产品型号 + */ + public String getModel() { + return model; + } + + /** + * @return 系统版本 + */ + public String getReleaseVersion() { + return releaseVersion; + } + + /** + * @return SDK版本 + */ + public String getSdkVersion() { + return sdkVersion; + } + + /** + * @return 屏幕宽 + */ + public int getDisplayWidth() { + return displayWidth; + } + + /** + * @return 屏幕高 + */ + public int getDisplayHeight() { + return displayHeight; + } + + /** + * @return IMEI + */ + public String getDeviceId() { + return deviceId; + } + + /** + * @return 网络服务提供名称 + */ + public String getNetworkOperatorName() { + return networkOperatorName; + } + + /** + * @return 网络服务提供 + */ + public String getNetworkOperator() { + return networkOperator; + } + + /** + * @return 网络服务提供商国家编码 + */ + public String getNetworkCountryISO() { + return networkCountryISO; + } + + /** + * @return SIM服务提供商 中国移动:46000&46002 中国联通:46001 中国电信:46003 + */ + public String getSimOperator() { + if (TextUtils.isEmpty(simOperator)) { + return "46000"; + } + return simOperator; + } + + /** + * @return SIM国家编码 + */ + public String getSimCountryISO() { + return simCountryISO; + } + + /** + * @return SIM 序列号 + */ + public String getSimSerialNumber() { + if (TextUtils.isEmpty(simSerialNumber)) { + return "000000"; + } + return simSerialNumber; + } + + /** + * @return IMSI + */ + public String getSubscriberId() { + if (TextUtils.isEmpty(subscriberId)) { + return "9"; + } + return "9" + subscriberId; + } + + /** + * @return 手机号码 + */ + /* + * public String getPhoneNumber() { return phoneNumber; } + */ + + /** + * 获取wifi mac地址 + * + * @return wifi mac地址(xx:xx:xx:xx:xx:xx) + */ + public String getLocalMacAddress() { + // if(TextUtils.isEmpty(localMacAddress)){ + // return localMacAddress;//mac[new Random().nextInt(10)]; + // } + // .replace(":", "") + return localMacAddress; + } + + public String buildUUID() { + //TODO 最后添加了时间 + String pid = + "86" + Build.BOARD.length() % 10 + Build.BRAND.length() % 10 + Build.CPU_ABI.length() % 10 + + Build.DEVICE.length() % 10 + Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 + + Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 + Build.MODEL.length() % 10 + + Build.PRODUCT.length() % 10 + Build.TAGS.length() % 10 + Build.TYPE.length() % 10 + + Build.USER.length() % 10 + System.currentTimeMillis(); + String lid = getDeviceId() + pid + getAndroidId() + getLocalMacAddress(); + + MessageDigest m = null; + try { + m = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + m.update(lid.getBytes(), 0, lid.length()); + byte p_md5Data[] = m.digest(); + + String uniqueID = new String(); + for (int i = 0; i < p_md5Data.length; i++) { + int b = (0xFF & p_md5Data[i]); + // if it is a single digit, make sure it have 0 in front (proper padding) + if (b <= 0xF) uniqueID += "0"; + // add number to string + uniqueID += Integer.toHexString(b); + } + uniqueID = uniqueID.toUpperCase(); + if (TextUtils.isEmpty(uniqueID) || "null".equals(uniqueID)) return buildUUID2(); + return uniqueID; + } + + private String buildUUID2() { + String pid = "86"; + + if (Build.BOARD != null) { + pid = pid + Build.BOARD.length() % 10; + } + if (Build.BRAND != null) { + pid = pid + Build.BRAND.length() % 10; + } + if (Build.CPU_ABI != null) { + pid = pid + Build.CPU_ABI.length() % 10; + } + if (Build.DEVICE != null) { + pid = pid + Build.DEVICE.length() % 10; + } + if (Build.DISPLAY != null) { + pid = pid + Build.DISPLAY.length() % 10; + } + if (Build.HOST != null) { + pid = pid + Build.HOST.length() % 10; + } + if (Build.ID != null) { + pid = pid + Build.ID.length() % 10; + } + if (Build.MANUFACTURER != null) { + pid = pid + Build.MANUFACTURER.length() % 10; + } + if (Build.MODEL != null) { + pid = pid + Build.MODEL.length() % 10; + } + if (Build.PRODUCT != null) { + pid = pid + Build.PRODUCT.length() % 10; + } + if (Build.TAGS != null) { + pid = pid + Build.TAGS.length() % 10; + } + if (Build.TYPE != null) { + pid = pid + Build.TYPE.length() % 10; + } + if (Build.USER != null) { + pid = pid + Build.USER.length() % 10; + } + + String lid = getDeviceId() + pid + getAndroidId() + getLocalMacAddress(); + + MessageDigest m = null; + + try { + m = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + m.update(lid.getBytes(), 0, lid.length()); + byte p_md5Data[] = m.digest(); + + String uniqueID = new String(); + for (int i = 0; i < p_md5Data.length; i++) { + int b = (0xFF & p_md5Data[i]); + // if it is a single digit, make sure it have 0 in front (proper padding) + if (b <= 0xF) uniqueID += "0"; + // add number to string + uniqueID += Integer.toHexString(b); + } + + uniqueID = uniqueID.toUpperCase(); + + return uniqueID; + } + + public String getAndroidId() { + return androidId; + } + + public void setAndroidId(String androidId) { + this.androidId = androidId; + } + + @Override + public String toString() { + return "DeviceId: " + getDeviceId() + " || DisplayHeight: " + getDisplayHeight() + + " || DisplayWidth: " + getDisplayWidth() + " || Manufacturer: " + getManufacturer() + + " || Model: " + getModel() + " || NetworkCountryISO: " + getNetworkCountryISO() + + " || NetworkOperator: " + + getNetworkOperator() + + " || NetworkOperatorName: " + + getNetworkOperatorName() + // +" || PhoneNumber: "+getPhoneNumber() + + " || ReleaseVersion: " + getReleaseVersion() + " || SdkVersion: " + getSdkVersion() + + " || SimCountryISO: " + getSimCountryISO() + " || SimOperator: " + getSimOperator() + + " || SimSerialNumber: " + getSimSerialNumber() + " || SubscriberId: " + getSubscriberId() + + " || LocalMacAddress: " + getLocalMacAddress(); + } + + public int getDpi() { + return dpi; + } + + public void setDpi(int dpi) { + this.dpi = dpi; + } + + +} diff --git a/app/src/main/java/cu/Preferences.java b/app/src/main/java/cu/Preferences.java new file mode 100644 index 0000000..4cb8192 --- /dev/null +++ b/app/src/main/java/cu/Preferences.java @@ -0,0 +1,26 @@ +package cu; + +/** + * Created by Wang on 2015/10/28. + */ +public class Preferences { + + // DEBUG调试模式 +// public static boolean DEBUG = true; + + public static final String UUID = "uuid"; + + public static final String KEYS = "keys"; // 设备注册后的标识 + //public static final String APPKEY = "appkey"; // header中固定参数,由服务端产生 + public static final String TOKEN = "token"; // 登录成功后服务器返回token,每次请求放在URL的后面 + + public static final String PUNCH_REMIND_TIME = "punc_remind_time"; // 每日打卡提醒 + + // 首次使用 + public static final String NOT_FIRST_USE_APP = "not_first_use_app"; + + // setActiveDeviceFlag这个接口,是一次性调用的,这个接口是当用户正式登录进去应用程序,第一次正式使用的时候调用。 + public static final String SET_ACTIVE_DEVICE_FLAG = "set_active_device_flag"; + + +} diff --git a/app/src/main/java/cu/db/DaoMaster.java b/app/src/main/java/cu/db/DaoMaster.java new file mode 100644 index 0000000..f592340 --- /dev/null +++ b/app/src/main/java/cu/db/DaoMaster.java @@ -0,0 +1,97 @@ +package cu.db; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDatabase.CursorFactory; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +import cu.db.Migration.AbstractMigratorHelper; +import cu.db.cache.CacheDao; +import cu.db.config.ConfigDao; +import de.greenrobot.dao.AbstractDaoMaster; +import de.greenrobot.dao.identityscope.IdentityScopeType; + + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. + +/** + * Master of DAO (schema version 1): knows all DAOs. +*/ +public class DaoMaster extends AbstractDaoMaster { + public static final int SCHEMA_VERSION = 3; + + /** Creates underlying database table using DAOs. */ + public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) { + ConfigDao.createTable(db, ifNotExists); + CacheDao.createTable(db, ifNotExists); + } + + /** Drops underlying database table using DAOs. */ + public static void dropAllTables(SQLiteDatabase db, boolean ifExists) { + ConfigDao.dropTable(db, ifExists); + CacheDao.dropTable(db, ifExists); + } + + public static abstract class OpenHelper extends SQLiteOpenHelper { + + public OpenHelper(Context context, String name, CursorFactory factory) { + super(context, name, factory, SCHEMA_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION); + createAllTables(db, false); + } + } + + /** WARNING: Drops all table on Upgrade! Use only during development. */ + public static class DevOpenHelper extends OpenHelper { + public DevOpenHelper(Context context, String name, CursorFactory factory) { + super(context, name, factory); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables"); +// dropAllTables(db, true); +// onCreate(db); + + + /* i represent the version where the user is now and the class named with this number implies that is upgrading from i to i++ schema */ + for (int i = oldVersion; i < newVersion; i++) { + try { + /* New instance of the class that migrates from i version to i++ version named DBMigratorHelper{version that the db has on this moment} */ + AbstractMigratorHelper migratorHelper = (AbstractMigratorHelper) Class.forName("com.commons.support.db.Migration.DBMigrationHelper" + i).newInstance(); + if (migratorHelper != null) { + System.out.println("greenDAO.11111111111111"); + /* Upgrade de db */ + migratorHelper.onUpgrade(db); + } + } catch (ClassNotFoundException | ClassCastException | IllegalAccessException | InstantiationException e) { + Log.e("greenDAO", "Could not migrate from schema from schema: " + i + " to " + i++); + /* If something fail prevent the DB to be updated to future version if the previous version has not been upgraded successfully */ + break; + } + } + + + } + } + + public DaoMaster(SQLiteDatabase db) { + super(db, SCHEMA_VERSION); + registerDaoClass(ConfigDao.class); + registerDaoClass(CacheDao.class); + } + + public DaoSession newSession() { + return new DaoSession(db, IdentityScopeType.Session, daoConfigMap); + } + + public DaoSession newSession(IdentityScopeType type) { + return new DaoSession(db, type, daoConfigMap); + } + +} diff --git a/app/src/main/java/cu/db/DaoSession.java b/app/src/main/java/cu/db/DaoSession.java new file mode 100644 index 0000000..242d0b5 --- /dev/null +++ b/app/src/main/java/cu/db/DaoSession.java @@ -0,0 +1,62 @@ +package cu.db; + +import android.database.sqlite.SQLiteDatabase; + +import java.util.Map; + +import cu.db.cache.Cache; +import cu.db.cache.CacheDao; +import cu.db.config.Config; +import cu.db.config.ConfigDao; +import de.greenrobot.dao.AbstractDao; +import de.greenrobot.dao.AbstractDaoSession; +import de.greenrobot.dao.identityscope.IdentityScopeType; +import de.greenrobot.dao.internal.DaoConfig; + + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. + +/** + * {@inheritDoc} + * + * @see AbstractDaoSession + */ +public class DaoSession extends AbstractDaoSession { + + private final DaoConfig configDaoConfig; + private final DaoConfig cacheDaoConfig; + + private final ConfigDao configDao; + private final CacheDao cacheDao; + + public DaoSession(SQLiteDatabase db, IdentityScopeType type, Map>, DaoConfig> + daoConfigMap) { + super(db); + + configDaoConfig = daoConfigMap.get(ConfigDao.class).clone(); + configDaoConfig.initIdentityScope(type); + + cacheDaoConfig = daoConfigMap.get(CacheDao.class).clone(); + cacheDaoConfig.initIdentityScope(type); + + configDao = new ConfigDao(configDaoConfig, this); + cacheDao = new CacheDao(cacheDaoConfig, this); + + registerDao(Config.class, configDao); + registerDao(Cache.class, cacheDao); + } + + public void clear() { + configDaoConfig.getIdentityScope().clear(); + cacheDaoConfig.getIdentityScope().clear(); + } + + public ConfigDao getConfigDao() { + return configDao; + } + + public CacheDao getCacheDao() { + return cacheDao; + } + +} diff --git a/app/src/main/java/cu/db/DaoUtil.java b/app/src/main/java/cu/db/DaoUtil.java new file mode 100644 index 0000000..02d40b9 --- /dev/null +++ b/app/src/main/java/cu/db/DaoUtil.java @@ -0,0 +1,47 @@ +package cu.db; + +import android.content.Context; + +import cu.db.cache.CacheDB; +import cu.db.config.ConfigUtil; + + +/** + * Created by qianjin on 2015/9/29. + */ +public class DaoUtil { + + + private static DaoMaster daoMaster; + private static DaoSession daoSession; + public static final String DB_NAME = "m_android_db"; + + /** + * 使用Db前需init + * @param context + */ + public static void init(Context context) { + daoSession = getDaoSession(context); + ConfigUtil.init(context); + CacheDB.init(context); + } + + private static DaoMaster getDaoMaster(Context context) { + if (daoMaster == null) { + DaoMaster.OpenHelper helper = new DaoMaster.DevOpenHelper(context, DB_NAME, null); + daoMaster = new DaoMaster(helper.getWritableDatabase()); + } + return daoMaster; + } + + public static DaoSession getDaoSession(Context context) { + if (daoSession == null) { + if (daoMaster == null) { + daoMaster = getDaoMaster(context); + } + daoSession = daoMaster.newSession(); + } + return daoSession; + } + +} diff --git a/app/src/main/java/cu/db/Migration/AbstractMigratorHelper.java b/app/src/main/java/cu/db/Migration/AbstractMigratorHelper.java new file mode 100644 index 0000000..15b1de6 --- /dev/null +++ b/app/src/main/java/cu/db/Migration/AbstractMigratorHelper.java @@ -0,0 +1,12 @@ +package cu.db.Migration; + +import android.database.sqlite.SQLiteDatabase; + +/** + * Created by User on 2015/9/30. + */ +public abstract class AbstractMigratorHelper { + + public abstract void onUpgrade(SQLiteDatabase db); + +} diff --git a/app/src/main/java/cu/db/Migration/DBMigrationHelper1.java b/app/src/main/java/cu/db/Migration/DBMigrationHelper1.java new file mode 100644 index 0000000..18ae6d0 --- /dev/null +++ b/app/src/main/java/cu/db/Migration/DBMigrationHelper1.java @@ -0,0 +1,34 @@ +package cu.db.Migration; + +import android.database.sqlite.SQLiteDatabase; + +/** + * Created by User on 2015/9/30. + */ +public class DBMigrationHelper1 extends AbstractMigratorHelper { + + @Override + public void onUpgrade(SQLiteDatabase db) { + + /* Create a temporal table where you will copy all the data from the previous table that you need to modify with a non supported sqlite operation */ + db.execSQL("CREATE TABLE \"CONFIG2\" (" + // + "\"_id\" INTEGER PRIMARY KEY ," + // 0: id + "\"KEY\" TEXT NOT NULL ," + // 1: key + "\"VALUE\" TEXT NOT NULL );"); // 2: value + + /* Copy the data from one table to the new one */ + db.execSQL("INSERT INTO CONFIG2 (_id, KEY, VALUE)" + + " SELECT _id, KEY, VALUE FROM CONFIG;"); + + /* Delete the previous table */ + db.execSQL("DROP TABLE CONFIG"); + /* Rename the just created table to the one that I have just deleted */ + db.execSQL("ALTER TABLE CONFIG2 RENAME TO CONFIG"); + + /* Add Index/es if you want them */ +// db.execSQL("CREATE INDEX " + "IDX_post_USER_ID ON CONFIG" + +// " (KEY);"); + //Example sql statement + db.execSQL("ALTER TABLE CONFIG ADD COLUMN COLUMNTEST TEXT"); + } +} diff --git a/app/src/main/java/cu/db/Migration/DBMigrationHelper2.java b/app/src/main/java/cu/db/Migration/DBMigrationHelper2.java new file mode 100644 index 0000000..748380b --- /dev/null +++ b/app/src/main/java/cu/db/Migration/DBMigrationHelper2.java @@ -0,0 +1,35 @@ +package cu.db.Migration; + +import android.database.sqlite.SQLiteDatabase; + +/** + * Created by User on 2015/9/30. + */ +public class DBMigrationHelper2 extends AbstractMigratorHelper { + + @Override + public void onUpgrade(SQLiteDatabase db) { + + /* Create a temporal table where you will copy all the data from the previous table that you need to modify with a non supported sqlite operation */ + db.execSQL("CREATE TABLE \"CONFIG2\" (" + // + "\"_id\" INTEGER PRIMARY KEY ," + // 0: id + "\"KEY\" TEXT NOT NULL ," + // 1: key + "\"VALUE\" TEXT NOT NULL ," + // 1: key + "\"COLUMNTEST\" TEXT );"); // 2: value + + /* Copy the data from one table to the new one */ + db.execSQL("INSERT INTO CONFIG2 (_id, KEY, VALUE)" + + " SELECT _id, KEY, VALUE FROM CONFIG;"); + + /* Delete the previous table */ + db.execSQL("DROP TABLE CONFIG"); + /* Rename the just created table to the one that I have just deleted */ + db.execSQL("ALTER TABLE CONFIG2 RENAME TO CONFIG"); + + /* Add Index/es if you want them */ +// db.execSQL("CREATE INDEX " + "IDX_post_USER_ID ON CONFIG" + +// " (KEY);"); + //Example sql statement + db.execSQL("ALTER TABLE CONFIG ADD COLUMN COLUMNTEST2 TEXT"); + } +} diff --git a/app/src/main/java/cu/db/MigrationHelper.java b/app/src/main/java/cu/db/MigrationHelper.java new file mode 100644 index 0000000..b0849d5 --- /dev/null +++ b/app/src/main/java/cu/db/MigrationHelper.java @@ -0,0 +1,157 @@ +package cu.db;//package com.commons.support.db; +// +//import android.database.Cursor; +//import android.database.sqlite.SQLiteDatabase; +//import android.text.TextUtils; +//import android.util.Log; +// +// +//import java.util.ArrayList; +//import java.util.Arrays; +//import java.util.List; +// +//import de.greenrobot.dao.AbstractDao; +//import de.greenrobot.dao.internal.DaoConfig; +// +// +///** +// * Created by pokawa on 18/05/15. +// */ +//public class MigrationHelper { +// +// private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS"; +// private static MigrationHelper instance; +// +// public static MigrationHelper getInstance() { +// if(instance == null) { +// instance = new MigrationHelper(); +// } +// return instance; +// } +// +// public void migrate(SQLiteDatabase db, Class>... daoClasses) { +// generateTempTables(db, daoClasses); +// DaoMaster.dropAllTables(db, true); +// DaoMaster.createAllTables(db, false); +// restoreData(db, daoClasses); +// } +// +// private void generateTempTables(SQLiteDatabase db, Class>... daoClasses) { +// for(int i = 0; i < daoClasses.length; i++) { +// DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]); +// +// String divider = ""; +// String tableName = daoConfig.tablename; +// String tempTableName = daoConfig.tablename.concat("_TEMP"); +// ArrayList properties = new ArrayList<>(); +// +// StringBuilder createTableStringBuilder = new StringBuilder(); +// +// createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" ("); +// +// for(int j = 0; j < daoConfig.properties.length; j++) { +// String columnName = daoConfig.properties[j].columnName; +// +// if(getColumns(db, tableName).contains(columnName)) { +// properties.add(columnName); +// +// String type = null; +// +// try { +// type = getTypeByClass(daoConfig.properties[j].type); +// } catch (Exception exception) { +// //Crashlytics.logException(exception); +// exception.printStackTrace(); +// } +// +// createTableStringBuilder.append(divider).append(columnName).append(" ").append(type); +// +// if(daoConfig.properties[j].primaryKey) { +// createTableStringBuilder.append(" PRIMARY KEY"); +// } +// +// divider = ","; +// } +// } +// createTableStringBuilder.append(");"); +// +// db.execSQL(createTableStringBuilder.toString()); +// +// StringBuilder insertTableStringBuilder = new StringBuilder(); +// +// insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" ("); +// insertTableStringBuilder.append(TextUtils.join(",", properties)); +// insertTableStringBuilder.append(") SELECT "); +// insertTableStringBuilder.append(TextUtils.join(",", properties)); +// insertTableStringBuilder.append(" FROM ").append(tableName).append(";"); +// +// db.execSQL(insertTableStringBuilder.toString()); +// } +// } +// +// private void restoreData(SQLiteDatabase db, Class>... daoClasses) { +// for(int i = 0; i < daoClasses.length; i++) { +// DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]); +// +// String tableName = daoConfig.tablename; +// String tempTableName = daoConfig.tablename.concat("_TEMP"); +// ArrayList properties = new ArrayList(); +// +// for (int j = 0; j < daoConfig.properties.length; j++) { +// String columnName = daoConfig.properties[j].columnName; +// +// if(getColumns(db, tempTableName).contains(columnName)) { +// properties.add(columnName); +// } +// } +// +// StringBuilder insertTableStringBuilder = new StringBuilder(); +// +// insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" ("); +// insertTableStringBuilder.append(TextUtils.join(",", properties)); +// insertTableStringBuilder.append(") SELECT "); +// insertTableStringBuilder.append(TextUtils.join(",", properties)); +// insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";"); +// +// StringBuilder dropTableStringBuilder = new StringBuilder(); +// +// dropTableStringBuilder.append("DROP TABLE ").append(tempTableName); +// +// db.execSQL(insertTableStringBuilder.toString()); +// db.execSQL(dropTableStringBuilder.toString()); +// } +// } +// +// private String getTypeByClass(Class type) throws Exception { +// if(type.equals(String.class)) { +// return "TEXT"; +// } +// if(type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) { +// return "INTEGER"; +// } +// if(type.equals(Boolean.class)) { +// return "BOOLEAN"; +// } +// +// Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString())); +// throw exception; +// } +// +// private static List getColumns(SQLiteDatabase db, String tableName) { +// List columns = new ArrayList<>(); +// Cursor cursor = null; +// try { +// cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null); +// if (cursor != null) { +// columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames())); +// } +// } catch (Exception e) { +// Log.v(tableName, e.getMessage(), e); +// e.printStackTrace(); +// } finally { +// if (cursor != null) +// cursor.close(); +// } +// return columns; +// } +//} \ No newline at end of file diff --git a/app/src/main/java/cu/db/cache/Cache.java b/app/src/main/java/cu/db/cache/Cache.java new file mode 100644 index 0000000..63abc06 --- /dev/null +++ b/app/src/main/java/cu/db/cache/Cache.java @@ -0,0 +1,113 @@ +package cu.db.cache; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. Enable "keep" sections if you want to edit. + +/** + * Entity mapped to table "CACHE". + */ +public class Cache { + + private Long id; + /** + * Not-null value. + */ + private String key; + /** + * Not-null value. + */ + private String value; + private Long timeout; + private Long currentTime; + + public Cache() { + } + + public Cache(Long id) { + this.id = id; + } + + public Cache(Long id, String key, String value, Long timeout, Long currentTime) { + this.id = id; + this.key = key; + this.value = value; + this.timeout = timeout; + this.currentTime = currentTime; + } + + public Cache(String key, String value) { + this.key = key; + this.value = value; + this.currentTime = System.currentTimeMillis(); + } + + public Cache(String key, String value, long timeout) { + this.key = key; + this.value = value; + this.timeout = timeout; + this.currentTime = System.currentTimeMillis(); + } + + public boolean isTimeout(){ + if (timeout == 0) { + return false; + } + if (System.currentTimeMillis() - currentTime < timeout) { + return false; + } + return true; + } + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + /** + * Not-null value. + */ + public String getKey() { + return key; + } + + /** + * Not-null value; ensure this value is available before it is saved to the database. + */ + public void setKey(String key) { + this.key = key; + } + + /** + * Not-null value. + */ + public String getValue() { + return value; + } + + /** + * Not-null value; ensure this value is available before it is saved to the database. + */ + public void setValue(String value) { + this.value = value; + } + + public Long getTimeout() { + return timeout; + } + + public void setTimeout(Long timeout) { + this.timeout = timeout; + } + + public Long getCurrentTime() { + return currentTime; + } + + public void setCurrentTime(Long currentTime) { + this.currentTime = currentTime; + } + +} diff --git a/app/src/main/java/cu/db/cache/CacheDB.java b/app/src/main/java/cu/db/cache/CacheDB.java new file mode 100644 index 0000000..67a6840 --- /dev/null +++ b/app/src/main/java/cu/db/cache/CacheDB.java @@ -0,0 +1,103 @@ +package cu.db.cache; + +import android.content.Context; +import android.text.TextUtils; + +import cu.db.DaoUtil; +import de.greenrobot.dao.query.DeleteQuery; +import de.greenrobot.dao.query.QueryBuilder; + +/** + * Created by qianjin on 2015/9/29. + */ +public class CacheDB { + + private static CacheDao cacheDao; + + public static final long CACHE_DAY = 3600 * 1000 * 24; + public static final long CACHE_HOUR = 3600 * 1000; + public static final long CACHE_MIN = 60 * 1000; + + + public static void init(Context context) { + cacheDao = DaoUtil.getDaoSession(context).getCacheDao(); + } + + + + + + + public static void save(Cache cache) { + Cache savedCache = getCache(cache.getKey()); + if (savedCache == null) { + cacheDao.insertOrReplace(cache); + } else { + savedCache.setValue(cache.getValue()); + savedCache.setCurrentTime(System.currentTimeMillis()); + savedCache.setTimeout(cache.getTimeout()); + cacheDao.insertOrReplace(savedCache); + } + } + + public static Cache getCache(String key) { + QueryBuilder qb = cacheDao.queryBuilder(); + qb.where(CacheDao.Properties.Key.eq(key)); + Cache cache = (Cache) qb.unique(); + if (cache == null) { + cache = new Cache(key, ""); + } else { + //timeout + if (cache.isTimeout()) { + delete(key); + cache = new Cache(key, ""); + } + } + return cache; + } + + public static String getCacheValue(String key) { + if (TextUtils.isEmpty(key)) { + return ""; + } + QueryBuilder qb = cacheDao.queryBuilder(); + qb.where(CacheDao.Properties.Key.eq(key)); + Cache cache = (Cache) qb.unique(); + if (cache == null) { + return ""; + } else { + if (cache.isTimeout()) { + delete(key); + return ""; + } + } + return cache.getValue(); + } + + + public static void deleteAll() { + cacheDao.deleteAll(); + } + + public static void delete(String key) { + QueryBuilder qb = cacheDao.queryBuilder(); + DeleteQuery bd = qb.where(CacheDao.Properties.Key.eq(key)).buildDelete(); + bd.executeDeleteWithoutDetachingEntities(); + //or + //Config config = getConfig(key); + //configDao.delete(config); + } + + public static boolean exist(String key) { + QueryBuilder qb = cacheDao.queryBuilder(); + qb.where(CacheDao.Properties.Key.eq(key)); + long cnt = qb.count(); + return cnt > 0 ? true : false; + } + + private static long currentTime() { + return System.currentTimeMillis(); + } + + +} diff --git a/app/src/main/java/cu/db/cache/CacheDao.java b/app/src/main/java/cu/db/cache/CacheDao.java new file mode 100644 index 0000000..0f8054b --- /dev/null +++ b/app/src/main/java/cu/db/cache/CacheDao.java @@ -0,0 +1,134 @@ +package cu.db.cache; + +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteStatement; + +import cu.db.DaoSession; +import de.greenrobot.dao.AbstractDao; +import de.greenrobot.dao.Property; +import de.greenrobot.dao.internal.DaoConfig; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. + +/** + * DAO for table "CACHE". +*/ +public class CacheDao extends AbstractDao { + + public static final String TABLENAME = "CACHE"; + + /** + * Properties of entity Cache.
+ * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property Id = new Property(0, Long.class, "id", true, "_id"); + public final static Property Key = new Property(1, String.class, "key", false, "KEY"); + public final static Property Value = new Property(2, String.class, "value", false, "VALUE"); + public final static Property Timeout = new Property(3, Long.class, "timeout", false, "TIMEOUT"); + public final static Property CurrentTime = new Property(4, Long.class, "currentTime", false, "CURRENT_TIME"); + }; + + + public CacheDao(DaoConfig config) { + super(config); + } + + public CacheDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + } + + /** Creates the underlying database table. */ + public static void createTable(SQLiteDatabase db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "\"CACHE\" (" + // + "\"_id\" INTEGER PRIMARY KEY ," + // 0: id + "\"KEY\" TEXT NOT NULL ," + // 1: key + "\"VALUE\" TEXT NOT NULL ," + // 2: value + "\"TIMEOUT\" INTEGER," + // 3: timeout + "\"CURRENT_TIME\" INTEGER);"); // 4: currentTime + } + + /** Drops the underlying database table. */ + public static void dropTable(SQLiteDatabase db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"CACHE\""; + db.execSQL(sql); + } + + /** @inheritdoc */ + @Override + protected void bindValues(SQLiteStatement stmt, Cache entity) { + stmt.clearBindings(); + + Long id = entity.getId(); + if (id != null) { + stmt.bindLong(1, id); + } + stmt.bindString(2, entity.getKey()); + stmt.bindString(3, entity.getValue()); + + Long timeout = entity.getTimeout(); + if (timeout != null) { + stmt.bindLong(4, timeout); + } + + Long currentTime = entity.getCurrentTime(); + if (currentTime != null) { + stmt.bindLong(5, currentTime); + } + } + + /** @inheritdoc */ + @Override + public Long readKey(Cursor cursor, int offset) { + return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0); + } + + /** @inheritdoc */ + @Override + public Cache readEntity(Cursor cursor, int offset) { + Cache entity = new Cache( // + cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id + cursor.getString(offset + 1), // key + cursor.getString(offset + 2), // value + cursor.isNull(offset + 3) ? null : cursor.getLong(offset + 3), // timeout + cursor.isNull(offset + 4) ? null : cursor.getLong(offset + 4) // currentTime + ); + return entity; + } + + /** @inheritdoc */ + @Override + public void readEntity(Cursor cursor, Cache entity, int offset) { + entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0)); + entity.setKey(cursor.getString(offset + 1)); + entity.setValue(cursor.getString(offset + 2)); + entity.setTimeout(cursor.isNull(offset + 3) ? null : cursor.getLong(offset + 3)); + entity.setCurrentTime(cursor.isNull(offset + 4) ? null : cursor.getLong(offset + 4)); + } + + /** @inheritdoc */ + @Override + protected Long updateKeyAfterInsert(Cache entity, long rowId) { + entity.setId(rowId); + return rowId; + } + + /** @inheritdoc */ + @Override + public Long getKey(Cache entity) { + if(entity != null) { + return entity.getId(); + } else { + return null; + } + } + + /** @inheritdoc */ + @Override + protected boolean isEntityUpdateable() { + return true; + } + +} diff --git a/app/src/main/java/cu/db/config/Config.java b/app/src/main/java/cu/db/config/Config.java new file mode 100644 index 0000000..8b2477c --- /dev/null +++ b/app/src/main/java/cu/db/config/Config.java @@ -0,0 +1,61 @@ +package cu.db.config; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. Enable "keep" sections if you want to edit. +/** + * Entity mapped to table "CONFIG". + */ +public class Config { + + private Long id; + /** Not-null value. */ + private String key; + /** Not-null value. */ + private String value; + + public Config() { + } + + public Config(Long id) { + this.id = id; + } + + public Config(Long id, String key, String value) { + this.id = id; + this.key = key; + this.value = value; + } + + public Config(String key, String value) { + this.key = key; + this.value = value; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + /** Not-null value. */ + public String getKey() { + return key; + } + + /** Not-null value; ensure this value is available before it is saved to the database. */ + public void setKey(String key) { + this.key = key; + } + + /** Not-null value. */ + public String getValue() { + return value; + } + + /** Not-null value; ensure this value is available before it is saved to the database. */ + public void setValue(String value) { + this.value = value; + } + +} diff --git a/app/src/main/java/cu/db/config/ConfigDao.java b/app/src/main/java/cu/db/config/ConfigDao.java new file mode 100644 index 0000000..aa39a37 --- /dev/null +++ b/app/src/main/java/cu/db/config/ConfigDao.java @@ -0,0 +1,117 @@ +package cu.db.config; + +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteStatement; + +import cu.db.DaoSession; +import de.greenrobot.dao.AbstractDao; +import de.greenrobot.dao.Property; +import de.greenrobot.dao.internal.DaoConfig; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. + +/** + * DAO for table "CONFIG". +*/ +public class ConfigDao extends AbstractDao { + + public static final String TABLENAME = "CONFIG"; + + /** + * Properties of entity Config.
+ * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property Id = new Property(0, Long.class, "id", true, "_id"); + public final static Property Key = new Property(1, String.class, "key", false, "KEY"); + public final static Property Value = new Property(2, String.class, "value", false, "VALUE"); + }; + + + public ConfigDao(DaoConfig config) { + super(config); + } + + public ConfigDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + } + + /** Creates the underlying database table. */ + public static void createTable(SQLiteDatabase db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "\"CONFIG\" (" + // + "\"_id\" INTEGER PRIMARY KEY ," + // 0: id + "\"KEY\" TEXT NOT NULL ," + // 1: key + "\"VALUE\" TEXT NOT NULL );"); // 2: value + } + + /** Drops the underlying database table. */ + public static void dropTable(SQLiteDatabase db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"CONFIG\""; + db.execSQL(sql); + } + + /** @inheritdoc */ + @Override + protected void bindValues(SQLiteStatement stmt, Config entity) { + stmt.clearBindings(); + + Long id = entity.getId(); + if (id != null) { + stmt.bindLong(1, id); + } + stmt.bindString(2, entity.getKey()); + stmt.bindString(3, entity.getValue()); + + } + + /** @inheritdoc */ + @Override + public Long readKey(Cursor cursor, int offset) { + return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0); + } + + /** @inheritdoc */ + @Override + public Config readEntity(Cursor cursor, int offset) { + Config entity = new Config( // + cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id + cursor.getString(offset + 1), // key + cursor.getString(offset + 2) // value + ); + return entity; + } + + /** @inheritdoc */ + @Override + public void readEntity(Cursor cursor, Config entity, int offset) { + entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0)); + entity.setKey(cursor.getString(offset + 1)); + entity.setValue(cursor.getString(offset + 2)); + } + + /** @inheritdoc */ + @Override + protected Long updateKeyAfterInsert(Config entity, long rowId) { + entity.setId(rowId); + return rowId; + } + + /** @inheritdoc */ + @Override + public Long getKey(Config entity) { + if(entity != null) { + return entity.getId(); + } else { + return null; + } + } + + /** @inheritdoc */ + @Override + protected boolean isEntityUpdateable() { + return true; + } + +} diff --git a/app/src/main/java/cu/db/config/ConfigUtil.java b/app/src/main/java/cu/db/config/ConfigUtil.java new file mode 100644 index 0000000..fb60c3c --- /dev/null +++ b/app/src/main/java/cu/db/config/ConfigUtil.java @@ -0,0 +1,124 @@ +package cu.db.config; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.TextUtils; + +import com.alibaba.fastjson.JSON; + +import cu.db.DaoUtil; +import de.greenrobot.dao.query.DeleteQuery; +import de.greenrobot.dao.query.QueryBuilder; + +/** + * Created by qianjin on 2015/9/7. + */ +public class ConfigUtil { + + private static ConfigDao configDao; + + /** + * 使用ConfigUtil前需init + * + * @param context + */ + public static void init(Context context) { + configDao = DaoUtil.getDaoSession(context).getConfigDao(); + } + + + public static void save(Config config) { + Config savedConfig = getConfig(config.getKey()); + if (savedConfig == null) { // 不会出现为空的情况 + configDao.insertOrReplace(config); + } else { + savedConfig.setValue(config.getValue()); + configDao.insertOrReplace(savedConfig); + } + } + + public static void save(String key, String value) { + Config config = new Config(key, value); + save(config); + } + + public static void save(String key, int value) { + save(key, String.valueOf(value)); + } + + public static void save(String key, boolean value) { + save(key, String.valueOf(value)); + } + + public static Config getConfig(String key) { + QueryBuilder qb = configDao.queryBuilder(); + qb.where(ConfigDao.Properties.Key.eq(key)); + Config config = (Config) qb.unique(); + if (config == null) { + config = new Config(key, "no data"); + } + return config; + } + + public static String getConfigValue(String key) { + QueryBuilder qb = configDao.queryBuilder(); + qb.where(ConfigDao.Properties.Key.eq(key)); + Config config = (Config) qb.unique(); + if (config == null) { + return ""; + } + return config.getValue(); + } + + + public static int getIntConfigValue(String key) { + String value = getConfigValue(key); + if (!TextUtils.isEmpty(value)) { + return Integer.valueOf(value); + } + return 0; + } + + public static boolean getBooleanConfigValue(String key) { + String value = getConfigValue(key); + if (!TextUtils.isEmpty(value)) { + return Boolean.valueOf(value); + } + return false; + } + + public static void deleteAll() { + configDao.deleteAll(); + } + + public static void delete(String key) { + QueryBuilder qb = configDao.queryBuilder(); + DeleteQuery bd = qb.where(ConfigDao.Properties.Key.eq(key)).buildDelete(); + bd.executeDeleteWithoutDetachingEntities(); + //or + //Config config = getConfig(key); + //configDao.delete(config); + } + + public static boolean exist(String key) { + QueryBuilder qb = configDao.queryBuilder(); + qb.where(ConfigDao.Properties.Key.eq(key)); + long cnt = qb.count(); + return cnt > 0 ? true : false; + } + + public static void savaObjConfigData(String key, Object obj) { + ConfigUtil.save(key, JSON.toJSONString(obj)); + } + + public static @Nullable + T getObjConfigData(String key, Class clazz) { + String value = ConfigUtil.getConfigValue(key); + if (!TextUtils.isEmpty(value)) { + return JSON.parseObject(value, clazz); + } + return null; + } + + +} diff --git a/xrecyclerview/src/main/java/com/jcodecraeer/xrecyclerview/ArrowRefreshHeaderOriginal.java b/xrecyclerview/src/main/java/com/jcodecraeer/xrecyclerview/ArrowRefreshHeaderOriginal.java new file mode 100755 index 0000000..23aa83a --- /dev/null +++ b/xrecyclerview/src/main/java/com/jcodecraeer/xrecyclerview/ArrowRefreshHeaderOriginal.java @@ -0,0 +1,269 @@ +package com.jcodecraeer.xrecyclerview; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.os.Handler; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.RotateAnimation; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.jcodecraeer.xrecyclerview.progressindicator.AVLoadingIndicatorView; + +import java.util.Date; + +public class ArrowRefreshHeaderOriginal extends LinearLayout implements BaseRefreshHeader{ + private LinearLayout mContainer; + private ImageView mArrowImageView; + private SimpleViewSwithcer mProgressBar; + private TextView mStatusTextView; + private int mState = STATE_NORMAL; + private Context mContext; + + private TextView mHeaderTimeView; + + private Animation mRotateUpAnim; + private Animation mRotateDownAnim; + + private final int ROTATE_ANIM_DURATION = 180; + + public int mMeasuredHeight; + + public ArrowRefreshHeaderOriginal(Context context) { + super(context); + initView(context); + } + + /** + * @param context + * @param attrs + */ + public ArrowRefreshHeaderOriginal(Context context, AttributeSet attrs) { + super(context, attrs); + initView(context); + } + + private void initView(Context context) { + + mContext = context; + // 初始情况,设置下拉刷新view高度为0 + mContainer = (LinearLayout) LayoutInflater.from(context).inflate( + R.layout.listview_header, null); + LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + lp.setMargins(0, 0, 0, 0); + this.setLayoutParams(lp); + this.setPadding(0, 0, 0, 0); + + addView(mContainer, new LayoutParams(LayoutParams.MATCH_PARENT, 0)); + setGravity(Gravity.BOTTOM); + + mArrowImageView = (ImageView)findViewById(R.id.listview_header_arrow); + mStatusTextView = (TextView)findViewById(R.id.refresh_status_textview); + + //init the progress view + mProgressBar = (SimpleViewSwithcer)findViewById(R.id.listview_header_progressbar); + AVLoadingIndicatorView progressView = new AVLoadingIndicatorView(context); + progressView.setIndicatorColor(0xffB5B5B5); + progressView.setIndicatorId(ProgressStyle.BallSpinFadeLoader); + mProgressBar.setView(progressView); + + + mRotateUpAnim = new RotateAnimation(0.0f, -180.0f, + Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, + 0.5f); + mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION); + mRotateUpAnim.setFillAfter(true); + mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f, + Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, + 0.5f); + mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION); + mRotateDownAnim.setFillAfter(true); + + mHeaderTimeView = (TextView)findViewById(R.id.last_refresh_time); + measure(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT); + mMeasuredHeight = getMeasuredHeight(); + } + + public void setProgressStyle(int style) { + if(style == ProgressStyle.SysProgress){ + mProgressBar.setView(new ProgressBar(mContext, null, android.R.attr.progressBarStyle)); + }else{ + AVLoadingIndicatorView progressView = new AVLoadingIndicatorView(this.getContext()); + progressView.setIndicatorColor(0xffB5B5B5); + progressView.setIndicatorId(style); + mProgressBar.setView(progressView); + } + } + + public void setArrowImageView(int resid){ + mArrowImageView.setImageResource(resid); + } + + public void setState(int state) { + if (state == mState) return ; + + if (state == STATE_REFRESHING) { // 显示进度 + mArrowImageView.clearAnimation(); + mArrowImageView.setVisibility(View.INVISIBLE); + mProgressBar.setVisibility(View.VISIBLE); + } else if(state == STATE_DONE) { + mArrowImageView.setVisibility(View.INVISIBLE); + mProgressBar.setVisibility(View.INVISIBLE); + } else { // 显示箭头图片 + mArrowImageView.setVisibility(View.VISIBLE); + mProgressBar.setVisibility(View.INVISIBLE); + } + + switch(state){ + case STATE_NORMAL: + if (mState == STATE_RELEASE_TO_REFRESH) { + mArrowImageView.startAnimation(mRotateDownAnim); + } + if (mState == STATE_REFRESHING) { + mArrowImageView.clearAnimation(); + } + mStatusTextView.setText(R.string.listview_header_hint_normal); + break; + case STATE_RELEASE_TO_REFRESH: + if (mState != STATE_RELEASE_TO_REFRESH) { + mArrowImageView.clearAnimation(); + mArrowImageView.startAnimation(mRotateUpAnim); + mStatusTextView.setText(R.string.listview_header_hint_release); + } + break; + case STATE_REFRESHING: + mStatusTextView.setText(R.string.refreshing); + break; + case STATE_DONE: + mStatusTextView.setText(R.string.refresh_done); + break; + default: + } + + mState = state; + } + + public int getState() { + return mState; + } + + @Override + public void refreshComplate(){ + mHeaderTimeView.setText(friendlyTime(new Date())); + setState(STATE_DONE); + new Handler().postDelayed(new Runnable(){ + public void run() { + reset(); + } + }, 500); + } + + public void setVisiableHeight(int height) { + if (height < 0) + height = 0; + LayoutParams lp = (LayoutParams) mContainer + .getLayoutParams(); + lp.height = height; + mContainer.setLayoutParams(lp); + } + + public int getVisiableHeight() { + int height = 0; + LayoutParams lp = (LayoutParams) mContainer + .getLayoutParams(); + height = lp.height; + return height; + } + + @Override + public void onMove(float delta) { + if(getVisiableHeight() > 0 || delta > 0) { + setVisiableHeight((int) delta + getVisiableHeight()); + if (mState <= STATE_RELEASE_TO_REFRESH) { // 未处于刷新状态,更新箭头 + if (getVisiableHeight() > mMeasuredHeight) { + setState(STATE_RELEASE_TO_REFRESH); + }else { + setState(STATE_NORMAL); + } + } + } + } + + @Override + public boolean releaseAction() { + boolean isOnRefresh = false; + int height = getVisiableHeight(); + if (height == 0) // not visible. + isOnRefresh = false; + + if(getVisiableHeight() > mMeasuredHeight && mState < STATE_REFRESHING){ + setState(STATE_REFRESHING); + isOnRefresh = true; + } + // refreshing and header isn't shown fully. do nothing. + if (mState == STATE_REFRESHING && height <= mMeasuredHeight) { + //return; + } + int destHeight = 0; // default: scroll back to dismiss header. + // is refreshing, just scroll back to show all the header. + if (mState == STATE_REFRESHING) { + destHeight = mMeasuredHeight; + } + smoothScrollTo(destHeight); + + return isOnRefresh; + } + + public void reset() { + smoothScrollTo(0); + setState(STATE_NORMAL); + } + + private void smoothScrollTo(int destHeight) { + ValueAnimator animator = ValueAnimator.ofInt(getVisiableHeight(), destHeight); + animator.setDuration(300).start(); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) + { + setVisiableHeight((int) animation.getAnimatedValue()); + } + }); + animator.start(); + } + + public static String friendlyTime(Date time) { + //获取time距离当前的秒数 + int ct = (int)((System.currentTimeMillis() - time.getTime())/1000); + + if(ct == 0) { + return "刚刚"; + } + + if(ct > 0 && ct < 60) { + return ct + "秒前"; + } + + if(ct >= 60 && ct < 3600) { + return Math.max(ct / 60,1) + "分钟前"; + } + if(ct >= 3600 && ct < 86400) + return ct / 3600 + "小时前"; + if(ct >= 86400 && ct < 2592000){ //86400 * 30 + int day = ct / 86400 ; + return day + "天前"; + } + if(ct >= 2592000 && ct < 31104000) { //86400 * 30 + return ct / 2592000 + "月前"; + } + return ct / 31104000 + "年前"; + } + +} diff --git a/xrecyclerview/src/main/java/com/jcodecraeer/xrecyclerview/XRecyclerViewOriginal.java b/xrecyclerview/src/main/java/com/jcodecraeer/xrecyclerview/XRecyclerViewOriginal.java new file mode 100755 index 0000000..5e7a36d --- /dev/null +++ b/xrecyclerview/src/main/java/com/jcodecraeer/xrecyclerview/XRecyclerViewOriginal.java @@ -0,0 +1,462 @@ +package com.jcodecraeer.xrecyclerview; + +import android.content.Context; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import java.util.ArrayList; + +public class XRecyclerViewOriginal extends RecyclerView { + + private Context mContext; + private boolean isLoadingData = false; + private boolean isnomore = false; + private int mRefreshProgressStyle = ProgressStyle.SysProgress; + private int mLoadingMoreProgressStyle = ProgressStyle.SysProgress; + private ArrayList mHeaderViews = new ArrayList<>(); + private ArrayList mFootViews = new ArrayList<>(); + private Adapter mAdapter; + private Adapter mWrapAdapter; + private float mLastY = -1; + private static final float DRAG_RATE = 3; + private LoadingListener mLoadingListener; + private ArrowRefreshHeader mRefreshHeader; + private boolean pullRefreshEnabled = true; + private boolean loadingMoreEnabled = true; + private static final int TYPE_REFRESH_HEADER = -5; + private static final int TYPE_HEADER = -4; + private static final int TYPE_NORMAL = 0; + private static final int TYPE_FOOTER = -3; + private int previousTotal = 0; + private int mPageCount = 0; + + public XRecyclerViewOriginal(Context context) { + this(context, null); + } + + public XRecyclerViewOriginal(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public XRecyclerViewOriginal(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context); + } + + private void init(Context context) { + mContext = context; + if(pullRefreshEnabled) { + ArrowRefreshHeader refreshHeader = new ArrowRefreshHeader(mContext); + mHeaderViews.add(0, refreshHeader); + mRefreshHeader = refreshHeader; + mRefreshHeader.setProgressStyle(mRefreshProgressStyle); + } + LoadingMoreFooter footView = new LoadingMoreFooter(mContext); + footView.setProgressStyle(mLoadingMoreProgressStyle); + addFootView(footView); + mFootViews.get(0).setVisibility(GONE); + } + + public void addHeaderView(View view) { + if (pullRefreshEnabled && !(mHeaderViews.get(0) instanceof ArrowRefreshHeader)) { + ArrowRefreshHeader refreshHeader = new ArrowRefreshHeader(mContext); + mHeaderViews.add(0, refreshHeader); + mRefreshHeader = refreshHeader; + mRefreshHeader.setProgressStyle(mRefreshProgressStyle); + } + mHeaderViews.add(view); + } + + public void addFootView(final View view) { + mFootViews.clear(); + mFootViews.add(view); + } + + public void loadMoreComplete() { + isLoadingData = false; + View footView = mFootViews.get(0); + if(previousTotal < getLayoutManager().getItemCount()) { + if(footView instanceof LoadingMoreFooter) { + ( (LoadingMoreFooter) footView ).setState(LoadingMoreFooter.STATE_COMPLETE); + } else{ + footView.setVisibility(View.GONE); + } + } else { + if(footView instanceof LoadingMoreFooter) { + ( (LoadingMoreFooter) footView ).setState(LoadingMoreFooter.STATE_NOMORE); + }else{ + footView.setVisibility(View.GONE); + } + isnomore = true; + } + previousTotal = getLayoutManager().getItemCount(); + } + + public void noMoreLoading() { + isLoadingData = false; + View footView = mFootViews.get(0); + isnomore = true; + if(footView instanceof LoadingMoreFooter) { + ( (LoadingMoreFooter) footView ).setState(LoadingMoreFooter.STATE_NOMORE); + }else{ + footView.setVisibility(View.GONE); + } + } + + public void refreshComplete() { + mRefreshHeader.refreshComplate(); + } + + public void setRefreshHeader(ArrowRefreshHeader refreshHeader){ + mRefreshHeader = refreshHeader; + } + + public void setPullRefreshEnabled(boolean enabled){ + pullRefreshEnabled = enabled; + } + + public void setLoadingMoreEnabled(boolean enabled){ + loadingMoreEnabled = enabled; + if(!enabled) { + if (mFootViews.size() > 0) { + mFootViews.get(0).setVisibility(GONE); + } + } + } + + public void setRefreshProgressStyle(int style) { + mRefreshProgressStyle = style; + if (mRefreshHeader != null){ + mRefreshHeader.setProgressStyle(style); + } + } + + public void setLaodingMoreProgressStyle(int style) { + mLoadingMoreProgressStyle = style; + if(mFootViews.size() > 0 && mFootViews.get(0) instanceof LoadingMoreFooter){ + ((LoadingMoreFooter) mFootViews.get(0)).setProgressStyle(style); + } + } + + public void setArrowImageView(int resid) { + if (mRefreshHeader != null){ + mRefreshHeader.setArrowImageView(resid); + } + } + + @Override + public void setAdapter(Adapter adapter) { + mAdapter = adapter; + mWrapAdapter = new WrapAdapter(mHeaderViews, mFootViews, adapter); + super.setAdapter(mWrapAdapter); + mAdapter.registerAdapterDataObserver(mDataObserver); + } + + @Override + public void onScrollStateChanged(int state) { + super.onScrollStateChanged(state); + + if (state == RecyclerView.SCROLL_STATE_IDLE && mLoadingListener != null && !isLoadingData && loadingMoreEnabled) { + LayoutManager layoutManager = getLayoutManager(); + int lastVisibleItemPosition; + if (layoutManager instanceof GridLayoutManager) { + lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition(); + } else if (layoutManager instanceof StaggeredGridLayoutManager) { + int[] into = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()]; + ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(into); + lastVisibleItemPosition = findMax(into); + } else { + lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition(); + } + if (layoutManager.getChildCount() > 0 + && lastVisibleItemPosition >= layoutManager.getItemCount() - 1 && layoutManager.getItemCount() > layoutManager.getChildCount() && !isnomore && mRefreshHeader.getState() < ArrowRefreshHeader.STATE_REFRESHING) { + + View footView = mFootViews.get(0); + isLoadingData = true; + if(footView instanceof LoadingMoreFooter) { + ( (LoadingMoreFooter) footView ).setState(LoadingMoreFooter.STATE_LAODING); + } else{ + footView.setVisibility(View.VISIBLE); + } + mLoadingListener.onLoadMore(); + } + } + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (mLastY == -1) { + mLastY = ev.getRawY(); + } + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + mLastY = ev.getRawY(); + break; + case MotionEvent.ACTION_MOVE: + final float deltaY = ev.getRawY() - mLastY; + mLastY = ev.getRawY(); + if ( isOnTop() && pullRefreshEnabled) { + mRefreshHeader.onMove(deltaY / DRAG_RATE); + if(mRefreshHeader.getVisiableHeight() > 0 && mRefreshHeader.getState() < ArrowRefreshHeader.STATE_REFRESHING ) { + Log.i("getVisiableHeight", "getVisiableHeight = " + mRefreshHeader.getVisiableHeight()); + Log.i("getVisiableHeight", " mRefreshHeader.getState() = " + mRefreshHeader.getState()); + return false; + } + } + break; + default: + mLastY = -1; // reset + if ( isOnTop() && pullRefreshEnabled) { + if( mRefreshHeader.releaseAction()) { + if (mLoadingListener != null) { + mLoadingListener.onRefresh(); + isnomore = false; + previousTotal = 0; + } + } + } + break; + } + return super.onTouchEvent(ev); + } + + private int findMax(int[] lastPositions) { + int max = lastPositions[0]; + for (int value : lastPositions) { + if (value > max) { + max = value; + } + } + return max; + } + + private int findMin(int[] firstPositions) { + int min = firstPositions[0]; + for (int value : firstPositions) { + if (value < min) { + min = value; + } + } + return min; + } + + private boolean isOnTop() { + if (mHeaderViews == null || mHeaderViews.isEmpty()) { + return false; + } + + View view = mHeaderViews.get(0); + if (view.getParent() != null) { + return true; + } else { + return false; + } +// LayoutManager layoutManager = getLayoutManager(); +// int firstVisibleItemPosition; +// if (layoutManager instanceof GridLayoutManager) { +// firstVisibleItemPosition = ((GridLayoutManager) layoutManager).findFirstVisibleItemPosition(); +// } else if ( layoutManager instanceof StaggeredGridLayoutManager ) { +// int[] into = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()]; +// ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(into); +// firstVisibleItemPosition = findMin(into); +// } else { +// firstVisibleItemPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition(); +// } +// if ( firstVisibleItemPosition <= 1 ) { +// return true; +// } +// return false; + } + + private final AdapterDataObserver mDataObserver = new AdapterDataObserver() { + @Override + public void onChanged() { + mWrapAdapter.notifyDataSetChanged(); + } + + @Override + public void onItemRangeInserted(int positionStart, int itemCount) { + mWrapAdapter.notifyItemRangeInserted(positionStart, itemCount); + } + + @Override + public void onItemRangeChanged(int positionStart, int itemCount) { + mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount); + } + + @Override + public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { + mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount, payload); + } + + @Override + public void onItemRangeRemoved(int positionStart, int itemCount) { + mWrapAdapter.notifyItemRangeRemoved(positionStart, itemCount); + } + + @Override + public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { + mWrapAdapter.notifyItemMoved(fromPosition, toPosition); + } + }; + + private class WrapAdapter extends Adapter { + + private Adapter adapter; + + private ArrayList mHeaderViews; + + private ArrayList mFootViews; + + private int headerPosition = 1; + + public WrapAdapter(ArrayList headerViews, ArrayList footViews, Adapter adapter) { + this.adapter = adapter; + this.mHeaderViews = headerViews; + this.mFootViews = footViews; + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + LayoutManager manager = recyclerView.getLayoutManager(); + if(manager instanceof GridLayoutManager) { + final GridLayoutManager gridManager = ((GridLayoutManager) manager); + gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + return (isHeader(position)|| isFooter(position)) + ? gridManager.getSpanCount() : 1; + } + }); + } + } + + @Override + public void onViewAttachedToWindow(ViewHolder holder) { + super.onViewAttachedToWindow(holder); + ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); + if(lp != null + && lp instanceof StaggeredGridLayoutManager.LayoutParams + && (isHeader( holder.getLayoutPosition()) || isFooter( holder.getLayoutPosition())) ) { + StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp; + p.setFullSpan(true); + } + } + + public boolean isHeader(int position) { + return position >= 0 && position < mHeaderViews.size(); + } + + public boolean isFooter(int position) { + return position < getItemCount() && position >= getItemCount() - mFootViews.size(); + } + + public boolean isRefreshHeader(int position) { + return position == 0 ; + } + + public int getHeadersCount() { + return mHeaderViews.size(); + } + + public int getFootersCount() { + return mFootViews.size(); + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + if (viewType == TYPE_REFRESH_HEADER) { + return new SimpleViewHolder(mHeaderViews.get(0)); + } else if (viewType == TYPE_HEADER) { + return new SimpleViewHolder(mHeaderViews.get(headerPosition++ )); + } else if (viewType == TYPE_FOOTER) { + return new SimpleViewHolder(mFootViews.get(0)); + } + return adapter.onCreateViewHolder(parent, viewType); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + if (isHeader(position)) { + return; + } + int adjPosition = position - getHeadersCount(); + int adapterCount; + if (adapter != null) { + adapterCount = adapter.getItemCount(); + if (adjPosition < adapterCount) { + adapter.onBindViewHolder(holder, adjPosition); + return; + } + } + } + + @Override + public int getItemCount() { + if (adapter != null) { + return getHeadersCount() + getFootersCount() + adapter.getItemCount(); + } else { + return getHeadersCount() + getFootersCount(); + } + } + + @Override + public int getItemViewType(int position) { + if(isRefreshHeader(position)){ + return TYPE_REFRESH_HEADER; + } + if (isHeader(position)) { + return TYPE_HEADER; + } + if(isFooter(position)){ + return TYPE_FOOTER; + } + int adjPosition = position - getHeadersCount();; + int adapterCount; + if (adapter != null) { + adapterCount = adapter.getItemCount(); + if (adjPosition < adapterCount) { + return adapter.getItemViewType(adjPosition); + } + } + return TYPE_NORMAL; + } + + @Override + public long getItemId(int position) { + if (adapter != null && position >= getHeadersCount()) { + int adjPosition = position - getHeadersCount(); + int adapterCount = adapter.getItemCount(); + if (adjPosition < adapterCount) { + return adapter.getItemId(adjPosition); + } + } + return -1; + } + + private class SimpleViewHolder extends ViewHolder { + public SimpleViewHolder(View itemView) { + super(itemView); + } + } + } + + public void setLoadingListener(LoadingListener listener) { + mLoadingListener = listener; + } + + public interface LoadingListener { + + void onRefresh(); + + void onLoadMore(); + } +} diff --git a/xrecyclerview/src/main/res/drawable-hdpi/a1.png b/xrecyclerview/src/main/res/drawable-hdpi/a1.png new file mode 100755 index 0000000..5713b8d Binary files /dev/null and b/xrecyclerview/src/main/res/drawable-hdpi/a1.png differ diff --git a/xrecyclerview/src/main/res/drawable-hdpi/a2.png b/xrecyclerview/src/main/res/drawable-hdpi/a2.png new file mode 100755 index 0000000..0522744 Binary files /dev/null and b/xrecyclerview/src/main/res/drawable-hdpi/a2.png differ diff --git a/xrecyclerview/src/main/res/drawable-hdpi/a3.png b/xrecyclerview/src/main/res/drawable-hdpi/a3.png new file mode 100755 index 0000000..1993c64 Binary files /dev/null and b/xrecyclerview/src/main/res/drawable-hdpi/a3.png differ diff --git a/xrecyclerview/src/main/res/drawable-hdpi/a4.png b/xrecyclerview/src/main/res/drawable-hdpi/a4.png new file mode 100755 index 0000000..45c9986 Binary files /dev/null and b/xrecyclerview/src/main/res/drawable-hdpi/a4.png differ diff --git a/xrecyclerview/src/main/res/drawable-hdpi/a5.png b/xrecyclerview/src/main/res/drawable-hdpi/a5.png new file mode 100755 index 0000000..88ce582 Binary files /dev/null and b/xrecyclerview/src/main/res/drawable-hdpi/a5.png differ diff --git a/xrecyclerview/src/main/res/drawable-hdpi/a6.png b/xrecyclerview/src/main/res/drawable-hdpi/a6.png new file mode 100755 index 0000000..2fe2e65 Binary files /dev/null and b/xrecyclerview/src/main/res/drawable-hdpi/a6.png differ diff --git a/xrecyclerview/src/main/res/drawable-hdpi/a7.png b/xrecyclerview/src/main/res/drawable-hdpi/a7.png new file mode 100755 index 0000000..bc2768e Binary files /dev/null and b/xrecyclerview/src/main/res/drawable-hdpi/a7.png differ diff --git a/xrecyclerview/src/main/res/drawable-hdpi/a8.png b/xrecyclerview/src/main/res/drawable-hdpi/a8.png new file mode 100755 index 0000000..fd87170 Binary files /dev/null and b/xrecyclerview/src/main/res/drawable-hdpi/a8.png differ diff --git a/xrecyclerview/src/main/res/layout/listview_header_original.xml b/xrecyclerview/src/main/res/layout/listview_header_original.xml new file mode 100755 index 0000000..07672c3 --- /dev/null +++ b/xrecyclerview/src/main/res/layout/listview_header_original.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file