I am stuck in a problem. I am creating a helper class that needs to be Singleton. And that class has a global context variable. I am not able to do this since context is available only from onCreate and this Singleton instance is created much before since it is static.
Can someone help me on how to solve this issue. Context is needed for the Singleton instance finally.
public class Helper {
private static Helper sHelper = new Helper() ;
private Helper () {} ;
public static Helper getInstance() {
return sHelper;
}
public boolean doSomething() {
mContext.getContentResolver;
return isDone;
}
}
You can set the context to be you ApplicationContext.
You can create an Application class and implement something like:
yourSingletonClass.getInstance().setContext(this);
This call should be in you application class under the onCreate method.
For more information try this docs:
Android - Application class
You just need to pass the following context to your helper class.
getApplicationContext()
You need pass the context trougth your construct helper class:
getApplicationContext()
Related
I have a class that's inputting some data into SharedPreferences.
private static Context context;
context = MainActivity.getContext();
sp = (SharedPreferences) context.getSharedPreferences("currentData", Context.MODE_PRIVATE).edit();
SharedPreferences.Editor editor = sp.edit();
editor.putString("name", placeName);
editor.apply()
I set the context using a method in my MainActivity class:
public static Context getContext(){
return context;
}
However I keep getting a null object reference. Tried multiple solutions from stack overflow and can't overcome the issue.
Why is context returning null?
This is because MainActivity.getContext() is null try passing the context from MainActivity to your class.
public Context context;
public YourClass(Context context) {
this.context= context;
}
In MainActivity init it like this:-
YourClass yours = new YourClass(MainActivity.this);
And also avoid using static contexts it might cause memory leaks !!
Context is an abstract class whose implementation is provided by the
Android system
Context is provided to any Activity by the android system during runtime (Activity indirectly extends Context). You are trying to get Context from MainActivity class via static method, which will not work and will always return null:
context = MainActivity.getContext();
You should always get Context from an instance of Activity, not the class itself. You can do this easily by passing an instance of your current Activity to the constructor of your class. Then, you call getContext() on an INSTANCE of that Activity, not the Activity class itself.
Also, wanted to mention that your code is mostly anti-pattern. You should never store Context in static variables. I'd recommend you read more about Activity lifecycle in android and Context - these are fundamental knowledge.
You can get context statically throughout the application
please try below code:
In the Android Manifest file, declare the following.
<application android:name="com.xyz.MyApplication">
</application>
Use this class
public class MyApplication extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
MyApplication.context = getApplicationContext();
}
public static Context getAppContext() {
return MyApplication.context;
}
}
Now you can call MyApplication.getAppContext() to get your application context statically.
You are getting the context from a static method in the class, that mean that method is called before the class is actually initialized. If there is no actual instance of the activity or if the OS haven't provide with context to the activity, then is null. The Activity has access to the contexto but after the Android underlining management initialized it, the class won't have the context by it self because it is there, if you notice Activities are never instantiated using the constructor because Android does it for you.
If you want to use a static method to having a nice syntax then the static method should be inside the class that use the shared preferences and should be passed from the activity, during any method of the Activity life cycle or when the user interacts with the ui (those listeners are set on the Activity life cycle).
class MyPreferences {
static void save(String toSave, Contex context) {
//TODO your operation here
}
}
And your activity:
public class MainActivity extends AppCompatActivity {
//Below is pseudo code, be careful on doing this precisely in the activity
#Override
onCreate() {
//TODO call super and setContentView
MyPreferences.save("foo", this);
}
}
It seems your problem is you are trying to make the other class to use the Activity, but in Android is the Activity that uses other classes
I have a class called myConstants and in it i list all my constants so when i need them I just reference MyConstants.MYCONSTANT. However, i would like to implement something like this for methods. i am repeating a lot of code, for instance, i have a formatCalendarString(Calendar c) method in 3 activities. seems redundant and unecessary. but i cant make them static because i get static calling non-static errors and the only other way i can think is to make a MyConstant object then call public functions off that object, like this...
MyConstants myConstants = new MyConstants();
myConstants.formatCalendarString(Calendar.getInstance());
is there some way i can just call the formatCalendarString() inside MyConstants class without generating an object?
You can use singleton pattern to cache instances. Keeping methods in something like parent activity does not make any sense (as primary role of activity is user interaction).
Example:
public class MyConstants {
private static MyConstants ourInstance;
private MyConstants() {
//private constructor to limit direct instantiation
}
public synchronized static MyConstants getInstance() {
//if null then only create instance
if (ourInstance ==null) {
ourInstance = new MyConstants();
}
//otherwise return cached instance
return ourInstance;
}
}
You just need a private constructor and public static method that would only generate instance if it is null.
Then, call MyConstants.getInstance().whateverMethod(). It will create only single instance.
However when using singleton, please keep memory leaks in mind. Do not pass activity context directly inside singletons.
If you want to have all methods in activities, you can put then in abstract class BaseActivity, which extends Activity, and then make your activities extends BaseActivity. However, if these methods doesn't correspond to something about activity, I suggest some Singleton or Util class
I agree with Pier Giorgio Misley. It's also good to add a private constructor, because you don't obviously want to instantiate an object.
Can't you just use a parent class? That way you can just inherit the methods and manage in one source. Then you don't have to use static functions then.
Edit: Like Tomasz Czura said, just extend the Class.
public class ParentClass {
public void commonMethod(){
}
}
public class OtherClass extends ParentClass{
}
You can use the Static keyword.
Static methods can be referenced from outside without istantiating the new object.
Just create a class:
public class MyClassContainingMethods{
public static String MyStaticMethod(){
return "I am static!";
}
}
Now call it like
String res = MyClassContainingStaticMethods.MyStaticMethod();
Hope this helps
NOTE
You CAN call non-static from static by doing something like this:
public static void First_function(Context context)
{
SMS sms = new SMS();
sms.Second_function(context);
}
public void Second_function(Context context)
{
Toast.makeText(context,"Hello",1).show(); // This i anable to display and cause crash
}
Example taken from here, you will obiouvsly have to fit it into your needs
From MyActivity, call to:
MyClass.getInstance();
MyClass.doStuff();
...
#EBean(scope = EBean.Scope.Singleton)
public class MyClass {
#Bean
MyManager manager;
public static void doStuff(){
manager.show();
// null pointer exception for the manager why ? how to access it ?
}
public static MyClass getInstance() {
if (_instance == null) {
_instance = new MyClass();
}
return _instance;
}
}
...
#EBean(scope = EBean.Scope.Singleton)
public class MyManager {
public void show(){ }
}
Android annotations access singleton class object into other class static method. Note : AA version 3.3.1
I am afraid you are using AA #EBean incorrectly. Did you read the documentation?
You do not have to write a getInstance() method yourself, AA will generate the appropriate method, do the injections in it, and automatically call it when injecting the bean into other components. You got a NullPointerException because you created the bean with your own getInstance() method, so no AA injections were performed. But actually you are getting a compile error in doStuff(), because you are accessing an instance field in a static method... So i assume the manager field is static, right? You should not use static fields/methods in singletons, the concept of the singleton is one instance is existing only, so using static fields/methods is redundant and also confusing.
You can fix the problem by either:
Creating an instance of MyClass by calling MyClass_.getInstance(context) manually, then use it
Inject a MyClass instance into another component with the #Bean annotation and use it from there
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
I'm considering creating a singleton wrapper for a Context so my model objects, if necessary, can open and read from a database connection. My model objects do not have access to a Context, and I'd like to avoid needing to pass a reference to a Context from object to object.
I was planning to place into this singleton a reference to the Context returned by Application.getApplicationContext(). This singleton object would be initialized in my custom Application instance before anything else would need to or have a chance to use it.
Can anyone think of a reason to not do this?
I would urge you to think about what reasons you have for not passing a reference of the application context into your model objects.
There are various well-documented disadvantages of using singletons. I won't go into detail here but you might want to consider:
How singletons limit your ability to properly unit-test your application.
Singletons hide dependencies between different entities in the code- you cannot determine dependecies from inspecting the interfaces.
You have no real control over the lifetime of a singleton, it could exist for the lifetime of your application. Do you really want to potentially hold a DB connection for the lifetime of your app?
The thread safety of your singleton.
If you valid reasons for not passing a reference to a context to other parts of your application then perhaps you should consider some other pattern- a factory might be one possible solution, a service another.
I'm not sure I get your idea, but here's what's been working for me:
public class MyApp extends Application {
private static MyApp instance;
#Override
public void onCreate() {
super.onCreate();
instance = this;
// ...
}
public static MyApp getInstance(){
return instance;
}
// misc helper methods
}
Pasted here to preserve formatting.
public class ContextContainer
{
private static boolean initialized;
private static Context context;
private ContextContainer()
{
//
}
public static synchronized void setApplicationContext(Context context)
{
if (!initialized) {
ContextContainer.context = context;
initialized = true;
} else {
throw new RuntimeException("ApplicationContext has already been set!");
}
}
public static synchronized Context getApplicationContext()
{
return context;
}
}