Hier ist eine alternative Lösung für alle Rückrufmethoden, die möglicherweise alle dem gleichen undefinierten Ereignisreihenfolgeverhalten mit Aktivitätszyklus unterliegen. Wenn Sie nicht den gesamten Android-Code für jeden Rückruf überprüfen, den Sie verwenden, um den Ursprungsauslöser zu bestimmen und wer die Implementierungen steuert, und hoffen, dass sich die Codebasis in Zukunft nicht ändert, kann man wirklich sagen, dass die Ereignisreihenfolge zwischen Rückrufen und Aktivitätslebenszyklusereignisse könnten garantiert werden.
Derzeit können diese Ordnungswechselwirkungen für Entwicklungszwecke normalerweise als undefiniertes Verhalten bezeichnet werden.
Am besten behandeln Sie dieses undefinierte Verhalten immer korrekt, sodass es überhaupt kein Problem darstellt, indem Sie sicherstellen, dass die Befehle ein definiertes Verhalten sind.
Mein Sony Xperia zum Beispiel schaltet meine aktuelle App im Ruhezustand durch, indem es die App zerstört und dann neu startet und in den Pausenzustand versetzt, ob Sie es glauben oder nicht.
Wie viel Testverhalten von Ereignisbestellungen Google in seinem SDK als spezielles Test-Build für Host-Umgebungsimplemente bereitstellt, weiß ich nicht, aber sie müssen sich definitiv bemühen, um sicherzustellen, dass das Verhalten von Ereignisbestellungen durch eine strenge Einhaltung der Regeln begrenzt wird Angelegenheit.
https://code.google.com/p/android/issues/detail?id=214171&sort=-opened&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened
import android.util.Log; import android.util.SparseArray;
/ ** * Erstellt von woliver am 24.06.2016. * * Die Android-Hostumgebung bestimmt einen Aktivitätslebenszyklus für OnCreate, onStart, onResume, onPause, onStop, onDestory *, in dem Speicher und Handles für andere Anwendungen freigegeben werden müssen. * Bei der Wiederaufnahme müssen wir diese Elemente manchmal neu binden und mit anderen Objekten aktivieren. * In der Regel stellen diese anderen Objekte Rückrufmethoden aus der Host-Umgebung bereit, die * ein onCreated und ein onDestroy bereitstellen, in denen wir nur von OnCreated aus an dieses Objekt binden und die Bindung onDestory verlieren können. * Diese Art von Rückrufmethoden, deren Ausführungszeit von unserer Host-Umgebung gesteuert wird * und es gibt keine Garantie dafür, dass das Verhalten / die Reihenfolge der Ausführung des Aktivitätslebenszyklus und dieser Rückrufmethoden * konsistent bleibt. * Zum Zwecke der Entwicklung können die Interaktionen und die Reihenfolge der Ausführung technisch als undefiniert bezeichnet werden *, da dies dem Implementierer der Host-Implementierung, Samsung, Sony, HTC, überlassen bleibt. * * Siehe folgendes Entwicklerdokument:https://developer.android.com/reference/android/app/Activity.html
* Zitat: * Wenn eine Aktivität durch eine andere Aktivität vollständig verdeckt wird, wird sie gestoppt. Es behält weiterhin alle Status- * und Mitgliedsinformationen bei, ist jedoch für den Benutzer nicht mehr sichtbar, sodass sein Fenster * ausgeblendet ist und häufig vom System beendet wird, wenn an anderer Stelle Speicher benötigt wird. * EndQuato: * * Wenn die Aktivität nicht ausgeblendet ist, wurden keine Rückrufe aufgerufen, von denen man erwartet hätte, dass sie vom Hostsystem * aufgerufen wurden, wie z. B. der SurfaceView-Rückruf der OnCreate- und OnDestory-Methodenschnittstelle. * Dies bedeutet, dass Sie das an SurfaceView gebundene Objekt wie eine Kamera * in einer Pause stoppen müssen und das Objekt niemals erneut binden müssen, da der OnCreate-Rückruf niemals aufgerufen wird. * * /
public abstract class WaitAllActiveExecuter<Size>
{
private SparseArray<Boolean> mReferancesState = null;
private int mAllActiveCount = 0;
private String mContextStr;
public WaitAllActiveExecuter(String contextStr, int... identifiers)
{
mReferancesState = new SparseArray<Boolean>(identifiers.length);
mContextStr = contextStr;
for (int i = 0; i < identifiers.length; i++)
mReferancesState.put(identifiers[i], false);
}
public void ActiveState(int identifier)
{
Boolean state = mReferancesState.get(identifier);
if (state == null)
{
throw new IllegalStateException(mContextStr + "ActiveState: Identifier not found '" + identifier + "'");
}
else if(state == false){
mReferancesState.put(identifier, true);
mAllActiveCount++;
if (mAllActiveCount == mReferancesState.size())
RunActive();
}
else
{
Log.e(mContextStr, "ActivateState: called to many times for identifier '" + identifier + "'");
}
}
public void DeactiveState(int identifier)
{
Boolean state = mReferancesState.get(identifier);
if (state == null)
{
throw new IllegalStateException(mContextStr + "DeActiveState: Identifier not found '" + identifier + "'");
}
else if(state == true){
if (mAllActiveCount == mReferancesState.size())
RunDeActive();
mReferancesState.put(identifier, false);
mAllActiveCount--;
}
else
{
Log.e(mContextStr,"DeActiveState: State called to many times for identifier'" + identifier + "'");
}
}
private void RunActive()
{
Log.v(mContextStr, "Executing Activate");
ExecuterActive();
}
private void RunDeActive()
{
Log.v(mContextStr, "Executing DeActivate");
ExecuterDeActive();
}
abstract public void ExecuterActive();
abstract public void ExecuterDeActive();
}
Beispiel für die Implementierung und Verwendung einer Klasse, die sich mit oder dem undefinierten Verhalten von Implementierern der Android-Host-Umgebung befasst.
private final int mBCTSV_SurfaceViewIdentifier = 1;
private final int mBCTSV_CameraIdentifier = 2;
private WaitAllActiveExecuter mBindCameraToSurfaceView =
new WaitAllActiveExecuter("BindCameraToSurfaceViewe", new int[]{mBCTSV_SurfaceViewIdentifier, mBCTSV_CameraIdentifier})
{
@Override
public void ExecuterActive() {
if (mCamera == null)
{
mCamera = Camera.open(mCameraIDUsed);
if (mCamera == null)
throw new RuntimeException("Camera could not open");
setDefaultCameraParameters(mCamera);
setPreviewSizesForCameraFromSurfaceHolder(getSurfaceHolderForCameraPreview());
}
try {
mCamera.startPreview();
mCamera.setPreviewDisplay(getSurfaceHolderForCameraPreview());
} catch (IOException e) {
e.printStackTrace();
ExecuterDeActive();
throw new RuntimeException("Camera preview could not be set");
}
}
@Override
public void ExecuterDeActive() {
if ( mCamera != null )
{
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
};
@Override
protected void onPause() {
mBindCameraToSurfaceView.DeactiveState(mBCTSV_CameraIdentifier);
Log.v(LOG_TAG, "Activity Paused - After Super");
}
@Override
public void onResume() {
mBindCameraToSurfaceView.ActiveState(mBCTSV_CameraIdentifier);
}
private class SurfaceHolderCallback implements SurfaceHolder.Callback
{
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.v(LOG_TAG, "Surface Changed");
}
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.v(LOG_TAG, "Surface Created");
mBindCameraToSurfaceView.ActiveState(mBCTSV_SurfaceViewIdentifier);
}
public void surfaceDestroyed(SurfaceHolder arg0) {
Log.v(LOG_TAG, "Surface Destoryed");
mBindCameraToSurfaceView.DeactiveState(mBCTSV_SurfaceViewIdentifier);
}
}