Actually i have created an singleton class. Now my singleton class extends Activity, and i have write onCreate() and onStart() method on this class. But it is never called.The code i have used is shown below. If anyone knows help me to solve these out.
Code
public class cycleManager
{
private static CycleManager m_cycleManagerObj;
private CycleManager()
{
// Initialise Variable
onInitialization();
readData(this); // show error when call from here
}
public static synchronized CycleManager getSingletonObject()
{
if (m_cycleManagerObj == null)
{
m_cycleManagerObj = new CycleManager();
}
return m_cycleManagerObj;
}
public Object clone() throws CloneNotSupportedException
{
throw new CloneNotSupportedException();
}
public void writeData(Context c)
{
SharedPreferences preferencesWrite = c.getSharedPreferences("myPreferences", 0);
SharedPreferences.Editor editor = preferencesWrite.edit();
// work to be done
}
public void readData(Context c)
{
SharedPreferences preferencesRead = c.getSharedPreferences("myPreferences", 0);
// work to be done
}
}
The thing is Android manages activities in its own manner: from calling a constructor to calling all lifecycle methods. So if you declare your Activity's constructor as private then Android will not be able to manage this activity.
Why do you need singleton Activity-class? Consider different launch modes
check your activity in the AndroidManifest.xml.
<activity
android:configChanges="orientation|keyboardHidden"
android:name=".ActivityName">
They are not public method.They are protected method.You should override existing method.try like the following.
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
The key here is that Android is supposed to be managing your activity lifecycle, not you.
onCreate and onStart (along with onPause, onDestroy and all the other android activity lifecycle functions) are called by the looper on Android's main thread.
How did you start this activity? Was it declared in your manifest as your main activity and launcher? Did you call startActivity and pass the class name?
The fact that you are creating a singleton instance of your activity, and that its constructor is private, suggests to me that Android would be unable to start this activity when you want it to, though some function for passing an existing activity to be managed may exist, and I've just never seen it.
If onCreate and onStart are never being called, it means Android doesn't know it is supposed to be running your activity.
You get an error because your class is not a subclass of Context. Add Context attribute to getSingletonObject(Context context) method and pass it to CycleManager(Context context) constructor.
Related
I am trying to solve a problem. In my application I need to determine if onStop method was called because of starting a new activity or it was called after user had clicked on the home button or had switched to another app.
I have BaseActivity class, and I need to check it here.
I have tried to find a way to do this, but unfortunately still no solution is found.
Maybe there is a workaround for that.
The idea is to differentiate the initiator of onStop method call.
I would be grateful for any help.
A possible solution would be to register an ActivityLifecycleCallbacks and save the reference name of the last activity that called onResume:
public class ActivityChecker implements Application.ActivityLifecycleCallbacks {
private static ActivityChecker mChecker;
private String mCurrentResumedActivity = "";
public static ActivityChecker getInstance() {
return mChecker = mChecker == null ? new ActivityChecker() : mChecker;
}
// If you press the home button or navigate to another app, the onStop callback will be called without touching the mCurrentResumedActivity property.
// When a new activity is open, its onResume method will be called before the onStop from the current activity.
#Override
public void onActivityResumed(Activity activity) {
// I prefer to save the toString() instead of the activity to avoid complications with memory leaks.
mCurrentResumedActivity = activity.toString();
}
public boolean isTheLastResumedActivity(#NonNull Activity activity) {
return activity.toString().equals(mCurrentResumedActivity);
}
// [...] All other lifecycle callbacks were left empty
}
The ActivityLifecycleCallbacks can be registered in your Application class:
public class App extends Application {
public App() {
registerActivityLifecycleCallbacks(ActivityChecker.getInstance());
}
}
Don't forget to register it in your manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="your.package.name">
<application
...
android:name=".App"
> ...
</application>
</manifest>
Then, you can use it in your base Activity.
public class MyBaseActivity {
#Override protected void onStop() {
if(ActivityChecker.getInstance().isTheLastResumedActivity(this)) {
// Home button touched or other application is being open.
}
}
}
References:
Registering your custom Application class and the ActivityLifecycleCallbacks: https://developer.android.com/reference/android/app/Application.html
After writing this I found this link with some other options to retrieve the current resumed activity: How to get current foreground activity context in android?.
You can use SharedPreferences to check it:
#Override
protected void onStop() {
super.onStop();
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
pref.edit().putBoolean("IfOnStopCalled", true).apply();
}
Check in your BaseActivity:
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
Boolean IfOnStopCalled = pref.getBoolean("IfOnStopCalled",false);
if(IfOnStopCalled){
//Do your action
}
else{
//Do your action
}
There are a lot of answered questions in Stackoverflow about checking if activity is null from a fragment, using getActivity()==null
How do I check if activity is not null in the activity itself?
My specific case is this:
activity starts an asynctask, then activity is destroyed, then asynctask returns in onPostExecute, it invokes a method in the activity (which is registered as a listener for that task) and this method uses a reference to THIS to pass a context in a method. The context is null, though.
EDIT: Here is some code.
public interface OnGetStuffFromServerListener {
void onGetStuffSuccess();
}
public class SomeActivity implements OnGetStuffFromServerListener {
#Override
public whatever onCreate() {
new GetStuffFromServer(this).execute();
}
#Override
public void onGetStuffFromServerSuccess() {
deleteSomeFiles(this); // NPE -> How do I check if activity still exists here?
}
private void deleteSomeFiles(Context context) {
...
context.getExternalFilesDir(null).toString(); // NPE toString on a null object reference
}
}
public class GetSomeStuffFromServer extends AsyncTask<Void, Void, Void> {
private OnGetSomeStuffFromServerListener listener;
public GetSomeStuffFromServer (OnGetSomeStuffFromServerListener listener) {
this.listener = listener;
}
...doInBackground
onPostExecute() {
if(listener!=null) {
listener.onGetSomeStuffFromServerSuccess();
}
}
}
Actually, if I am using getApplicationContext() instead of this, maybe I will not have a problem at all?
I'm not sure why your Activity is being destroyed. Although you may be able to recreate the Activity using a Bundle. Google's documentation on Activities gives the following sample for saving and restoring an instance of your activity.
The following will save the state of your Activity:
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
The following will be called to restore your Activity's previous state. Note that the logic is contained in onCreate(), so it sounds like you will have initialize your Activity again.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
...
}
Let me know if that helps!
edit:
Try canceling the operation in onDestroy(). If the Activity has called onDestroy() its memory has been released by the device. Make sure you aren't disposing of your Activity anywhere else in your code.
#Override
protected void onDestroy() {
asynctask.cancel(true);
super.onDestroy();
}
Use myActivity.isDestroyed()
reference to doc
I would like to preserve the data or string on reload of the activity without using shared prefrences or sqllite databases.
Currently I have tried OnsavedInstancestate or OnRestoreInstancestate method but it will work only if orientation changes not for reloading the activity...
Please suggest me to overcome this.
Regards
priya
You can use singleTon class mechanism here.
Try to create a singleton class in your app.
Get instance of the class in your activity.
set the data to the class in onCreate()
get the data from the class whenever you want say in onRestart().
To learn more about singleTon class see this..
Create singleton class
public class Singleton {
private static Singleton singleton = new Singleton();
/*
* A private Constructor prevents any other class from instantiating.
*/
public String valueToStore;
private Singleton() {
}
/* Static 'instance' method */
public static Singleton getInstance() {
return singleton;
}
public String getValueToStore() {
return valueToStore;
}
public void setValueToStore(String valueToStore) {
this.valueToStore = valueToStore;
}
}
In your activity.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Singleton singleton = Singleton.getInstance();
singleton.setValueToStore("Hai");
}
#Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
Singleton singleton = Singleton.getInstance();
Log.d("Value", singleton.getValueToStore());
}
You could try using the application class to store the data in a global singleton that would persist the data, then you could load and store the data from the singleton when you needed it using getter and setter methods.
See this similar question for how to do it: Using the Android Application class to persist data
The easiest way to keep data when an activity is destroyed is to use
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("Test", "Test");
super.onSaveInstanceState(outState);
}
Note that this will not get called when the user press the back button only when the system destroys the activity or another activity comes above.
I have an Activity in whose onCreate() method i call a Utility function.
This utility functions requires a callback class instance as a parameter, in which it returns the info that i need. this is:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Utility.functionA(new functionACallBack() {
/**
*
*/
private static final long serialVersionUID = -7896922737679366614L;
#Override
public void onResponse(String error) {
((MyActivity) AppClass.getAppContext()).finish();
}
});
}
Once I have obtained that info, I want to close the activity. so i called finish() from inside the anonymous class that i created for the callback.
But the activity is not getting finished. I thought maybe i need to call finish() from UI thread so i did runOnUiThread(), in inside it also i tried calling finish(). But it just doesn't work.
Could someone please help me with this issue?
UPDATE:
I am storing APP context and then trying to use that but to no avail.
public class AppClass extends Application {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
AppClass.mContext = getApplicationContext();
}
public static Context getAppContext(){
return AppClass.mContext;
}
}
Simply call something like this:
#Override
public void onResponse(String error) {
((Activity) context).finish();
}
As this is a static function, you'll have to be able to access your Context in a static way. You can save that as a Class variable, but you'll have to be aware about its handling as it might lead to memory leaks.
To avoid them, you can declare a class that extends Application and save here your context, so this way you won't ever have a memory leak.
Try using this code:
((Activity) ActivityClass.this).finish();
Remember, use the Activity class, not the Application one.
I have a little problem about needing Activity/Application everywhere...
More precisely I have classes defined like this:
public class MyApp extends Application {
private static Activity currentActivity;
private static MyApp instance;
#Override
public void onCreate() {
super.onCreate();
instance = this;
}
public static void setCurrentActivity(Activity activity) {
currentActivity = activity;
}
}
And I have an Extended activity like this:
public class MyActivity extends Activity {
....
#Override
public void onResume() {
super.onResume();
MyApp.setCurrentActivity(this);
}
....
#Override
public void onDestroy() {
super.onDestroy();
MyApp.setCurrentActivity(null); // for nullifying static reference
}
}
My questions are:
Is the above code snippet fair ?
Should I use super.onDestroy(); after the MyApp.setCurrentActivity(null); to verify that activity is not reffered and destroyed succesfully?
And most important, what about static reference instance? where can I nullify it to not prevent from GC ?
Thanks.
Is the above code snippet fair ?
Nope. The biggest problem is in MyActivity.onDestroy(). This can be called at any time when the activity is no longer in use (ie: after it has finished). If you null out currentActivity in onDestroy() you will not be clearing the reference to MyActivity, you will be clearing the reference to whatever activity happens to be currently active at the moment. I you really want to have currentActivity point to the current activity, the best you can do is something like this:
#Override
public void onPause() {
super.onPause();
if (MyApp.getCurrentActivity() == this) {
MyApp.setCurrentActivity(null);
}
}
Also, be aware that there is a small window between onPause() of an activity and onResume() of the next activity so that it is possible that currentActivity will be null during this time. Watch out for that!
Should I use super.onDestroy(); after the
MyApp.setCurrentActivity(null); to verify that activity is not
reffered and destroyed succesfully?
See my comment above. You cannot null out this reference in onDestroy().
And most important, what about static reference instance? where can I
nullify it to not prevent from GC ?
You don't need to. There is only ever one instance of MyApp created and it lives for as long as your process exists. When Android doesn't need your process anymore it just kills the process, which will clean up everything automagically.