Android: extending android.app.Application - android

I have a DBHandler class that will be used in several activities to do some crud operations. created a MyApp class (extends Application) to hold one instantiation of the DBHandler.
My DBHandler class needs a Context to create the SQLiteOpenHelper to populate the db, etc.
That's where the problem starts: in my MyApp constructor, I want to instantiate my DBHandler, so I wrote this:
public MyApp() {
super();
dbh = DBHandler(<WHAT DO I PASS HERE>);
}
I tried getApplicationContext(), getBaseContext(), 'this'... nothing seems to be a fully-instantiated context at this point. I get a NPE when the SQLiteOpenHelper tries ctx.getResources().
A workaround: create the DBHandler and set it in the onCreate of my main class. -> UGLY (call me a aesthetician)
Question: is there a way to do it when Android creates MyApp?
Thanks!

Creating your DBHandler in MyApp.onCreate() is the proper way to do what you want.
#Override
public void onCreate() {
super.onCreate();
dbh = new DBHandler(this);
}

Related

Concept of introduce class, object?

i'm new here so still very blur with some certain things here.
& i'm a bit confuse with following codes.
public class SmsActivity extends ListActivity {
private String[] mSmsReceiver;
public SmsActivity(){
mSmsReceiver = new SmsReceived();
setListAdapter(new ArrayAdapter<String>(this, R.layout.main,mSmsReceiver));
my understanding: (should be wrong)
line 1: Class SmsActivity under a superclass ListActivity
line 2: i introduce a string array term name:mSmReceiver
line 3: calling method SmsActivity()
line 4: inside SmsActivity method, mSmsReceiver(a string array) call method SmsReceived
line 5: ArrayAdapter(in string form, loaded with the info. of mSmsReceiver) loaded into setListAdapter
My question:
pls correct my understanding upon code above.
line 5, what is this refers to?
(i checked on internet & books, it always says context. but i'm totally no idea what is context exactly means, anyone can explain what is context refering here?)
full codes:
import...
....
public class SmsActivity extends ListActivity {
private String[] mSmsReceiver;
public SmsActivity(){
mSmsReceiver = new SmsReceived();
setListAdapter(new ArrayAdapter<String>(this, R.layout.main,mSmsReceiver));
ListView listView = getListView();
listView.setTextFilterEnabled(true);
//---method is call when listitem is clicked---
listView.setOnItemClickListener(new OnItemClickListener() {edit later});
}
private class SmsReceived extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{..... }
}
}
Basically this is a definition of a class named SmsActivity.
You are right about line 1 and line 2. More precisely, mSmReceiver is a private number of class SmsActivity.
Line 3 should be the constructor which I am not sure because I'm not an android developer and I heard it use onCreate instead in Activity. But anyway it wouldn't be calling the method just definition of it. The constructor will be used to initialize the class.
And line 4 mSmsReceiver(a string array) call method SmsReceived. Not the case, it would be initialize mSmsReceiver with an object, which is an instance of class SmsReceived.
Line 5 this refers to the class SmsActivity. In classes this almost always refers to the class it's in. And this provide a context so you can use this.someMumber or this.someFunction.
The keyword "this" in Java is basically a reference to the Class that its in. For example:
public class MyClass {
MyClass myVar = this;
}
This will put an instance of the class MyClass in that variable. It gives you an instance of whatever class your in. If you call it in a method:
public void myMethod() {
MyClass m = this;
}
This will give you an instance of whatever class invoked myMethod. Weather its an instance of MyClass or an instance of a subclass of MyClass. Whatever instance used to invoke the method will be placed in the m variable.
So when you call "this" in an Activity it gives you an instance of that Activity.

Using singleton class for sharing instance of database between activities?

Hey! I want to use a singleton class, because if I open the database every activity I get "Leak found"( that happens because I open the database even if it is already open ) . I create a singleton class , but I don't know how should I use it.
Here is my class:
package com.ShoppingList;
import com.ShoppingList.databases.DbAdapter;
public class DbManager {
DbAdapter db;
// singleton
private static DbManager instance = null;
private DbManager() {
}
public static DbManager getInstance() {
if (instance == null)
instance = new DbManager();
return instance;
}
public void setinstance(DbAdapter db){
this.db=db;
}
public DbAdapter getinstancedb(){
return db;
}
}
In the first activity I put :
db = new DbAdapter(this);
db.open();
DbManager.getInstance().setinstance(db);
and for the next activity : DbManager.getInstance().getinstancedb(); but I get force close for second activity.
Can anyone help me how to use it? Thanks...
You can extend Application class and create there an instance of DbAdapter. This way it will be shared by all your activities.
Because db has the same context and life cycle of your first activity. Make your methods public and make them do all the setup/teardown necessary to return your desired result.
regarding the leak warning. Are you closing your db manager connection in onDestroy()?

How to pass database adapter to another activity?

I'm having some trouble understanding the search dialog in the Android SDK.
The "main activity" of my application provides a button. If the user clicks this button the search dialog is called. The search itself is then done in an async task as it might need some time. So far so good.
The main activity also creates a database adapter object which is used to initialize the database, perform queries, etc. But how can I use this adapter object in the searchable activity?
MAIN activity
// Init database
DatabaseAdapter dba = new DatabaseAdapter();
dba.init();
// open search dialog
if (buttonClick) onSearchRequest();
Searchable activity
Get intent and receive query from search dialog -> OK
How can I use the database adapter again to perform a query?
Do I have to create a new object? Can I pass it somehow from the min activity to the searchable activity, [...]?
Thanks,
Robert
You can create adapter in Application class, and retreieve it in all your activities. That's what I do for my projects.
public class ApplicationClass extends Application {
Adapter adapter.
#Override
public void onCreate(){
adapter=new Adapter();
super.onCreate();
}
public Adapter getAdapter(){
return adapter;
}
}
Then call from Activity:
Adapter adapter=(ApplicationClass)getApplication().getAdapter();
Something like that. ApplicationClass is for your app name. Could be MyAppNameApplication You should create it in your package and then declare in AndroidManifest.xml
An option would be to use a singleton and provide access to the DatabaseAdapter via a static method. Ex:
private static DatabaseAdapter sWritableAdapter = null;
private static DatabaseAdapter sReadableAdapter = null;
public static DatabaseAdapter openForReading(Context ctx) {
if(sReadableAdapter == null)
sReadableAdapter = new DatabaseAdapter(new DatabaseHelper(ctx).getReadableDatabase());
return sReadableAdapter;
}
or for write access:
public static DatabaseAdapter openForWriting(Context ctx) {
if(sWritableAdapter == null)
sWritableAdapter = new DatabaseAdapter(new DatabaseHelper(ctx).getWritableDatabase());
return sWritableAdapter;
}
So in your searchable activity you would write for instance:
DatabaseAdapter adapter = DatabaseAdapter.openForReading(ctx);
adapter.searchSomething();
Marco
You should rather implement an ContentProvider
http://developer.android.com/guide/topics/providers/content-providers.html
They are singletons, and accessible from (almost) everywhere in your application.

Access databasehelper object globally

Whenever i need to create SQLiteOpenHelper 'databasehelper' object, i need to pass the context in function call.
dbUtils.setEntityValues(this, moduleId, sendTo)
the 'this' parameter refers to the activity context. each time new databasehelper object is creating and perform db tasks.
DataBaseHelper dbHelper = new DataBaseHelper(context);
try {
dbHelper.openDataBase();
SQLiteDatabase db = dbHelper.getReadableDatabase();
From class files which are not extending Activity or Application, i cant create databasehelper object. Is there any way to get databasehelper object globally? OR any way to get the application context in classes that are not Activity...?
Im an android beginner, please suggest some tips..
Thanks in advance,
Joe
joe,
You can use getApplicationContext() or getBaseContext() to access the application context from classes that don't extend context.
You will probably also want to read up on this question a bit What's the difference between the various methods to get a Context?
Good luck!
Thanks willytate, I resolved it. the way i do it is...
class myActivity extends Activity {
public static Activity me = null;
...
protected void onCreate(Bundle icicle) {
...
me = this;
...
};
};
class myClass {
void myMthd() {
...
Intent myIntnt = myActivity.me.getIntent();
...
};
};
Now i can create the 'databasehelper' object without passing context like following..
public DataBaseHelper() {
super(myActivity.me.getApplicationContext(), DB_NAME, null, 1);
this.myContext = myActivity.me.getApplicationContext();
}
Thanks again,
Joe

How to make an Android singleton and custom data class with database?

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

Categories

Resources