2016-05-04 5 views
0

Meine App scheint also gut zu funktionieren, solange ich aktiv telefoniere. Ich kann den Bildschirm drehen, die App schließen, wieder öffnen, was auch immer, keine Probleme.Stürzt meine App ab, weil ich meine Datenbank Singleton falsch implementiert habe?

Aber wenn ich den Home/Back-Knopf drücke und die App in den Hintergrund sende, und wenn ich dann für die Nacht ins Bett gehe, wenn ich einige Stunden später aufwache und versuche, die App wieder zu öffnen, stürzt sie sofort ab . Ich habe keine Ahnung, was diesen Fehler verursacht, aber ich nehme an, dass es mit einem NullPointerException (der Fluch meiner Existenz zu diesem Zeitpunkt) zu tun hat, weil Android beschlossen hat, etwas für den Speicher freizugeben.

Ich konsultierte dieses Diagramm:

enter image description here

Also, wenn ich die App in den Hintergrund senden, geht es zu onStop(), und dann schließlich Android kann etwas Speicher frei und den Prozess töten, ich so, wenn öffne die App erneut, sie versucht onCreate() aufzurufen, außer jetzt stürzt onCreate() ab. Das ergab für mich keinen Sinn.

Der einzige andere Grund, den ich mir vorstellen konnte, war die Tatsache, dass ich eine SQLite3 Datenbank Singleton in meiner App verwende, die irgendwie von Android aufgefressen wird und Speicher freigibt. Im onCreate() Methode aller mein Activities und Fragments Ich nenne typischerweise mDatabaseHelper = DatabaseHelper.getInstance(context); (wo die context ist in der Regel entweder this, wenn ich in einem Activity bin, oder getActivity() wenn ich in einem Fragment bin).

Das ist mein DatabaseHelper Klasse:

public class DatabaseHelper extends SQLiteOpenHelper { 
    private static volatile SQLiteDatabase mDatabase; 
    private static DatabaseHelper mInstance = null; 
    private static Context mContext; 

    //... various constant fields here ... 

    public static synchronized DatabaseHelper getInstance(Context context){ 
     if (mInstance == null){ 
      mInstance = new DatabaseHelper(context.getApplicationContext()); 
     } 
     return mInstance; 
    } 

    private DatabaseHelper(Context context){ 
     super(context, DB_NAME, null, DB_VERSION); 
     mContext = context; 
    } 

    public void open() throws SQLException { 
     mDatabase = getWritableDatabase(); 
    } 

    public void close(){ 
     mDatabase.close(); 
    } 

    //... other functions here ... 
} 

In meiner Abschuss Aktivität (MainActivity), Ich tue dies:

public class MainActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(@Nullable Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     DatabaseHelper databaseHelper = DatabaseHelper.getInstance(this); 
     databaseHelper.open(); 
     Intent intent = new Intent(this, AnotherActivity.class); 
     startActivity(intent); 
     finish(); 
    } 

} 

Dies ist die einzige Zeit, die ich je open() in der gesamten App aufrufen. Ich rufe nie close() überall an.

Erklärt dies, was meine App zum Absturz bringt? Da ich getInstance() in meinem onCreate Methoden aufrufen (die aufgerufen werden, wenn ich die App nach einer langen Leerlaufperiode wieder aufnehmen), führt dies zu dem Verdacht, dass in dieser Funktion etwas schief geht. Kann Android jemals Speicher freigeben, indem er den Anwendungskontext irgendwie zerstört? Ist es möglich, dass mDatabase irgendwie auf null gesetzt wird? Was muss ich noch tun, um sicherzustellen, dass ich diese Datenbank richtig implementiert habe?

+2

Sie sollten auch Ihre Stacktrace hier –

+0

habe ich nicht über einen Stacktrace weil dieser Absturz tritt nur auf, wenn ich die App auf meinem Handy installiert haben und ließ es allein für mehrere Stunden.Ich kann den Fehler nicht in meinem Emulator/Android Studio replizieren (der einzige Ort, an dem ich die Stacktrace-/Fehlerprotokolle sehen kann, wenn die Fehler tatsächlich auftreten). –

+1

Sie können den Absturzbericht von Ihrem Telefon senden, wenn es stürzt, denke ich. Versuch das? Laden Sie es im Alpha-Testmodus in den Laden, warten Sie, bis es abstürzt, und senden Sie den Bericht. – Vucko

Antwort

0

Dies geschieht im Allgemeinen mit Singleton-Mustern in Android. Sie können ein wenig darüber lesen hier

Static singleton lifetime in Android

Das bin ich in der Vergangenheit gebissen hat. Ich würde möglicherweise öffnen Sie auf die If-Anweisung in Ihrer GetInstance-Methode, um direkt nach dem Erstellen der Datenbank ausgeführt werden. Wenn Android den Speicher aufräumt, weil die App über einen längeren Zeitraum inaktiv ist, wird die Datenbank beim nächsten Mal erneut geöffnet. dh:

public static synchronized DatabaseHelper getInstance(Context context){ 
    if (mInstance == null){ 
     mInstance = new DatabaseHelper(context.getApplicationContext()); 
     try { 
      mInstance.open(); 
     } catch (Exception exe) {} 
    } 
    return mInstance; 
}