├── .gitignore ├── AndroidManifest.xml ├── README.md ├── pom.xml ├── proguard.cfg ├── project.properties └── src └── main └── java └── com └── j256 └── ormlite └── android ├── extras ├── AndroidBaseDaoImpl.java ├── NoIdCursorWrapper.java ├── OrmliteCursorAdapter.java ├── OrmliteCursorLoader.java └── OrmliteListLoader.java └── support └── extras ├── AndroidBaseDaoImpl.java ├── NoIdCursorWrapper.java ├── OrmliteCursorAdapter.java ├── OrmliteCursorLoader.java └── OrmliteListLoader.java /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | target 3 | .project 4 | .settings 5 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ORMLite Extras for Android 2 | 3 | Some classes offering additional functionality for ORMLite on Android. 4 | 5 | Please visit the [ORMLite Website](http://ormlite.com/) for more information on ORMLite. 6 | 7 | # Credits 8 | [Nick Campion](mailto://campnic@gmail.com) 9 | jromanda@gmail.com 10 | luke.rt.meyer@gmail.com 11 | 12 | # License 13 | The class NoIdCursorWrapper is the work of jromanda@gmail.com . you'll need to contact him for license until I get clearance to release this work on his behalf. 14 | 15 | The OrmliteCursorAdapter is based off of logic from https://github.com/sosiouxme/Android-examples thanks to luke.rt.meyer@gmail.com 16 | 17 | Contact myself for license information on the rest of the code. 18 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.j256.ormlite 5 | ormlite-android-extras 6 | 0.0.1-SNAPSHOT 7 | http://github.com/kaeppler/droid-fu 8 | 9 | 10 | 11 | nfc 12 | Nick Campion 13 | campnic@gmail.com 14 | http://blog.nicholascampion.com 15 | -6 16 | 17 | 18 | 19 | 20 | http://github.com/campnic/ormlite-android-extras 21 | scm:git:git://github.com/campnic/ormlite-android-extras.git 22 | scm:git:git@github.com:campnic/ormlite-android-extras.git 23 | 24 | 25 | 26 | GitHub 27 | http://github.com/campnic/ormlite-android-extras/issues 28 | 29 | 30 | 31 | 3.2 32 | 13 33 | _r1 34 | UTF-8 35 | 36 | 37 | 38 | 39 | package 40 | 41 | 42 | 43 | 44 | 45 | org.apache.maven.plugins 46 | maven-compiler-plugin 47 | 48 | 1.5 49 | 1.5 50 | 51 | 52 | 53 | 54 | 55 | org.apache.maven.plugins 56 | maven-jar-plugin 57 | 2.2 58 | 59 | 60 | **/*.apk 61 | **/*.dex 62 | **/*.ap_ 63 | 64 | 65 | 66 | 67 | 68 | maven-release-plugin 69 | 2.0-beta-9 70 | 71 | http://github.com/campnic/ormlite-android-extras/tree 72 | 73 | 74 | 75 | 76 | com.jayway.maven.plugins.android.generation2 77 | maven-android-plugin 78 | 2.8.3 79 | 80 | true 81 | true 82 | 83 | ${env.ANDROID_HOME} 84 | ${androidVersion} 85 | 86 | 87 | true 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | android 96 | android 97 | ${androidVersion}${androidApiRevision} 98 | provided 99 | 100 | 101 | 102 | android.support 103 | compatibility-v4 104 | r7 105 | provided 106 | 107 | 108 | 109 | 110 | com.google.android 111 | android-test 112 | 2.2.1 113 | provided 114 | 115 | 116 | 117 | com.j256.ormlite 118 | ormlite-core 119 | 4.42 120 | provided 121 | 122 | 123 | 124 | com.j256.ormlite 125 | ormlite-android 126 | 4.42 127 | provided 128 | 129 | 130 | 131 | 132 | 133 | http://github.com/campnic/ormlite-android-extras/downloads 134 | 135 | 136 | 137 | 138 | copy-jar 139 | 140 | 141 | copyTo 142 | 143 | 144 | 145 | 146 | 147 | maven-antrun-plugin 148 | 149 | 150 | install 151 | 152 | run 153 | 154 | 155 | 156 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | release-sign-artifacts 171 | 172 | 173 | performRelease 174 | true 175 | 176 | 177 | 178 | 179 | 180 | org.apache.maven.plugins 181 | maven-gpg-plugin 182 | 1.0-alpha-4 183 | 184 | 185 | sign-artifacts 186 | verify 187 | 188 | sign 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /proguard.cfg: -------------------------------------------------------------------------------- 1 | -optimizationpasses 5 2 | -dontusemixedcaseclassnames 3 | -dontskipnonpubliclibraryclasses 4 | -dontpreverify 5 | -verbose 6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 7 | 8 | -keep public class * extends android.app.Activity 9 | -keep public class * extends android.app.Application 10 | -keep public class * extends android.app.Service 11 | -keep public class * extends android.content.BroadcastReceiver 12 | -keep public class * extends android.content.ContentProvider 13 | -keep public class * extends android.app.backup.BackupAgentHelper 14 | -keep public class * extends android.preference.Preference 15 | -keep public class com.android.vending.licensing.ILicensingService 16 | 17 | -keepclasseswithmembernames class * { 18 | native ; 19 | } 20 | 21 | -keepclasseswithmembers class * { 22 | public (android.content.Context, android.util.AttributeSet); 23 | } 24 | 25 | -keepclasseswithmembers class * { 26 | public (android.content.Context, android.util.AttributeSet, int); 27 | } 28 | 29 | -keepclassmembers class * extends android.app.Activity { 30 | public void *(android.view.View); 31 | } 32 | 33 | -keepclassmembers enum * { 34 | public static **[] values(); 35 | public static ** valueOf(java.lang.String); 36 | } 37 | 38 | -keep class * implements android.os.Parcelable { 39 | public static final android.os.Parcelable$Creator *; 40 | } 41 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-15 12 | android.library=true 13 | -------------------------------------------------------------------------------- /src/main/java/com/j256/ormlite/android/extras/AndroidBaseDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.j256.ormlite.android.extras; 2 | 3 | import java.sql.SQLException; 4 | import java.util.List; 5 | 6 | import android.content.Context; 7 | import android.content.Loader; 8 | import android.database.Cursor; 9 | 10 | import com.j256.ormlite.android.AndroidCompiledStatement; 11 | import com.j256.ormlite.dao.BaseDaoImpl; 12 | import com.j256.ormlite.stmt.PreparedQuery; 13 | import com.j256.ormlite.stmt.StatementBuilder; 14 | import com.j256.ormlite.support.ConnectionSource; 15 | import com.j256.ormlite.support.DatabaseConnection; 16 | import com.j256.ormlite.table.DatabaseTableConfig; 17 | 18 | public abstract class AndroidBaseDaoImpl extends BaseDaoImpl 19 | { 20 | 21 | public AndroidBaseDaoImpl(Class dataClass) throws SQLException 22 | { 23 | super(dataClass); 24 | } 25 | 26 | public AndroidBaseDaoImpl(ConnectionSource connectionSource, Class dataClass) throws SQLException 27 | { 28 | super(connectionSource, dataClass); 29 | } 30 | 31 | public AndroidBaseDaoImpl(ConnectionSource connectionSource, DatabaseTableConfig tableConfig) throws SQLException 32 | { 33 | super(connectionSource, tableConfig); 34 | } 35 | 36 | public Cursor getCursor(PreparedQuery query) throws SQLException 37 | { 38 | DatabaseConnection readOnlyConn = connectionSource.getReadOnlyConnection(); 39 | AndroidCompiledStatement stmt = (AndroidCompiledStatement) query.compile(readOnlyConn, StatementBuilder.StatementType.SELECT); 40 | Cursor base = stmt.getCursor(); 41 | String idColumnName = getTableInfo().getIdField().getColumnName(); 42 | int idColumnIndex = base.getColumnIndex(idColumnName); 43 | NoIdCursorWrapper wrapper = new NoIdCursorWrapper(base, idColumnIndex); 44 | return wrapper; 45 | } 46 | 47 | public Loader> getResultSetLoader(Context context, PreparedQuery query) throws SQLException 48 | { 49 | return new OrmliteListLoader(context, this, query); 50 | } 51 | 52 | public OrmliteCursorLoader getSQLCursorLoader(Context context, PreparedQuery query) throws SQLException 53 | { 54 | return new OrmliteCursorLoader(context, this, query); 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/main/java/com/j256/ormlite/android/extras/NoIdCursorWrapper.java: -------------------------------------------------------------------------------- 1 | package com.j256.ormlite.android.extras; 2 | 3 | import android.database.Cursor; 4 | import android.database.CursorWrapper; 5 | import android.widget.ListView; 6 | 7 | /** 8 | * A {@link CursorWrapper} implementation that allows a {@link Cursor} without a 9 | * field named "_id" to be used with various Android {@link ListView} classes 10 | * that expect a column named "_id". This is done by specifying an alias field 11 | * name to be used in place of "_id". 12 | */ 13 | public class NoIdCursorWrapper extends CursorWrapper 14 | { 15 | private int idColumnIndex; 16 | 17 | /** 18 | * Create a NoIdCursorWrapper using the alias column index. 19 | * 20 | * @param c 21 | * the cursor to wrap 22 | * @param idColumnIndex 23 | * the column index to use as the _id column alias 24 | */ 25 | public NoIdCursorWrapper(Cursor c, int idColumnIndex) 26 | { 27 | super(c); 28 | this.idColumnIndex = idColumnIndex; 29 | } 30 | 31 | /** 32 | * Create a NoIdCursorWrapper using the alias column name. 33 | * 34 | * @param c 35 | * the cursor to wrap 36 | * @param idColumnName 37 | * the column name to use as the _id column alias 38 | */ 39 | public NoIdCursorWrapper(Cursor c, String idColumnName) 40 | { 41 | super(c); 42 | idColumnIndex = c.getColumnIndex(idColumnName); 43 | } 44 | 45 | @Override 46 | public int getColumnIndex(String columnName) 47 | { 48 | int index = super.getColumnIndex(columnName); 49 | if (index < 0 && "_id".equals(columnName)) 50 | { 51 | index = idColumnIndex; 52 | } 53 | return index; 54 | }; 55 | 56 | @Override 57 | public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException 58 | { 59 | int index = getColumnIndex(columnName); 60 | if (index >= 0) 61 | { 62 | return index; 63 | } 64 | // let the AbstractCursor generate the exception 65 | return super.getColumnIndexOrThrow(columnName); 66 | }; 67 | } -------------------------------------------------------------------------------- /src/main/java/com/j256/ormlite/android/extras/OrmliteCursorAdapter.java: -------------------------------------------------------------------------------- 1 | package com.j256.ormlite.android.extras; 2 | 3 | import java.sql.SQLException; 4 | 5 | import android.content.Context; 6 | import android.database.Cursor; 7 | import android.view.View; 8 | import android.widget.CursorAdapter; 9 | 10 | import com.j256.ormlite.android.AndroidDatabaseResults; 11 | import com.j256.ormlite.stmt.PreparedQuery; 12 | 13 | public abstract class OrmliteCursorAdapter extends CursorAdapter 14 | { 15 | PreparedQuery mQuery; 16 | 17 | public OrmliteCursorAdapter(Context context, Cursor c, PreparedQuery query) 18 | { 19 | super(context, c, false); 20 | mQuery = query; 21 | } 22 | 23 | @Override 24 | public void bindView(View itemView, Context context, Cursor cursor) 25 | { 26 | try 27 | { 28 | T item = mQuery.mapRow(new AndroidDatabaseResults(cursor, null)) ; 29 | bindView(itemView, context, item); 30 | } 31 | catch(SQLException e) 32 | { 33 | e.printStackTrace(); 34 | } 35 | 36 | } 37 | 38 | public void setQuery(PreparedQuery query) 39 | { 40 | mQuery = query; 41 | } 42 | 43 | abstract public void bindView(View itemView, Context context, T item); 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/j256/ormlite/android/extras/OrmliteCursorLoader.java: -------------------------------------------------------------------------------- 1 | package com.j256.ormlite.android.extras; 2 | 3 | import java.io.FileDescriptor; 4 | import java.io.PrintWriter; 5 | import java.sql.SQLException; 6 | 7 | import android.content.AsyncTaskLoader; 8 | import android.content.Context; 9 | import android.database.ContentObserver; 10 | import android.database.Cursor; 11 | 12 | import com.j256.ormlite.dao.Dao; 13 | import com.j256.ormlite.stmt.PreparedQuery; 14 | 15 | public class OrmliteCursorLoader extends AsyncTaskLoader { 16 | final ForceLoadContentObserver mObserver; 17 | 18 | private Cursor mCursor; 19 | private AndroidBaseDaoImpl mDao; 20 | private PreparedQuery mQuery; 21 | 22 | 23 | /* Runs on a worker thread */ 24 | @Override 25 | public Cursor loadInBackground() { 26 | Cursor cursor = null; 27 | try 28 | { 29 | cursor = mDao.getCursor(mQuery); 30 | } catch (SQLException e) 31 | { 32 | e.printStackTrace(); 33 | } 34 | if (cursor != null) { 35 | // Ensure the cursor window is filled 36 | cursor.getCount(); 37 | registerContentObserver(cursor, mObserver); 38 | } 39 | return cursor; 40 | } 41 | 42 | /** 43 | * Registers an observer to get notifications from the content provider 44 | * when the cursor needs to be refreshed. 45 | */ 46 | void registerContentObserver(Cursor cursor, ContentObserver observer) { 47 | cursor.registerContentObserver(mObserver); 48 | } 49 | 50 | /* Runs on the UI thread */ 51 | @Override 52 | public void deliverResult(Cursor cursor) { 53 | if (isReset()) { 54 | // An async query came in while the loader is stopped 55 | if (cursor != null) { 56 | cursor.close(); 57 | } 58 | return; 59 | } 60 | Cursor oldCursor = mCursor; 61 | mCursor = cursor; 62 | 63 | if (isStarted()) { 64 | super.deliverResult(cursor); 65 | } 66 | 67 | if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) { 68 | oldCursor.close(); 69 | } 70 | } 71 | 72 | public OrmliteCursorLoader(Context context, AndroidBaseDaoImpl dao, PreparedQuery query) { 73 | super(context); 74 | mObserver = new ForceLoadContentObserver(); 75 | mDao = dao; 76 | mQuery = query; 77 | } 78 | 79 | @Override 80 | protected void onStartLoading() { 81 | if (mCursor != null) { 82 | deliverResult(mCursor); 83 | } 84 | if (takeContentChanged() || mCursor == null) { 85 | forceLoad(); 86 | } 87 | } 88 | 89 | /** 90 | * Must be called from the UI thread 91 | */ 92 | @Override 93 | protected void onStopLoading() { 94 | // Attempt to cancel the current load task if possible. 95 | cancelLoad(); 96 | } 97 | 98 | @Override 99 | public void onCanceled(Cursor cursor) { 100 | if (cursor != null && !cursor.isClosed()) { 101 | cursor.close(); 102 | } 103 | } 104 | 105 | @Override 106 | protected void onReset() { 107 | super.onReset(); 108 | 109 | // Ensure the loader is stopped 110 | onStopLoading(); 111 | 112 | if (mCursor != null && !mCursor.isClosed()) { 113 | mCursor.close(); 114 | } 115 | mCursor = null; 116 | } 117 | 118 | 119 | 120 | public PreparedQuery getQuery() 121 | { 122 | return mQuery; 123 | } 124 | 125 | public void setQuery(PreparedQuery mQuery) 126 | { 127 | this.mQuery = mQuery; 128 | } 129 | 130 | public Dao getDao() 131 | { 132 | return mDao; 133 | } 134 | 135 | @Override 136 | public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 137 | super.dump(prefix, fd, writer, args); 138 | writer.print(prefix); writer.print("mCursor="); writer.println(mCursor); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/com/j256/ormlite/android/extras/OrmliteListLoader.java: -------------------------------------------------------------------------------- 1 | package com.j256.ormlite.android.extras; 2 | 3 | import java.sql.SQLException; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import android.content.AsyncTaskLoader; 8 | import android.content.Context; 9 | 10 | import com.j256.ormlite.dao.Dao; 11 | import com.j256.ormlite.stmt.PreparedQuery; 12 | 13 | public class OrmliteListLoader extends AsyncTaskLoader> 14 | { 15 | private Dao mDao = null; 16 | private PreparedQuery mQuery = null; 17 | private List mData = null; 18 | 19 | public OrmliteListLoader(Context context, Dao dao, PreparedQuery query) 20 | { 21 | super(context); 22 | mDao = dao; 23 | mQuery = query; 24 | } 25 | 26 | @Override 27 | public List loadInBackground() 28 | { 29 | List result = null; 30 | 31 | try 32 | { 33 | if (mQuery != null) 34 | { 35 | result = mDao.query(mQuery); 36 | } else 37 | { 38 | result = mDao.queryForAll(); 39 | } 40 | 41 | } catch (SQLException e) 42 | { 43 | result = Collections.emptyList(); 44 | } 45 | 46 | return result; 47 | } 48 | 49 | @Override 50 | public void deliverResult(List datas) 51 | { 52 | if (isReset()) 53 | { 54 | // An async query came in while the loader is stopped. We 55 | // don't need the result. 56 | if (datas != null) 57 | { 58 | onReleaseResources(datas); 59 | } 60 | } 61 | 62 | List oldDatas = mData; 63 | mData = datas; 64 | 65 | if (isStarted()) 66 | { 67 | // If the Loader is currently started, we can immediately 68 | // deliver its results. 69 | super.deliverResult(datas); 70 | } 71 | 72 | if (oldDatas != null && !oldDatas.isEmpty()) 73 | { 74 | onReleaseResources(oldDatas); 75 | } 76 | } 77 | 78 | /** 79 | * Handles a request to start the Loader. 80 | */ 81 | @Override 82 | protected void onStartLoading() 83 | { 84 | if (mData != null) 85 | { 86 | // If we currently have a result available, deliver it 87 | // immediately. 88 | deliverResult(mData); 89 | } else 90 | { 91 | // If the data has changed since the last time it was loaded 92 | // or is not currently available, start a load. 93 | forceLoad(); 94 | } 95 | } 96 | 97 | /** 98 | * Handles a request to stop the Loader. 99 | */ 100 | @Override 101 | protected void onStopLoading() 102 | { 103 | // Attempt to cancel the current load task if possible. 104 | cancelLoad(); 105 | } 106 | 107 | /** 108 | * Handles a request to cancel a load. 109 | */ 110 | @Override 111 | public void onCanceled(List datas) 112 | { 113 | super.onCanceled(datas); 114 | 115 | // At this point we can release the resources associated with 'apps' 116 | // if needed. 117 | onReleaseResources(datas); 118 | } 119 | 120 | /** 121 | * Handles a request to completely reset the Loader. 122 | */ 123 | @Override 124 | protected void onReset() 125 | { 126 | super.onReset(); 127 | 128 | // Ensure the loader is stopped 129 | onStopLoading(); 130 | 131 | // At this point we can release the resources associated with 'apps' 132 | // if needed. 133 | if (mData != null) 134 | { 135 | onReleaseResources(mData); 136 | mData = null; 137 | } 138 | } 139 | 140 | /** 141 | * Helper function to take care of releasing resources associated with an 142 | * actively loaded data set. 143 | */ 144 | protected void onReleaseResources(List datas) 145 | { 146 | // For a simple List<> there is nothing to do. For something 147 | // like a Cursor, we would close it here. 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/com/j256/ormlite/android/support/extras/AndroidBaseDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.j256.ormlite.android.support.extras; 2 | 3 | import java.lang.ref.WeakReference; 4 | import java.sql.SQLException; 5 | import java.util.ArrayList; 6 | import java.util.Collections; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | import android.content.Context; 11 | import android.database.Cursor; 12 | import android.support.v4.content.Loader; 13 | import android.util.Log; 14 | 15 | import com.j256.ormlite.android.AndroidCompiledStatement; 16 | import com.j256.ormlite.dao.BaseDaoImpl; 17 | import com.j256.ormlite.stmt.PreparedDelete; 18 | import com.j256.ormlite.stmt.PreparedQuery; 19 | import com.j256.ormlite.stmt.StatementBuilder; 20 | import com.j256.ormlite.support.ConnectionSource; 21 | import com.j256.ormlite.support.DatabaseConnection; 22 | import com.j256.ormlite.table.DatabaseTableConfig; 23 | 24 | public abstract class AndroidBaseDaoImpl extends BaseDaoImpl 25 | { 26 | 27 | public AndroidBaseDaoImpl(Class dataClass) throws SQLException { 28 | super(dataClass); 29 | } 30 | 31 | public AndroidBaseDaoImpl(ConnectionSource connectionSource, Class dataClass) throws SQLException { 32 | super(connectionSource, dataClass); 33 | } 34 | 35 | public AndroidBaseDaoImpl(ConnectionSource connectionSource, DatabaseTableConfig tableConfig) throws SQLException { 36 | super(connectionSource, tableConfig); 37 | } 38 | 39 | public Cursor getCursor(PreparedQuery query) throws SQLException { 40 | DatabaseConnection readOnlyConn = connectionSource.getReadOnlyConnection(); 41 | AndroidCompiledStatement stmt = (AndroidCompiledStatement) query.compile(readOnlyConn, StatementBuilder.StatementType.SELECT); 42 | Cursor base = stmt.getCursor(); 43 | String idColumnName = getTableInfo().getIdField() 44 | .getColumnName(); 45 | int idColumnIndex = base.getColumnIndex(idColumnName); 46 | NoIdCursorWrapper wrapper = new NoIdCursorWrapper(base, idColumnIndex); 47 | return wrapper; 48 | } 49 | 50 | public Loader> getResultSetLoader(Context context, PreparedQuery query) throws SQLException { 51 | OrmliteListLoader loader = new OrmliteListLoader(context, this, query); 52 | synchronized (mLoaders) 53 | { 54 | mLoaders.add(new WeakReference>(loader)); 55 | } 56 | return loader; 57 | } 58 | 59 | public OrmliteCursorLoader getSQLCursorLoader(Context context, PreparedQuery query) throws SQLException { 60 | OrmliteCursorLoader loader = new OrmliteCursorLoader(context, this, query); 61 | synchronized (mLoaders) 62 | { 63 | mLoaders.add(new WeakReference>(loader)); 64 | } 65 | return loader; 66 | } 67 | 68 | protected List>> mLoaders = Collections.synchronizedList(new ArrayList>>()); // new 69 | 70 | protected void notifyContentChange() { 71 | synchronized (mLoaders) 72 | { 73 | for (Iterator>> itr = mLoaders.iterator(); itr.hasNext();) 74 | { 75 | WeakReference> weakRef = itr.next(); 76 | Loader loader = weakRef.get(); 77 | if (loader == null) 78 | { 79 | itr.remove(); 80 | } else 81 | { 82 | loader.onContentChanged(); 83 | } 84 | } 85 | } 86 | } 87 | 88 | @Override 89 | public int create(T arg0) throws SQLException { 90 | int result = super.create(arg0); 91 | if (result > 0) 92 | { 93 | notifyContentChange(); 94 | } 95 | return result; 96 | } 97 | 98 | @Override 99 | public int updateRaw(String arg0, String... arg1) throws SQLException { 100 | int result = super.updateRaw(arg0, arg1); 101 | if (result > 0) 102 | { 103 | notifyContentChange(); 104 | } 105 | return result; 106 | } 107 | 108 | @Override 109 | public int delete(PreparedDelete preparedDelete) throws SQLException { 110 | int result = super.delete(preparedDelete); 111 | if (result > 0) 112 | { 113 | notifyContentChange(); 114 | } 115 | return result; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/j256/ormlite/android/support/extras/NoIdCursorWrapper.java: -------------------------------------------------------------------------------- 1 | package com.j256.ormlite.android.support.extras; 2 | 3 | import android.database.Cursor; 4 | import android.database.CursorWrapper; 5 | 6 | /** 7 | * A {@link CursorWrapper} implementation that allows a {@link Cursor} without a 8 | * field named "_id" to be used with various Android Adapter based view classes 9 | * that expect a column named "_id". This is done by specifying an alias field 10 | * name to be used in place of "_id". 11 | */ 12 | public class NoIdCursorWrapper extends CursorWrapper 13 | { 14 | private int idColumnIndex; 15 | 16 | /** 17 | * Create a NoIdCursorWrapper using the alias column index. 18 | * 19 | * @param c 20 | * the cursor to wrap 21 | * @param idColumnIndex 22 | * the column index to use as the _id column alias 23 | */ 24 | public NoIdCursorWrapper(Cursor c, int idColumnIndex) 25 | { 26 | super(c); 27 | this.idColumnIndex = idColumnIndex; 28 | } 29 | 30 | /** 31 | * Create a NoIdCursorWrapper using the alias column name. 32 | * 33 | * @param c 34 | * the cursor to wrap 35 | * @param idColumnName 36 | * the column name to use as the _id column alias 37 | */ 38 | public NoIdCursorWrapper(Cursor c, String idColumnName) 39 | { 40 | super(c); 41 | idColumnIndex = c.getColumnIndex(idColumnName); 42 | } 43 | 44 | @Override 45 | public int getColumnIndex(String columnName) 46 | { 47 | int index = super.getColumnIndex(columnName); 48 | if (index < 0 && "_id".equals(columnName)) 49 | { 50 | index = idColumnIndex; 51 | } 52 | return index; 53 | }; 54 | 55 | @Override 56 | public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException 57 | { 58 | int index = getColumnIndex(columnName); 59 | if (index >= 0) 60 | { 61 | return index; 62 | } 63 | // let the AbstractCursor generate the exception 64 | return super.getColumnIndexOrThrow(columnName); 65 | }; 66 | } -------------------------------------------------------------------------------- /src/main/java/com/j256/ormlite/android/support/extras/OrmliteCursorAdapter.java: -------------------------------------------------------------------------------- 1 | package com.j256.ormlite.android.support.extras; 2 | 3 | import java.sql.SQLException; 4 | 5 | import android.content.Context; 6 | import android.database.Cursor; 7 | import android.support.v4.widget.CursorAdapter; 8 | import android.view.View; 9 | 10 | import com.j256.ormlite.android.AndroidDatabaseResults; 11 | import com.j256.ormlite.stmt.PreparedQuery; 12 | 13 | public abstract class OrmliteCursorAdapter extends CursorAdapter 14 | { 15 | protected PreparedQuery mQuery; 16 | 17 | public OrmliteCursorAdapter(Context context, Cursor c, PreparedQuery query) 18 | { 19 | super(context, c, false); 20 | mQuery = query; 21 | } 22 | 23 | @Override 24 | public void bindView(View itemView, Context context, Cursor cursor) 25 | { 26 | try 27 | { 28 | T item = mQuery.mapRow(new AndroidDatabaseResults(cursor, null)) ; 29 | bindView(itemView, context, item); 30 | } 31 | catch(SQLException e) 32 | { 33 | e.printStackTrace(); 34 | } 35 | 36 | } 37 | 38 | public void setQuery(PreparedQuery query) 39 | { 40 | mQuery = query; 41 | } 42 | 43 | abstract public void bindView(View itemView, Context context, T item); 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/j256/ormlite/android/support/extras/OrmliteCursorLoader.java: -------------------------------------------------------------------------------- 1 | package com.j256.ormlite.android.support.extras; 2 | 3 | import java.io.FileDescriptor; 4 | import java.io.PrintWriter; 5 | import java.sql.SQLException; 6 | 7 | import android.content.Context; 8 | import android.database.ContentObserver; 9 | import android.database.Cursor; 10 | import android.support.v4.content.AsyncTaskLoader; 11 | 12 | import com.j256.ormlite.dao.Dao; 13 | import com.j256.ormlite.stmt.PreparedQuery; 14 | 15 | public class OrmliteCursorLoader extends AsyncTaskLoader { 16 | final ForceLoadContentObserver mObserver; 17 | 18 | private Cursor mCursor; 19 | private AndroidBaseDaoImpl mDao; 20 | private PreparedQuery mQuery; 21 | 22 | 23 | /* Runs on a worker thread */ 24 | @Override 25 | public Cursor loadInBackground() { 26 | Cursor cursor = null; 27 | try 28 | { 29 | cursor = mDao.getCursor(mQuery); 30 | } catch (SQLException e) 31 | { 32 | e.printStackTrace(); 33 | } 34 | if (cursor != null) { 35 | // Ensure the cursor window is filled 36 | cursor.getCount(); 37 | registerContentObserver(cursor, mObserver); 38 | } 39 | return cursor; 40 | } 41 | 42 | /** 43 | * Registers an observer to get notifications from the content provider 44 | * when the cursor needs to be refreshed. 45 | */ 46 | void registerContentObserver(Cursor cursor, ContentObserver observer) { 47 | cursor.registerContentObserver(mObserver); 48 | } 49 | 50 | /* Runs on the UI thread */ 51 | @Override 52 | public void deliverResult(Cursor cursor) { 53 | if (isReset()) { 54 | // An async query came in while the loader is stopped 55 | if (cursor != null) { 56 | cursor.close(); 57 | } 58 | return; 59 | } 60 | Cursor oldCursor = mCursor; 61 | mCursor = cursor; 62 | 63 | if (isStarted()) { 64 | super.deliverResult(cursor); 65 | } 66 | 67 | if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) { 68 | oldCursor.close(); 69 | } 70 | } 71 | 72 | public OrmliteCursorLoader(Context context, AndroidBaseDaoImpl dao, PreparedQuery query) { 73 | super(context); 74 | mObserver = new ForceLoadContentObserver(); 75 | mDao = dao; 76 | mQuery = query; 77 | } 78 | 79 | @Override 80 | protected void onStartLoading() { 81 | if (mCursor != null) { 82 | deliverResult(mCursor); 83 | } 84 | if (takeContentChanged() || mCursor == null) { 85 | forceLoad(); 86 | } 87 | } 88 | 89 | /** 90 | * Must be called from the UI thread 91 | */ 92 | @Override 93 | protected void onStopLoading() { 94 | // Attempt to cancel the current load task if possible. 95 | cancelLoad(); 96 | } 97 | 98 | @Override 99 | public void onCanceled(Cursor cursor) { 100 | if (cursor != null && !cursor.isClosed()) { 101 | cursor.close(); 102 | } 103 | } 104 | 105 | @Override 106 | protected void onReset() { 107 | super.onReset(); 108 | 109 | // Ensure the loader is stopped 110 | onStopLoading(); 111 | 112 | if (mCursor != null && !mCursor.isClosed()) { 113 | mCursor.close(); 114 | } 115 | mCursor = null; 116 | } 117 | 118 | 119 | 120 | public PreparedQuery getQuery() 121 | { 122 | return mQuery; 123 | } 124 | 125 | public void setQuery(PreparedQuery mQuery) 126 | { 127 | this.mQuery = mQuery; 128 | } 129 | 130 | public Dao getDao() 131 | { 132 | return mDao; 133 | } 134 | 135 | @Override 136 | public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 137 | super.dump(prefix, fd, writer, args); 138 | writer.print(prefix); writer.print("mCursor="); writer.println(mCursor); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/com/j256/ormlite/android/support/extras/OrmliteListLoader.java: -------------------------------------------------------------------------------- 1 | package com.j256.ormlite.android.support.extras; 2 | 3 | import java.sql.SQLException; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import android.content.Context; 8 | import android.support.v4.content.AsyncTaskLoader; 9 | 10 | import com.j256.ormlite.dao.Dao; 11 | import com.j256.ormlite.stmt.PreparedQuery; 12 | 13 | public class OrmliteListLoader extends AsyncTaskLoader> 14 | { 15 | private Dao mDao = null; 16 | private PreparedQuery mQuery = null; 17 | private List mData = null; 18 | 19 | public OrmliteListLoader(Context context, Dao dao, PreparedQuery query) 20 | { 21 | super(context); 22 | mDao = dao; 23 | mQuery = query; 24 | } 25 | 26 | @Override 27 | public List loadInBackground() 28 | { 29 | List result = null; 30 | 31 | try 32 | { 33 | if (mQuery != null) 34 | { 35 | result = mDao.query(mQuery); 36 | } else 37 | { 38 | result = mDao.queryForAll(); 39 | } 40 | 41 | } catch (SQLException e) 42 | { 43 | result = Collections.emptyList(); 44 | } 45 | 46 | return result; 47 | } 48 | 49 | @Override 50 | public void deliverResult(List datas) 51 | { 52 | if (isReset()) 53 | { 54 | // An async query came in while the loader is stopped. We 55 | // don't need the result. 56 | if (datas != null) 57 | { 58 | onReleaseResources(datas); 59 | } 60 | } 61 | 62 | List oldDatas = mData; 63 | mData = datas; 64 | 65 | if (isStarted()) 66 | { 67 | // If the Loader is currently started, we can immediately 68 | // deliver its results. 69 | super.deliverResult(datas); 70 | } 71 | 72 | if (oldDatas != null && !oldDatas.isEmpty()) 73 | { 74 | onReleaseResources(oldDatas); 75 | } 76 | } 77 | 78 | /** 79 | * Handles a request to start the Loader. 80 | */ 81 | @Override 82 | protected void onStartLoading() 83 | { 84 | if (mData != null) 85 | { 86 | // If we currently have a result available, deliver it 87 | // immediately. 88 | deliverResult(mData); 89 | } else 90 | { 91 | // If the data has changed since the last time it was loaded 92 | // or is not currently available, start a load. 93 | forceLoad(); 94 | } 95 | } 96 | 97 | /** 98 | * Handles a request to stop the Loader. 99 | */ 100 | @Override 101 | protected void onStopLoading() 102 | { 103 | // Attempt to cancel the current load task if possible. 104 | cancelLoad(); 105 | } 106 | 107 | /** 108 | * Handles a request to cancel a load. 109 | */ 110 | @Override 111 | public void onCanceled(List datas) 112 | { 113 | super.onCanceled(datas); 114 | 115 | // At this point we can release the resources associated with 'apps' 116 | // if needed. 117 | onReleaseResources(datas); 118 | } 119 | 120 | /** 121 | * Handles a request to completely reset the Loader. 122 | */ 123 | @Override 124 | protected void onReset() 125 | { 126 | super.onReset(); 127 | 128 | // Ensure the loader is stopped 129 | onStopLoading(); 130 | 131 | // At this point we can release the resources associated with 'apps' 132 | // if needed. 133 | if (mData != null) 134 | { 135 | onReleaseResources(mData); 136 | mData = null; 137 | } 138 | } 139 | 140 | /** 141 | * Helper function to take care of releasing resources associated with an 142 | * actively loaded data set. 143 | */ 144 | protected void onReleaseResources(List datas) 145 | { 146 | // For a simple List<> there is nothing to do. For something 147 | // like a Cursor, we would close it here. 148 | } 149 | 150 | } 151 | --------------------------------------------------------------------------------