I want to access a class extending SQLiteOpenHelper to get the context of database from a java class. I need to pass application context to get that but don`t have access to getApplicationContext().
How can I get Application Context in java class that is not activity?
I suggest you create a constructor that has a parameter of the Context type.
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
// Variables
private Context ctx;
public MySQLiteOpenHelper(Context ctx) {
this.ctx = ctx;
}
//More code
}
Now, in your activities, you can do this:
MySQLiteOpenHelper helper = new MySQLiteOpenHelper(this);
And in your fragments, you can do this:
MySQLiteOpenHelper helper = new MySQLiteOpenHelper(getActivity().getApplicationContext()); //getActivity() would work too, Activity (indirectly) extends Context.
You can create custom Application class and write method getContext().
Someting like this:
public class MyApplication extends Application {
private static MyApplication mCurrentInstance;
#Override
public void onCreate() {
super.onCreate();
mCurrentInstance = this;
}
public static MyApplication instance() {
return mCurrentInstance;
}
public static Context context() {
return mCurrentInstance.getApplicationContext();
}
}
And add this class into manifest:
<application
android:name=".MyApplication">
Related
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();
Why does the following method throws an NPE,
public ActivityOne extends Activity{
DataManager dtMan = new DataManager(this)
public onCreate (){
...some source code here...
dtMan.check();
}
}
public class DataManager(){
private Context myContext;
public DataManager (Context context){
myContext = context;
}
Helper helper = new Helper(this);
public boolean check(){
helper.open();
...some source code here...
}
}
When I view the logcat; I get a java.null.pointer exception, so I did something like
public class DataManager(){
private Context myContext;
public DataManager (Context context){
myContext = context;
}
public boolean check(Context context){
**Helper helper = new Helper(context);**
helper.open();
...some source code here...
}
}
And it worked, so what is the difference between the two DataManager in Java/Android programming perspective, thus this approach if I understand correctly must be replicated to as follow:
public class DataManager(){
private Context myContext;
public DataManager (Context context){
myContext = context;
}
public boolean check(Context context){
**Helper helper = new Helper(context);**
helper.open();
...some source code here...
}
public boolean check2(Context context){
**Helper helper = new Helper(context);**
helper.open();
...some source code here...
}
public boolean check3(Context context){
**Helper helper = new Helper(context);**
helper.open();
...some source code here...
}
}
Meaning I just can't declare the Helper Class once and use it anywhere the calling class, did I forgot some fundamentals? Please clarify.
Will the context also lead to memory leaks?, if so, how will I fix it?
#EDIT:
Well I forgot to include the Helper Class
public class Helper{
private Context myContext;
public Helper(Context context){
myContext = context;
}
public void open(){
//do stuff here
}
}
Your code does not work because the DataManager is initialized at field scope in the Activity.
Classes which need a Context should always be initialized in one of the Activity's life cycle methods:
onCreate, onStart, onDestroy, etc.
Like this:
private DataManager dataManager;
public void on create(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
dataManager = new DataManager(this):
}
You also should initialize the Helper class in the DataManager constructor:
public class DataManager(){
private Context context;
private Helper helper;
public DataManager (Context context){
this.context = context;
this.helper = new Helper(this.context);
}
public boolean check(Context context){
helper.open();
//...some source code here...
}
}
To prevent memory leaks you just need to make sure the DataManager class is not a static instance with an Activity Context.
If you don't need an Activity Context but you're also fine with an Application Context you should use it:
public DataManager(Context context){
this.context = context.getApplicationContext();
//...
}
Try put
dtMan = new DataManager(this)
in onCreate method in Activity?
I know I can use getApplicationContext() to get Context from sub class of ListActivity.
but PublicPar is common class, how can I get Context from this class.
public class SMSMain extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
Context my=getApplicationContext();
}
}
public class PublicPar {
public static void SetNotification(){
}
}
If you have a common (helper-type) class like your PublicPar class, the best you can do is to pass context as a parameter to each method:
public static void SetNotification(Context context) {
}
Remember to not set this context to any PublicPar class variable to avoid leaking it.
Try this. It should work:
public class SMSMain extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// Context my=getApplicationContext();
new PublicPar().SetNotification(SMSMain.this)
}
}
public class PublicPar {
public static void SetNotification(final Context context ){
// You can proceed with using the context here.
}
}
If you don't want to pass the Context around as part of constructor argument, you can expose a static method in the application.
public class MyApplication extends Application {
private static MyApplication myinstance;
public MyApplication() {
myinstance = this;
}
public static Context getAppContext() {
myinstance.getApplicationContext();
}
}
I want to start an activity from a static java method on an android device.
I do not have any context or anything passed as parameter to the static function.
For starting the activity I must call "startActivity" with the current running method as "this" pointer. So is there a way to get the current running activity?
You can access only static variables/objects inside static method.
So You need to Implement this way
public class MainActivity extends Activity {
private static Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
}
public static void goToLoginActivity() {
Intent login = new Intent(mContext, LoginActivity.class);
mContext.startActivity(login);
}
}
NOTE : But this is not the proper way to do so, this may cause window leak issue.
Better approach is pass activity/context object as parameter like this.
public static void goToLoginActivity(Context mContext) {
Intent login = new Intent(mContext, LoginActivity.class);
mContext.startActivity(login);
}
Create a Class in your app extending class Application, define a static context and initialise this with your application context. You can expose a static method from this class for accessing defined static reference. Thats it.
class MyApp extends Application{
private static Context mContext;
public void onCreate(){
mContext = this.getApplicationContext();
}
public static Context getAppContext(){
return mContext;
}
}
Now you can use this static method for accessing context anywhere in your app.
I'm playing with the GCM.
Everything is perfect using the example on https://code.google.com/p/gcm/source/checkout
Im getting notifications on my app with the gcm messages,
Now I want to add the message in a listView located on my MainActivity.
Im receiving my messages on a different class (GcmIntentService.java). How can I get MainActivity context to sendBroadcast.
Already tried with
private static Context mContext;
public static Context getContext() {
return mContext;
}
public static void setContext(Context context) {
mContext = context;
}
But is not working.
Any Ideas.
Thanks
I am not sure what you are doing. But keeping the below in mind
Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself).
http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/
You can do as below
Example:
new MyClass(ActivityName.this);
class MyClass
{
Context mContext;
public MyClass(Context context)
{
mContext=context;
}
}
pass the context variable through constructor .
create new activity like below
public class GetContext extends AppCompatActivity {
Context mainActivity;
public GetContext(Context mainActivity){
this.mainActivity = mainActivity;
}
and in your previous mainActivity send this context as below
GetContext sendContext = new GetContext(mainActivityContext);
where mainActivityContext is Context mainActivityContext = this;
or simply pass this instead of mainActivityContext
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_get_attendance_from_database);
}