Prevent multiple instantiation of an activity - android

Is it possible to make an activity singleton?
I have found many resources that just tell to use android:launchMode="singleInstance" or singleTask, but I would constructor to be called only once.
Ideally, I would like to be able to specify custom constructor/builder method e.g. getInstance()

You could store your references in Application instead of an Activity. The application class is de facto a singleton. You only need to define your access methods.
public class BaseApplication extends Application {
private static BaseApplication sInstance = null;
public synchronized static BaseApplication getInstance() {
return sInstance;
}
public synchronized static void setInstance(BaseApplication app) {
sInstance = app;
}
public BaseApplication() {
}
#Override
public void onCreate() {
super.onCreate();
setInstance(this);
}
Now you can access it by calling BaseApplication.getInstance(). As a bonus the Application extends Context so now you have an application context reference anywhere you want (safe to use pretty much everywhere except inflating layouts).
Don't forget to define this class as the base application class in your manifest:
<application
android:name="com.yourapp.BaseApplication">

Usually they do as follows:
1) define what comprise the Activity state
2) Save the state in onSaveInstanceState
3) Restore the state in onCreate or in onRestoreInstanceState

Related

Public Methods for all activities

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

can a singleton class extend Activity

I am using a singleton class to store global variables for the entire project. Also, to host some common functions which several classes/Activities may use, such as launching an alertBuilder window. But in order to do that... I need my singleton to extend Activity like this:
public class dataBaseObject extends Activity {
I tried to extend application, but that won't allow me to do this:
View view = context.getLayoutInflater().inflate(layoutType, null);
therefore, can someone tell me if there are any hidden pitfalls of extending Activity for a singleton ?
It doesn't make sense for an Activity class to be a singleton, because instances of Activity are instantiated by the android system.
What you can do is make an abstract class that extends Activity, like this
public abstract class AbstractActivity extends Activity {
public static final int EXAMPLE_CONSTANT = 345;
public final void exampleMethod() {
...
}
// This may not be needed
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
....
}
}
Then you can make all of your activity classes extend AbstractActivity. You do not need to declare an abstract class like this in manifest.xml.
An alternative solution is to make all of your utility methods have a parameter that is an Activity or a Context and pass this to these methods.

Get Android application from application context

I have access to application context but not to application. I want to get the application (so I can get all running activities), but couldn't find a way to do so. Is there an existing API to get application from application context or I will have to override getApplicationContext for that?
No, there's no such API out of the box. However, you can either get application context and cast it to Application object, or Extend Application class, and make it a singleton so you can grab an instance of it from everywhere.
public class MyApplication extends Application {
private static MyApplication singleton;
// Returns the application instance
public static MyApplication getInstance() {
return singleton;
}
public final void onCreate() {
super.onCreate();
singleton = this;
}
}

android: how to use getApplication and getApplicationContext from non activity / service class

I'm using extending application class on Android to share my data across the entire app.
I can use getApplication() method from all my activities.
However, there are certain custom helper classes I created; for example, an XMLHelper class which does not inherit from any activity / service class.
Here the getApplication() method is not available.
How do I sort this out and what are the best design practices to solve this?
The getApplication() method is located in the Activity class, that's why you can't access it from your helper class.
If you really need to access your application context from your helper, you should hold a reference to the activity's context and pass it on invocation to the helper.
The getApplication() method is located in the Activity class, so whenever you want getApplication() in a non activity class you have to pass an Activity instance to the constructor of that non activity class.
assume that test is my non activity class:
Test test = new Test(this);
In that class i have created one constructor:
public Class Test
{
public Activity activity;
public Test (Activity act)
{
this.activity = act;
// Now here you can get getApplication()
}
}
Casting a Context object to an Activity object compiles fine.
Try this:
((Activity) mContext).getApplication(...)
Either pass in a Context (so you can access resources), or make the helper methods static.
In order to avoid to pass this argument i use class derived from Application
public class MyApplication extends Application {
private static Context sContext;
#Override
public void onCreate() {
super.onCreate();
sContext= getApplicationContext();
}
public static Context getContext() {
return sContext;
}
and invoke MyApplication.getContext() in Helper classes.
Don't forget to update the manifest.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example">
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name">
<activity....>
......
</activity>
</application>
</manifest>
Sending your activity context to other classes could cause memoryleaks because holding that context alive is the reason that the GC can't dispose the object
try this, calling the activity in the constructor
public class WebService {
private Activity activity;
public WebService(Activity _activity){
activity=_activity;
helper=new Helper(activity);
}
}
((MyApplication) getApplicationContext()).myMethod()

Best way to get an Application Context into a static method in Android

I'm working on an Android application that has several Activities. In it I have a class with several static methods. I would like to be able to call these methods from the different Activities. I'm using the static methods to load data from an xml file via a XmlResourceParser. To create a XmlResourceParser requires a call on the Application Context. So my question is, what is the best way to get a reference to the Application Context into the static methods? Have each Activity get it and pass it in? Store it somehow in a global variable?
The better way would be to pass the Activity object as parameter to the static functions.
AFAIK, there is no such method which will give you the application context in the static method.
This should get you access to applicationContext from anywhere allowing you to get applicationContext anywhere that can use it; Toast, getString(), sharedPreferences, etc. I have used this to get applicationContext inside of static methods multiple times.
The Singleton:
package com.domain.packagename;
import android.content.Context;
/**
* Created by Versa on 10.09.15.
*/
public class ApplicationContextSingleton {
private static PrefsContextSingleton mInstance;
private Context context;
public static ApplicationContextSingleton getInstance() {
if (mInstance == null) mInstance = getSync();
return mInstance;
}
private static synchronized ApplicationContextSingleton getSync() {
if (mInstance == null) mInstance = new PrefsContextSingleton();
return mInstance;
}
public void initialize(Context context) {
this.context = context;
}
public Context getApplicationContext() {
return context;
}
}
Initialize the Singleton in your Application subclass:
package com.domain.packagename;
import android.app.Application;
/**
* Created by Versa on 25.08.15.
*/
public class mApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
ApplicationContextSingleton.getInstance().initialize(this);
}
}
If I´m not wrong, this gives you a hook to applicationContext everywhere, call it with ApplicationContextSingleton.getInstance.getApplicationContext();
You shouldn´t need to clear this at any point, as when application closes, this goes with it anyway.
Remember to update AndroidManifest.xml to use this Application subclass:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.domain.packagename"
>
<application
android:allowBackup="true"
android:name=".mApplication" <!-- This is the important line -->
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:icon="#drawable/app_icon"
>
Please let me know if you see anything wrong here, thank you. :)
I am not sure this is going to work all the time but it works for me now:
public class myActivity extends ListActivity
{
public static Context baseContext;
public void onCreate(Bundle savedInstanceState)
{
baseContext = getBaseContext();
}
Then you may use the static in your package:
myApplication.baseContext
There's a post in Sane Tricks For InsaneWorld blog with an answer.
It says you can replace the Application object with your own subclass and then keep the app context statically there.
You can find example code in the post.
The original blog post - http://uquery.blogspot.co.il/2011/08/how-to-get-application-context.html

Categories

Resources