I need to have an access to helper not only from Activities, but, for example, from BroadcastReceivers and AsyncTasks. Am I right, that if I am using OrmLiteBaseActivity to approach it is to use this methods:
OpenHelperManager.getHelper(context, DatabaseHelper.class);
OpenHelperManager.releaseHelper();
inside not Activity classes?
EDIT:
I understand that helper lifecycle is handled by OrmLiteBaseActivity. What I am asking is how to handle helper lifecycle outside of activities. For example, I need an access to database from BroadcastReceiver or AsyncTask. Is it a right way to achieve this using OpenHelperManager.getHelper(context, DatabaseHelper.class);, when I am starting some database stuff in another thread, and OpenHelperManager.releaseHelper();, when I've done all database work and want to release helper?
Am I right, that if I am using OrmLiteBaseActivity to approach it is to use this methods...
Yes, using the OpenHelperManager.getHelper(...) and releaseHelper() methods is the right way to do this. To quote from the ORMLite Android docs:
If you do not want to extend the OrmLiteBaseActivity and other base classes then you will need to duplicate their functionality. You will need to call OpenHelperManager.getHelper(Context context, Class openHelperClass) at the start of your code, save the helper and use it as much as you want, and then call OpenHelperManager.release() when you are done with it. You will probably want to have something like the following in your classes:
The sample code in the docs is:
private DatabaseHelper databaseHelper = null;
#Override
protected void onDestroy() {
super.onDestroy();
if (databaseHelper != null) {
OpenHelperManager.releaseHelper();
databaseHelper = null;
}
}
private DBHelper getHelper() {
if (databaseHelper == null) {
databaseHelper =
OpenHelperManager.getHelper(this, DatabaseHelper.class);
}
return databaseHelper;
}
Related
I am trying to use ORMLite in my app (because apparently writing all the CRUD methods myself is the "harder not smarter" way to develop), but I am running into a problem: A lot of the sample projects I see have Activities that extend OrmLiteBaseActivity. Normally my Activities extend AppCompatActivity.
Is this going to be a problem at all? Does OrmLiteBaseActivity extend AppCompatActivity anywhere? Or do I have to sacrifice AppCompat if I go with ORMLite?
I'm not familiar with ORMLite however I wouldn't recommend dropping AppCompat in favor of ORMLite. So what can you do?
By looking at the source of ORMLiteBaseActivity you can see that this class extends Activity and not AppCompatActivity which basically makes sense for a library. Furthermore you can see that the class doesn't do much.
So Option #1 don't use the ORMLiteBaseActivity or Option #2 create an own Base Activity for your app which extends AppCompatActivity and does the same as the ORMLiteBaseActivity. In other words: It would be an option to copy the class in your project and to simply replace the extends part.
As for 2021, actually, you can do better. So you should not sacrifice AppCompatActivity for OrmLiteBaseActivity, you may use them both.
First, import OpenHelperManager:
import com.j256.ormlite.android.apptools.OpenHelperManager;
define object in your activity
private DatabaseHelper databaseHelper = null;
use following getHelperMethod
private DatabaseHelper getHelper() {
if (databaseHelper == null) {
databaseHelper = OpenHelperManager.getHelper(this, DatabaseHelper.class);
// we don't need the following line that much
// databaseHelper.getWritableDatabase(); // explicitly calls onCreate method of DatabaseHelper
//where you create tables for example, again it will be called anyway
}
return databaseHelper;
}
Override OnDestroy of your AppCompatActivity to free resources when your activity is done
#Override
protected void onDestroy() {
super.onDestroy();
if (databaseHelper != null) {
OpenHelperManager.releaseHelper();
databaseHelper = null;
}
}
So you may call any method of DatabaseHelper in my case listAllEntries() from your activity like this:
getHelper().listAllEntries();
I want to check if a SQLite Database is open, and if it is, I would like to access that Database within a service class.
I am worried, and have seen, that multiple open calls to the database clash, and throw exceptions. Because I do query the database within both my Activity and Service classes, I am attempting to implement the solution Commonsware recommended here: When to close db connection on android? Every time after your operation finished or after your app exit. However I do not want to close then open the Database within the Service class if the Activity might need it. From this answer Why use SQLiteOpenHelper over SQLiteDatabase?, it looks like it might make sense to implement a SQLiteOpenHelper to solve the issue of making multiple calls.
Thank you so much for all your help!!
This man Kevin is a legend: http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection. Thank you so much.
On that link he shares his ridiculously simple solution:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static DatabaseHelper instance;
public static synchronized DatabaseHelper getHelper(Context context)
{
if (instance == null)
instance = new DatabaseHelper(context);
return instance;
}
//Other stuff...
}
Then in my SQLite class I changed my code to look like this:
public BlacklistWordDataSource(Context context) {
dbHelper = MySQLiteHelper.getHelper(context);
}
at onCreat in the activity put datasource.open();
then do what ever you want
and at the end of actevity put this to close :
/** Call after close activity */
#Override
protected void onStop() {
super.onStop();
//Close dataSource
datasource.close();
}
I have an SQLite database that is in a separate class from the main class that extends Activity.
I noticed that there are two ways of setting up the database. one way is to put it inside the main Activity class, either in the class or as a nested sub class. the second way is to put it in the separate class.
the separate class looks better, however there is one disadvantage. You have to create an instance of it in the main activity class every time you want to do something. I read that instantiating objects in Android is expensive and should be avoided.
despite this, I would rather make the database as a separate class. Is the cost of instantiating objects enough that it makes putting the database in the same class a better deal?
example of separate class for SQLite database: incomplete psudo-code
public class SQLiteDB {
private static class DbHelper extends SQLiteOpenHelper{
// db helper methods
}
// methods for DB, like get, set, and others
public void openDatabase(){ }
public void closeDatabse(){ }
public void insertRecord(String record){ }
}
example use in main Activity: incompete psudo-code
public class Main extends Activity{
// every time I want to use it I must instantiate an object for the database class
// many instances of SQLiteDB object created, garbage collector works hard
SQLiteDB mDatabase = new SQLiteDB();
openDatabase();
insertRecord("insert this");
closeDatabase();
}
SQLite database in separate class vs. in same class, which is better?
This is very comprehensive question and it depends on more factors(type of application, personal requirements, how you'll deal with db etc.). Somebody can prefer to place database as inner class and someone as separated class. Problem is that many developers are trying to "stick" as much code as possible into one class and maybe they "fear" to create a little more classes. I don't know that exactly. I mentioned that only as my personal note.
But let's back to your question. What is better?
I think that approach with separeted class. You should let your Activity classes only "Activity classes" > only for creating and dealing with UI. Application appearance should be separated from application logic. If you'll follow this "rule" your code will become more clean and human-readable(if someone else will look at your code he shouldn't be completely lost). It's not a shame to have 20 purely written classes as to have all stuff sticked in one class(like a pig).
however there is one disadvantage. You have to create an instance of
it in the main activity class every time you want to do something. I
read that instantiating objects in Android is expensive and should be
avoided.
Did you think about an usage of Singleton? This design pattern is worth to think about it. You will always have only one instance that have many benefits e.q. no waste of memory. I have only good experiences with Singleton. Therefore i recommend you to try and use it.
Example:
private static SQLiteOpenHelper instance;
public static SQLiteOpenHelper getInstance(Context mContext) {
if (instance == null) {
instance = new SQLiteOpenHelperImplementation(mContext);
}
return instance;
}
And at the end i give you a few suggestions:
Everytime you'll work with cursors, databases etc. release / close
them immediately after work is done. This can solve many exceptions
related to SQLiteDatabase and Cursor
An usage of synchronized blocks and methods is pretty good practise
in the case of concurrent programming to avoid many problems
If you have more than one table in database i suggest you create
"serving" class for each table that will wrap CRUD operations and specific
methods of the table
Before Activity is destroyed, check and release all sources which are not
already released.
I prefer the solution you gave here. The primary advantage is that you can easily access the database from any Activity (or other class) in your app. To solve the problem of creating a new instance every time you use the database, you can instead create a single instance in onCreate(), use the database all you want while the Activity is active, and finally close the database in onDestroy().
This would be a matter of personal taste.
However, what I've found to be efficient and clean has been to create a class that extends SQLiteOpenHelper. In this class you will end up writing the SQL code to create your tables and writing methods as your stored procedures.
The class would look something like this:
public class DatabaseInterface extends SQLiteOpenHelper {
// Database version
private static final int DATABASE_VERSION = 1;
public DatabaseInterface(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
//in your oncreate you will write the queries to create your tables
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_NEWS = "CREATE TABLE News(id INTEGER)";
db.execSQL(CREATE_NEWS);
}
// upgrading tables
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// drop tables if exist
db.execSQL("DROP TABLE IF EXSIST " + NEWS);
// recreate tables
onCreate(db);
}
Consider we have a News obj that takes 1 param as it's constructor, your stored procedures can look something like this:
public ArrayList<News> getNews() {
ArrayList<News> mNewes = new ArrayList<News>();
SQLiteDatabase db = null;
Cursor cursor = null;
try {
String sQry = "SELECT * FROM " + NEWS;
db = this.getWritableDatabase();
cursor = db.rawQuery(sQry, null);
if (cursor.moveToFirst()) {
do {
mNewes.add(new News(cursor.getInt(0)));
} while (cursor.moveToNext());
}
} catch (SQLiteException e) {
Log.e("SQLite - getNewes", e.getMessage());
return null;
} finally {
cursor.close();
db.close();
}
return mNewes;
}
In the above method you get and open the application database preform the query on it, anticipating any sql errors and then close the database. Doing it this way assures that you never have any resources open that you don't need/aren't using.
I've used this method in two apps that are currently out in the market and it runs rather quickly with making several hundred calls to methods I created for my stored procedures
Consider following: I've got Service, which writes into DB in AsyncTask. And my Activity reads data from DB(consider UI thread for simplicity). I access DB using SQLiteOpenHelper. I create single instance in Application onCreate() and then obtain it in service and activity. Is there any possibility that I would get my DB 'dead locked'? Previously, I used ContentProvider for such operations. Though, it is based on using single SQLiteOpenHelper instance, I decided to simplify my project by excluding ContentProvider.
Consider code:
public class App extends Application {
private OpenHelper openHelper;
#Override
public void onCreate(){
super.onCreate();
openHelper=new OpenHelper();
}
public OpenHelper getHelper(){
return openHelper;
}
}
In Activity:
OpenHelper helper=(App)getApplication().getHelper();
SQLiteDatabase db=helper.getReadableDatabase();
// Do reading
And inside Serice, in separate thread:
OpenHelper helper=(App)getApplication().getHelper();
SQLiteDatabase db=helper.getWritableDatabase();
//Do writing
Would it be safe?
UPD This might be the solution, but not sure how to use it.
Late, late answer. You're totally fine. That's the proper way to do it, actually. See my blog post: http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection/. Dig through my profile here. Lots of examples of this. ContentProvdier is just a lot of overhead and not needed unless you're sharing data outside of your app. Transactions are good to speed things up and (obviously) improve consistency, but not needed.
Just use one SqliteOpenHelper in your app and you're safe.
My bet: it isn't safe.
To be in safer position you should use SQL transactions. Begin with beginTransaction() or beginTransactionNonExclusive() and finish with endTransaction(). Like shown here
This is my solution
I created a class and a private static object to syncronize all db access
public class DBFunctions {
// ...
private static Object lockdb = new Object();
/**
* Do something using DB
*/
public boolean doInsertRecord(final RecordBean beanRecord) {
// ...
boolean success = false;
synchronized (lockdb) {
// ...
//
// here ... the access to db is in exclusive way
//
// ...
final SQLiteStatement statement = db.compileStatement(sqlQuery);
try {
// execute ...
statement.execute();
statement.close();
// ok
success = true;
} catch (Exception e) {
// error
success = false;
}
}
return success;
}
}
I tryed using ASYNC task and it works fine .
I hope is the right way to solve the problem.
Any other suggestions ???
Good question. My first thought is it wouldn't be safe. However, according to the SQLite docs, SQLite can be used in 3 modes. The default mode is "serialized" mode:
Serialized. In serialized mode, SQLite
can be safely used by multiple threads
with no restriction
So I assume this it's compiled in serialized mode on Android.
Just saw this while I was looking for something else.
This problem looks like it would be efficiently solved by using a ContentProvider. That way both the Activity as well as the Service can use the content provider and that will take care of the Db contention issues.
I want to use a singleton pattern to hold a database and some other data/methods for my Android application.
I realize there are many reasons against singletons, but for this case I'd like to use it.
I've sub-classed UIApplication and made a data class within it called MyAppData.
MyAppData needs to have access to the SQLite database.
When I create the databse, I need to pass a context. I could pass the application context, but it will not directly relate to MyAppData.
I don't know if this wlll cause problems with my code.
So my thought is to have MyAppdata extend android.content.ContextWrapper. I don't think I should extend Activity because it's really not an activity, its a data class with methods to access the database.
I'm wondering if I extend ContextWrapper will there be something deep in the code I'm missing that will cause big problems down the road (memory leaks, etc).
This may not be the ideal approach to this (and I've considered other options), but my goal is to:
Have a singleton class in UIApplication that can encapsulate the database and be retrieved easily from any activity in my app.
Thanks in advance for your suggestions/warnings/advice.
Subclass android.database.sqlite.SQLiteOpenHelper and android.app.Application (with the latter being properly declared in AndroidManifest.xml).
Now,
public class MyApplication extends Application {
private static SQLiteOpenHelper openHelper;
#Override
public void onCreate() {
super.onCreate();
openHelper = new DbManager(this);
//
}
public static SQLiteDatabase getDB() {
return openHelper.getWritableDatabase();
}
}
Then have helper DAO classes that will perform instertions/updates/etc.
That's what I'm using in all of my apps.
I've used this approach:
Create a class responsible for managing the db, let's call it DBUtil. This class will extend android.database.sqlite.SQLiteOpenHelper. You can pass a reference to the application context to the constructor of this class. This class will contain methods for creating the db, adding, removing and retrieving items.
Create another class, let's call it AppCore, create a static instance of the DBUtil and a static init() method that accepts an ApplicationContext object
public class AppCore
{
public static var dbUtil:DBUtil;
public static void init( ApplicationContext context )
{
dbUtil = new DBUtil( context );
}
}
Then in the onCreate() method of our your application's main Activity, initialize the AppCore class.
#Override
protected void onCreate(Bundle savedInstanceState)
{
AppCore.init( getApplicationContext() );
}
So, it's not really a Singleton. Instead, the DBUtil instance is maintained as a static property, yet still accessible throughout your application, such as this:
AppCore.dbUtil.createNewRecord( params );
Also, I found this tutorial to be very helpful when getting started with this topic: http://developer.android.com/guide/tutorials/notepad/index.html