I would like to extend my Application class in order to globally access the logged in ParseUser without repeatedly calling .getCurrentUser() and accessing it's fields in every activity.
Currently my Application class is already extended to initialize Parse and ParseFacebookUtils. As per this thread, it says to make an instance of the ParseUser in the Application class however I'm not sure how to do so.
Note: I do not want to use intents as ParseUser is not serializable.
Thank you for your help. I can't see the relevance for code inclusion but please ask if you require any.
Method ParseUser.getCurrentUser() doesn't perform any network operations so it can't block UI. Also it is static, so by some means it already gives you global access.
I think it is not the best idea to duplicate it's value somewhere and it could cause bugs
What you can do is have 2 attributes in the existing application class.
isLoggedIn(boolean) - initialise it as false
user(ParseUser)
And place getters and setters.
When the user logs into the system you can set the isLoggedIn to true and set the user as well in the loginActivity. Suppose extended Application class is MyApplication.
((MyApplication)getApplication).setIsLoggedIn(true)
((MyApplication)getApplication).setUser(parseUser) .
After that you can in other activities you can simply check the isLoggedIn boolean value and do the necessary actions.
You can retrieve the set user by
ParseUser currentUser = ((MyApplication)getApplication).getUser()
Hope this helps.
I have implemented a Singleton to solve my problem. I have extended the Application class to initialize a Singleton so that an instance of this Singleton exists whether an activity is destroyed or othewise. I can access this instance via any activity and as such access all the fields of the current ParseUser.
// Application Class
public class Application extends android.app.Application{
#Override
public void onCreate() {
Parse.initialize(this, "redacted", "redacted");
ParseFacebookUtils.initialize(this);
initSingleton();
}
protected void initSingleton() {
ParseUserSingleton.initInstance();
}
}
// Singleton Class
public class ParseUserSingleton {
private static ParseUserSingleton instance;
public ParseUser user;
public HashMap<String, String> userFields = new HashMap<>();
public static void initInstance() {
if (instance == null) {
// Create the instance
instance = new ParseUserSingleton();
}
}
public static ParseUserSingleton getInstance() {
// Return the instance
return instance;
}
private ParseUserSingleton() {
// Constructor hidden because this is a singleton
}
public void customSingletonMethod() {
try {
user = ParseUser.getCurrentUser().fetch();
} catch (ParseException e) {
e.printStackTrace();
}
userFields.put("name", user.get("availability").toString());
// repeat for other fields
}
}
// Activity access
ParseUserSingleton.getInstance().customSingletonMethod();
userHashMap = ParseUserSingleton.getInstance().userFields;
Related
I have this simple module SharePreferencesModule.java :
#Module(includes = ApplicationModule.class)
public class SharedPreferencesModule {
#Provides
SharedPreferences sharedPreferences(MyApp app) {
return app.getSharedPreferences("...", Context.MODE_PRIVATE);
}
#Provides
#Named("firstname")
static String getFirstname(SharedPreferences preferences) {
return preferences.getString("firstname", "");
}
}
With this component SharedPreferencesComponent.java :
#Component(modules = SharedPreferencesModule.class)
public interface SharedPreferencesComponent {
void inject(MyFragment myClass);
}
And this class, which is using the module :
public MyFragment extends Fragment {
#Inject
#Name("firstname")
String firstname;
#Override
public void onAttach(Context context) {
// Not posting "Injector" code in the snippet because it is irrelevant
Injector.getSharedPreferencesComponent().inject(this);
}
}
When MyFragment is created I successfully inject the firstname, but if edit the shared prefs, I am still referencing the old value of firstname. Which is normal because Dagger is providing the firstname only when MyFragment is attached.
How can I stay up to date with the shared prefs ?
Should I re-inject MyFragment everytime the shared prefs are updated ? Seems messy to me.
Or can I somehow force Dagger to fetch this data for me ?
Should I re-inject MyFragment everytime the shared prefs are updated ?
You should only inject once, in the same way that you don't call the constructor multiple times.
There might be some exceptions where it would indeed be necessary (or preferrable) to inject again, but all of those injections should happen before you start using your objects. Injecting multiple times leads to an inconsistent state where it is unclear which object references which version of your injected objects.
This might work in some cases, but will lead to difficult bugs in others, and either way you will have a hard time to set it up, making sure to update everything. You'd be better off just destroying and recreating the whole fragment everytime something changes.
Injecting an object should be the initial setup that gets done once and after that the class should be ready to use.
If something keeps changing then Dagger is not the best fit to provide it. Your name would possibly be better put in some NameSettings class
class NameSettings {
private SharedPreferences prefs;
#Inject NameSettings(SharedPreferences prefs) {
this.prefs = prefs;
}
String getName() { return /* load from prefs */ }
void setName(String name) { /* save to prefs */ }
}
Instead of direcyly injecting a name you could now inject NameSettings and call get / set to update your name. This way you can always read and write the latest value without the need to deal with SharedPreferences directly.
Now your NameSettings would not change and there would be no need to re-inject it either.
You could even go ahead and return an Observable (e.g. RxJava, or some custom implementation of an observable pattern) where you can then listen for changes and update your UI dynamically whenever it changes.
I would #Provide the SharedPreferences object itself. This minimizes the dependency graph and makes you read/write any preference.
I am working on an application developed using Servlet and spring.
Below is the code followed by the description.
package com.mymodule.listener;
import net.sf.ehcache.*;
//imports
public class MyInitializationListener implements ServletContextListener {
/** Singleton instance of CacheManager. */
private static CacheManager singletonManager = null;
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("--ServletContextListener destroyed*--");
}
private static CacheManager getInstance() {
if (singletonManager == null) {
singletonManager = CacheManager.create();
}
return singletonManager;
}
private Cache getCache() {
Cache cache = null;
cache = MyInitializationListener.getInstance().getCache("myCache");
return cache;
}
// Run this before web application is started
public void contextInitialized(ServletContextEvent arg0) {
final Cache cache = getCache();
//logic here
}
Above is my Listener class which gets loaded as soon as the server is started. I have created the ehcache object in the above class. My requirement is as below:
Connect to the database and get the value.
Store the value in cache , so that any further request to that value is retrieved from a cache instead of a database hit.
But the issue is when the above Listener is initialized during server startup, my other XML files where I have configured the data sources are not yet started.So I cannot write any database logic in my Listener class. To solve this issue I have to write the database logic in other class and that class is present in other packages.
package com.mymodule.dao.hibernate;
public class MyDAOImpl extends HibernateDaoSupport implements MyDAO {
public String getDataValue() throws DataLayerException {
//String SQL = "...";
//logic to connect to the database and get the value.
//here I want to get that ehcache object which was created after the server is started in MyInitializerListener class.
}
Please suggest which would be the best possible way and how to get the ehcache object in other classes of the application present in different packages. The value returned from the database table is being used in many parts of the application , and that's the reason I want to store that value in ehcache and call from the cache whenever required.
Create a getter method like this:
public MyObject getMyObject()
{
return myObjectInstance;
}
Then you will be able to get the object from any class that creates an instance of the listener. If you need to get it into a class that doesn't create an instance of the listener, you can still use this, as long as the requesting class has a reference to a class that can reference a class (...) that has access to an instance of the listener.
For example, if You had a class that needs the object and has an instance of the class that instantiated the listener, you could just create a getter method inside both the listener and the class that created it:
In the listener:
public MyObject getMyObject()
{
return myObject;
}
In the class that created the listener:
public MyObject getMyObjectFromListener()
{
return listenerInstance.getMyObject();
}
It's dirty, but it should work.
Since you are using Spring, the correct way is to make the CacheManager or the Cache proper Spring beans.
Once that is achieved you will be able to inject them in the places that require them, whether it is a ServletContextListener or you DAO implementation.
so I've been working on a project that receives data from server, for example sessionKey. I created getter and setter method like this :
public class sEngine
{
private static String sessionKey;
public static String getSessionKey() {
return sessionKey;
}
public static void setSessionKey(
String sessionKey) {
sEngine.sessionKey = sessionKey;
}
}
Then I have activity A. In this activity A, I insert a value into the setter method.
public class A extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
sEngine.setSessionKey("Hello world")
}
}
I also have activity B. In this activity B, I call the getter method
public class B extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
String sessionKey = sEngine.getSessionKey();
}
}
It occurs to me, that Android sometimes wipes all the data in order to free some memory, for example when I let the program idle for too long, or I used Advanced Task Killer. The problem is if those happen, I will get null in activity B when I call the getter method although I've set the value in activity A. Is there any way for me to maintain the value stored via the setter method (other than using SharedPreference) so the value will still be there although Android wipes the memories/data?
Is there any way for me to maintain the value stored via the setter
method (other than using SharedPreference) so the value will still be
there although Android wipes the memories/data?
Not sure why you wouldn't want to use SharedPreferences, despite it being the perfect candidate in your requirement. When somethings as simple as this can store it:
SharedPreferences sharedPrefs = getApplicationContext().getSharedPreferences(SOME_KEY, Context.MODE_PRIVATE);
Editor editor = sharedPrefs.edit();
editor.putString("session_key", sessionKey );
This will ensure your sessionkey always remains stored for easy retrieval. Unless the user clears your app data that is.
Your only alternatives as opposed to SharedPreferences are saving the sessionkey to a Database which in my opinion, considering the task it will perform, is absolutely unnecessary.
You could also consider writing the sessionkey to a text file and then read it to retrive the data.
Both the alternatives to SharedPreferences are truly unfit for the purpose you need it for. And I would really urge you to re-consider using SharedPreferences .
Try this, Declare you non activity class in A Activity. and then set your session value.
sEngine mengine = new sEngine();
mengine.setSessionKey("Hello world");
And also get session value in B activity.
sEngine mengine = new sEngine();
String str = mengine.getSessionKey();
change
sEngine.sessionKey = sessionKey;
in your code to
this.sessionKey = sessionKey;
or simply
sessionKey = sessionKey;
using sEngine. makes one believe that your class is static.Which it isnt!
or if you want to use this sEngine. everywhere in your code you need to declare this class as static.In that case you just need to make the class declaration to static:
public static class sEngine {
I tried from this example
https://stackoverflow.com/a/9472019/485978
I have a service, this service just connects to the database directly and I put all data in a bean which is located inside this class.
public class ServiceApplication extends Application {
private static ServiceApplication mInstance;
public ServiceApplication() {
super();
}
public static ServiceApplication getInstance() {
return mInstance;
}
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
private Person personalData;
public Person getPersonalData() {
return personalData;
}
public void setPersonalData(Person personalData) {
this.personalData = personalData;
}
}
When retrieving a data from the database I used an AsyncTask where in doBackground() this is the code
ServiceApplication.getInstance().setPersonalData(personalData);
Log.d("AndroidService", "First name: "+ ServiceApplication.getInstance().getPersonalData().getFirstName());
So far it can retrieved the First Name.
However when I try to access those data from another activity all I get is null.
I tried two ways but it produces null
First implementation:
ServiceApplication app = (ServiceApplication) getApplication();
String name = (app.getPersonalData() != null) ? app.getPersonalData().getFirstName().trim() : "user";
Second implementation:
String name = (ServiceApplication.getInstance().getPersonalData() != null) ? ServiceApplication.getInstance().getPersonalData().getFirstName().trim() : "user";
Do you guys no how to persist the data and how to retrieve it from other activities?
If you are trying to pass data between a service and an activity you have to use another approach, as described here. If you just want to load Person data from a database into a singleton then you don't need to a Service. Just open a connection to the db, read the data and store it. Something like:
...
public Person getPersonalData() {
if(personalData == null) {
... open the db and load the data here ...
}
return personalData;
}
...
Note that only mInstance is static. It does not guarantee that you will receive the same personalData object. personalData could be and is definitely null in your case.
You might want to declare personalData as static as well.
private static Person personalData;
But in this case, you will reset the data on your next call to setPersonalData.
I would recommend you create a static structure as
private static ArrayList<Person> pList = new ArrayList<Person>();
Then in your setPersonalData() you can add objects to your pList.
You can replace your getPersonalData to return the pList. Hence you can use the same singleton instance from you activity to add data to the list and use the same to retrieve
I'm logging all the changes made to my objects in the DB.
#PostPersist
public void logPostPersist(Object object) {
PAudit p = new PAudit();
p.setChangeType("INSERT");
p.setObjectState(object.toString());
p.setUserName(SecurityContextHolder.getContext().getAuthentication().getName());
try {
p.persist();
} catch (Exception e) {
e.printStackTrace();
}
}
#PostUpdate
public void logUpdate(Object object) {
PAudit p = new PAudit();
p.setChangeType("UPDATE");
p.setObjectState(object.toString());
p.setUserName(SecurityContextHolder.getContext().getAuthentication().getName());
p.persist();
}
this will give me the current state of the object after it has changed.
I also want to add the previous state of the object (before it has changed) along with the current state.
How can I get the both states of the object (before change and after change) at the same time?
Thank you.
You can do this by creating an interface which your domain classes providing previous state should implement:
public interface PreviousStateProvider {
public T getPreviousState();
public void setPreviousState(T state);
}
The domain class should have a private property to hold the state at the point at which it was loaded.
Then you can create a Hibernate PostLoad listener which sets the loaded state on the domain object at the point that it's loaded. Then when you come to update the domain object you can access the previous (loaded) state using the:
getPreviousState()
method.
Hope this is clear.