Wann/warum funktioniert mein Java singleton-Instanz zerstört werden?
Habe ich eine android-app, ist das setup zum starten einer Java-Aktivität (nennen wir es MyJavaActivity), die wiederum startet eine NativeActivity. Wenn die NativeActivity beendet, es kehrt zurück zu MyJavaActivity.
Ich habe auch ein Java-singleton-Klasse (nennen wir es MyJavaSingleton) ich möchte bleiben im Speicher, während meiner gesamten application lifecycle. Ich setzen einige der singleton-Klasse member-Variablen, aus meiner NativeActivity (über JNI), die können später abgerufen werden MyJavaActivity.
Das problem ist, MyJavaSingleton Instanz zu sein scheint, im Speicher, bis NativeActive beendet, aber irgendwie scheint auf null zu setzen wieder, wenn MyJavaActivity wieder startet, also alle Variablen, die ich gesetzt hatte in NativeActivity sind jetzt auf die Standardwerte zurückgesetzt. Warum geschieht dieses?
public class MyJavaActivity extends Activity implements View.OnTouchListener
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
MyJavaSingleton.Instance().DoStuff();
}
@Override
public boolean onTouch(View arg0, MotionEvent arg1)
{
Intent intent = new Intent(MyJavaActivity.this, NativeActivity.class);
startActivity(intent); //at this point, android_main will be executed
}
}
/////////////////////////////
public class MyJavaSingleton
{
static private MyJavaSingleton mInstance = null;
synchronized public static MyJavaSingleton Instance()
{
if( mInstance == null )
{
mInstance = new MyJavaSingleton();
Log.v(TAG, "New MyJavaSIngleton instance");
}
return mInstance;
}
}
/////////////////////////////
//Native
void android_main(struct android_app* state)
{
//Do various stuff, set some variables on the MyJavaSingleton
//At this point, MyJavaSingleton.mInstance is still at the same address in memory, which is good //
ANativeActivity_finish(state->activity);
exit(0);
//Problem: sometime after this exit and before MyJavaActivity::onCreate is called, MyJavaSingleton.mInstance is set to null!
}
Im obigen code-Extraktion, die "Neue MyJavaSIngleton Instanz" wird gedruckt, wenn Sie die app zum ersten mal gestartet, und dann wieder rechts, nach der NativeActivity beendet (dh nach android_main verlassen wird) und MyJavaActivity die onCreate wird aufgerufen, wieder.
Warum MyJavaSingleton.mInstance werden NULL, wenn wieder MyJavaActivity?
- warum sind Sie durch den Aufruf von exit()? Nicht, dass tötet die JVM, oder bin ich da unwissend von Android?
- Ja, ich mag es nicht zu nennen, exit (), ich denke, dies ist ein hack, aber die Anwendung scheint nicht zurück zu MyJavaActivity, es sei denn, ich mache das.
finish()
funktioniert nicht?- Wie @James singleton sagte, Sie sollten privat sein. Auch, wie geschrieben,
Instance()
solltesynchronized
. - Nein, In meinem code-Ausschnitt können Sie sehen, ich nenne das native äquivalent zu " finish()
, which is
ANativeActivity_finish. With only this (and no
exit()), the app does not return to
MyJavaActivity, it simply stops at the last screen that
NativeActivity` zeigte. @Hemal ich erwähnte dies in einem früheren Kommentar - aber ich hatte ursprünglich es zuprivate
und das Verhalten ist das gleiche. Ich habe versucht, hinzufügen von "synchronisiert", obwohl immer noch die gleichen Ergebnisse 🙁 ich werde zu aktualisieren meinem code oben zu zeigen, diese beiden änderungen. - Ich weiß nicht, wie laden von Klassen funktioniert in Android, aber es würde eine Instanz der
static
für die einzelnen classloader das laden der Klasse, denn es würde eine Instanz der Klasse per classloader. Man könnte hinzufügen, ein einstatic {System.out.println("Loading MyJavaSingleton");}
wenn dies der Fall sein könnte - Danke für den Tipp! Ich fügte hinzu, diese statischen print-Anweisung und es wird zwei mal aufgerufen, jedes mal direkt nach `MyJavaActivity::onCreate' eingetragen. Nicht sicher, ob ich verstehe, warum aber?
- Ich denke, weil die Klasse bekam entladen früher. Sie drucken konnte, der classloader in der static-block, um zu sehen, wenn Sie unterschiedlich sind.
MyJavaSingleton.class.getClassLoader()
. Ich weiß nicht genug über Android, so Frage ich mich, warumMyJavaActivity.onCreate
bekommt sogar wieder angerufen. Ist die Anwendung wieder starten?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Jede Android-app läuft in einem eigenen Prozess, so lange wie es läuft, singleton verfügbar sein wird. Wenn der Prozess stirbt, singleton verloren. Daher, wenn die app erneut gestartet, dieses singleton-Objekt müssen neu erstellt werden.
exit
werden muss, die Tötung der Prozess und dann neu gestartet wird, irgendwie bringt mich zurück zuMyJavaActivity
. Leider mitexit
scheint die einzige Möglichkeit zu sein, um wieder zurück auf die Java-Aktivität, dass heißt es 🙁Achten Sie darauf, Lesen Sie in der Dokumentation der Prozess-lifecycle:
http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html#Lifecycle
In diesem Fall, wenn Sie Ihre app im hintergrund ist (in Bezug auf Aktivitäten keine Aktivitäten sind für den Benutzer sichtbar), Ihr Prozess getötet werden kann jederzeit. Wenn der Benutzer später zurück, um eine Ihrer Tätigkeiten, wird ein neuer Prozess erstellt wird und eine neue Instanz der activity erstellt.
NativeActivity
,MyJavaActivity
, undMyJavaSingleton
alle sind Teil des gleichen Prozesses. EntwederMyJavaActivity
undNativeActivity
sind immer sichtbar an einem gewissen Punkt (außer beim übergang zwischen Ihnen), also, ich weiß nicht, warum meine app Prozess jemals getötet oder warum meine original singleton-Instanz ist verloren und eine neue singleton-Instanz erzeugt wird.Ich würde mInstance private. Nur für den Fall einige andere code ist versehentlich eingestellt haben.
null
irgendwo sonst in der gleichen Klasse. Reflexion kann verwendet werden, um es wieder auf null. Aber in diesem Fall würde es auf null gesetzt werden, auch wenn espublic
.finalize
Methode inMyJavaSingleton
mit einigen print-Anweisungen und einen Haltepunkt, dieser wird nie getroffen entweder! :S"Android OS kann und beendet Ihre singleton und auch nicht Ihnen davon erzählen."
Quelle: http://www.2linessoftware.com/2010/08/03/singletons-and-services-and-shutdowns-oh-my/
Den Autor der Artikel schlägt einige Lösungen, wie die Verwendung eines Service-oder Unterklassen der Application-Klasse. Es scheint ganz ein wenig Unterstützung für die letztere:
Wie deklarieren Sie Globale Variablen in Android?