I have code like this:
public class DatabaseHelper extends SQLiteOpenHelper
{
private static final String DATABASE_NAME = "IDATT.data.db";
private static final int DATABASE_VERSION = 201;
private Context mContext;
public DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
}
I wonder if onCreate/onUpgrade going to be called in super or after creation? Reason I ask - I need Context inside my onUpgrade/onCreate methods and don't know how to test this class
The onCreate() is always called when you instantiate you class, just like those ones that extends Activity.
The onUpgrade() just gonna to be called if you pass a different DATABASE_VERSION to the super call.
Hope it helps
Related
I would like to have a database for each user of my app. Usernames are stored in SharedPreferences. So I'm looking for something like this:
public class DatabaseHelper extends SQLiteOpenHelper {
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
String LoggedInUser = sp.getString("user","");
public static final String DATABASE_NAME = LoggedInUser + ".db";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
public void onCreate(SQLiteDatabase db) {
...
}
...
}
But this doesn't work, because SharedPreferences need context (using getApplicationContext() instead of this doesn't work either. This can be solved by something like this:
private Context appContext;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
this.appContext = context;
}
And then accessing SharedPreferences afterwards.
But I need to access SharedPreferences before this method ("DATABASE_NAME" is used in the above method and I want to define "DATABASE_NAME" using SharedPreferences).
Is there any way for doing this?
Since call to super() must be first statement, the only solution to achieve it would be to pass the DATABASE_NAME as constructor parameter:
public DatabaseHelper(final Context context, final string dbName) {
super(context, dbName, null, 1);
}
You can then either implement factory or Facade pattern to construct or pass the value to DatabaseHelper or simply pass the dbName value from Activity/Fragment.
An example of Factory could be:
public final class DatabaseFactory {
public static DatabaseHelper getDataBaseHelper(final Context context){
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
final String loggedInUser = sp.getString("user","");
return new DatabaseHelper(context,loggedInUser);
}
}
In Activity you can access the Helper as follows:
public class MainActivity extends Activity{
...
#Override
public void onCreate(Bundle savedInstanceState) {
...
final DatabaseHelper myDB = DatabaseFactory.getDataBaseHelper(this);
...
}
}
Must you use SharedPreference in you SQLiteOpenHelper?
I think you maybe use SQLite in your Activity, then how about declare SharedPreference in your Activity first, and get that in your SQLite through database's constructor.
I have a DBHelper class set up as a singleton:
public class DBHelper extends SQLiteOpenHelper {
private static DBHelper sInstance;
public static synchronized DBHelper getInstance(Context context) {
if (sInstance == null) {
sInstance = new DBHelper(context.getApplicationContext());
}
return sInstance;
}
private DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
databasePath = context.getDatabasePath(DATABASE_NAME).getPath();
}
}
I have a MainActivity and a number of fragments. Many of these fragments need access to my DBHelper methods
Should I be using dbHelper = DBHelper.getInstance(getApplicationContext()) in every fragment that needs database access? Instantiation will only happen once due to the singleton pattern, so I don't need to worry about the class being instantiated in every single fragment with that code
Or is it better to instantiate the DBHelper in MainActivity only, and then in any fragment that needs database access get a reference to the mainactivity and call the object methods from there? Something like this in each fragment:
mainActivity = (MainActivity) getActivity();
mainActivity.dbHelper.insertData();
Since you are sure Singleton will be instantiated in MainActivity the first approach shouldn't have any problems, you could even call getInstance(null) in your fragments
I think the most prodcutive decision will be create custom fragment class, extend it your fragment or v4.fragment, initialise in it dbHelper and use your custom fragment in your activity. it is my humble opinion :)
Codes here is one simple way to resolve concurrent problem in singleton pattern.
public DBHelper extends SQLiteOpenHelper {
// declare private constructor
// some public method
public static class Wrapper {
private static DBHelper dbHelper;
public static void init(Context ctx, Object otherArgs) {
// init DBHelper
dbHelper = new DBHelper(ctx, otherArgs);
}
public static DBHelper get(){
return dbHelper;
}
}
}
In custom Application
public MyApp extends Application{
void onCreate(){
DBHelper.Wrpper.init(this, otherArgs);
}
}
Code like this where DBHelper is needed:
DBHelper.Wrapper.get().insertData();
I have two database to support two languages for my application.
I want to change database when I change language from settings.
Is it possible?? How can i do this?
It should be possible quite easily when you provide a string resource with the name of the database:
In /res/values/strings.xml put a line like this:
<string name="db_name">database</string>
In /res/values-de/strings.xml put that line:
<string name="db_name">database_de</string>
And in your DBHelper class use the database name of the strings file currently active according to language settings:
public class DBHelper extends SQLiteOpenHelper {
private final static int DB_VERSION = 1;
private static DBHelper sInstance;
/**
* Provides access to DBHelper singleton.
* #param context
* #return
*/
public static DBHelper getInstance(Context context) {
// Use the application context, which will ensure that you
// don't accidentally leak an Activity's context.
// See this article for more information: http://bit.ly/6LRzfx
if (sInstance == null) {
sInstance = new DBHelper(context.getApplicationContext());
}
return sInstance;
}
/**
* Constructor should be private to prevent direct instantiation.
* make call to static factory method "getInstance()" instead.
*/
private DBHelper(Context context) {
// here comes the magic:
String dbName = context.getString(R.string.db_name);
super(context, db_name, null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
// ...
}
// ...
}
using Ridcully solution, you will need to add only the database name part,
all you need to add is the class you extend.
this example from the library you mentioned:
public class MyDatabase extends SQLiteAssetHelper {
private static final int DATABASE_VERSION = 1;
public MyDatabase(Context context) {
// here comes the magic:
String dbName = context.getString(R.string.db_name);
super(context, dbName , null, DATABASE_VERSION);
}
}
The other database class can be:
public class MyDatabase2 extends SQLiteAssetHelper {
private static final int DATABASE_VERSION = 1;
public MyDatabase(Context context) {
// here comes the magic:
String dbName = context.getString(R.string.db_name_2);
super(context, dbName , null, DATABASE_VERSION);
}
}
NOTE: to use SQLiteAssetHelper, u need to create the database yourself, and put in the assets/databases folder.
you can create sqlite database with this app Sqlitebrowser
04-11 05:05:17.837: W/SQLiteConnectionPool(6454): A SQLiteConnection object for database Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
this is an error return by my logcat ive searched for the possible solution for this error in here andhere saying you should close database but i have this code
#Override
protected void onPause() {
super.onPause();
if (db.isOpen()) {
db.close();
}
}
on all my ativity so im wondering why i get this error
public class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper sInstance;
private static final String DATABASE_NAME = "database_name";
private static final String DATABASE_TABLE = "table_name";
private static final int DATABASE_VERSION = 1;
public static DatabaseHelper getInstance(Context context) {
// Use the application context, which will ensure that you
// don't accidentally leak an Activity's context.
// See this article for more information: http://bit.ly/6LRzfx
if (sInstance == null) {
sInstance = new DatabaseHelper(context.getApplicationContext());
}
return sInstance;
}
/**
* Constructor should be private to prevent direct instantiation.
* make call to static factory method "getInstance()" instead.
*/
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
im currently doing the same thing im doing this tutorial if you want to try it you can you can find it here
I have database class. The class and its constructor are shown below.
public class LatLogDBAdapter {
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
I want to use the database in the static method. So that I declare as private static LatLogDBAdapter dbHelper;. Then when i initialize, i have problem. dbHelper = new LatLogDBAdapter(this); dbHelper = new LatLogDBAdapter(DetailMapView.this); make compile error. How can I use this in static method?
If you want to create static method that returns your dbhelper i suggest you to create normal subclass of SQLiteOpenHelper and in this class create public static method that will return new instance. This also is sounds like good reason to use design pattern Singleton
Update:
I mean I want to use this database class inside another java class.
That class has static method and use the database.
Here i create for you basic snippet of code:
public class AdapterWrapper {
private static SQLiteOpenHelper instance;
public static SQLiteOpenHelper getInstance(Context c) {
if (instance == null) {
instance = new DatabaseHelper(c);
}
return instance;
}
private static class DatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "Example";
private static final int DB_START_VERSION = 1;
public DatabaseHelper(Context cntx) {
super(cntx, DB_NAME, null, DB_START_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
// creating tables
}
#Override
public void onUpgrade(SQLiteDatabase db, int old, int new) {
/// drop an upgrading db
}
}
}