Präferenzpersistenz unter Android [] (Präferenzpersistenz unter Android), Notizen, Seite 723555
https://www.purl.org/stefan_ram/pub/praeferenzpersistenz_android (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
Android-Entwicklung

Präferenzpersistenz unter Android 

Beim Verlassen unseres Programmes mit einer Zurück-Aktion geht der Zählerstand des bisher in diesem Kurs entwickelten Zählerprogramms unter Umständen verloren. Dies liegt daran, daß unsere Aktivität beim Verlassen des Programms aufgelöst wird, wodurch auch der Zustand des Textfelds verloren geht. Die Aktivität kann dann zwar anschließend wiederhergestellt werden, dabei wird der alte Zählerstand jedoch nicht  automatisch wieder eingesetzt.

In einer früheren Lektion haben wir in einer ähnlichen Situation zu sichernde Daten in ein Bündel  geschrieben, aber ein Bündel wird bei der Beendigung einer Aktivität nicht dauerhaft  gespeichert. Deswegen speichern wir unsere Daten nun in einer Präferenz.

Speicherung des Zählers in einer Präferenz

Wir wollen den Zählerstand beim Beenden der Aktivität mit der Zurücktaste in einer Präferenz speichern. Dies erledigen wir in »onPause()«.

In »onResume()« haben wir dann gegebenenfalls Gelegenheit, alle Informationen, welche aus der vorherigen Inkarnation der Aktivität wiederverwendet werden sollen, wieder aus der Präferenz zu lesen, in die wir sie zuvor geschrieben hatten.

Um zu verhindern, daß wir in »onResume()« einen aus einem Bündel wiederhergestellten Wert mit einem veralteten, zuvor gespeicherten Wert überschreiben, setzen wir den Zähler nur dann  auf den zuvor gespeicherten Stand, wenn er nicht schon aus einem Bündel wiederhergestellt wurde. Um diese Information zu erhalten, verwenden wir die eigens dafür eingeführte Variable »set« der Klasse »CounterView«.

Man kann in dem folgenden Programm nach »/* persist */« suchen, um Stellen zu finden, die mit der Präferenzpersistenz zu tun haben, oder nach »/* rotate */«, um Stellen zu finden, die mit der Bündelpersistenz zu tun haben.

MainActivity.java

package com.example;

/** Verschiedene statische Hilfsmethoden für Android-Programmierung. */
final class Android
{

/** Laufender Zähler für Ausgaben einer Aufzeichnung. */
static long logcount = 0;

/** Ausgabe einer Information in das Logbuch.
@param object eine java.lang.Object-Referenz, die wie durch einen Aufruf
der Methode {@link java.lang.String#valueOf(java.lang.Object)} ein
{@link java.lang.String}-Objekt erzeugt, welches dann mit dem Etikett
"com.example" und der Einstufung als Information in das Logbuch
geschrieben wird. */

final static void println( final java.lang.Object object )
{ try{ java.lang.Thread.sleep( 50 ); } /* otherwise slow logcat might miss some logs */
catch( final java.lang.InterruptedException exception ){ } /* modified */
android.util.Log.i
( "com.example", "[" + logcount++ + "] " + java.lang.String.valueOf( object )); }

/** Erzeugen eines Parameterbündels zu einer Sichtfläche.
Diese Methode liefert ein Parameterbündel zu der als Argument {@code view}
angegebenen Sichtfläche. Falls die Sichtfläche bereits ein
Parameterbündel enthält, so wird dieses zurückgeliefert; ansonsten
wird ein neues Parameterbündel erzeugt und zurückgeliefert,
dessen Breite, Höhe und Gewicht auf Null gesetzt wurden.
@param view eine {@link android.view.View}-Referenz, die nicht gleich null
sein darf
@return ein Parameterobjekt zu der als Argumentwert angegebenen Sichtfläche */

final static android.widget.LinearLayout.LayoutParams getParams
( final android.view.View view )
{ final android.view.ViewGroup.LayoutParams old = view.getLayoutParams();
final android.widget.LinearLayout.LayoutParams params = old != null ?
( android.widget.LinearLayout.LayoutParams )old:
new android.widget.LinearLayout.LayoutParams( 0, 0, 0f );
return params; }

/** Festlegen der Breite einer Sichtfläche.
Diese Methode stellt den Wert für die Breite in den Anordnungsparameter
der Sichtfläche {@code view} auf den Wert {@code width}.
@param view eine {@link android.view.View}-Referenz, die nicht gleich null
sein darf
@param width ein {@code int}-Wert, der für die Breite in den Anordnungsparametern
der angegebenen Sichtfläche zulässig sein muß */

final static void setWidth( final android.view.View view, final int width )
{ final android.widget.LinearLayout.LayoutParams params = getParams( view );
params.width = width; view.setLayoutParams( params ); }

/** Festlegen der Höhe einer Sichtfläche.
Diese Methode stellt den Wert für die Höhe in den Anordnungsparameter
der Sichtfläche {@code view} auf den Wert {@code height}.
@param view eine {@link android.view.View}-Referenz, die nicht gleich null
sein darf
@param height ein {@code int}-Wert, der für die Höhe in den Anordnungsparametern
der angegebenen Sichtfläche zulässig sein muß */

final static void setHeight( final android.view.View view, final int height )
{ final android.widget.LinearLayout.LayoutParams params = getParams( view );
params.height = height; view.setLayoutParams( params ); }

/** Legt das Gewicht einer Sichtfläche fest.
Diese Methode stellt den Wert für die Höhe in den Anordnungsparameter
der Sichtfläche {@code view} auf den Wert {@code height}.
@param view eine {@link android.view.View}-Referenz, die nicht gleich null
sein darf
@param height ein {@code int}-Wert, der für die Höhe in den Anordnungsparametern
der angegebenen Sichtfläche zulässig sein muß */

final static void setWeight( final android.view.View view, final float weight )
{ final android.widget.LinearLayout.LayoutParams params = getParams( view );
params.weight = weight; view.setLayoutParams( params ); }}


/** Verschiedene statische Hilfsmethoden, die speziell für diese
App gedacht sind. */

final class Application
{

/** Legt die Hintergrundfarbe für eine Sichtfläche fest.
Diese Methode stellt den Wert für die Hintergrundfarbe in der
übergebenen Sichtfläche {@code view} auf die Hintergrundfarbe
dieser Anwendung ein.
@param view eine {@link android.view.View}-Referenz, die nicht gleich null
sein darf */

final static void applyBackgroundColorTo( final android.view.View view )
{ final int yellow = 0xFFFFFF00; view.setBackgroundColor( yellow ); }

/** Legt die Textfarbe für eine Sichtfläche fest.
Diese Methode stellt den Wert für die Textfarbe in der
übergebenen Sichtfläche {@code view} auf die Textfarbe
dieser Anwendung ein.
@param view eine {@link android.view.View}-Referenz, die nicht gleich null
sein darf */

final static void applyTextColorTo( final android.widget.TextView view )
{ final int black = 0xFF000000; view.setTextColor( black ); }

/** Stellt die Ränder der übergebenen Sichtfläche ein.
Diese Methode fügt einen kleinen Rand oben und rechts (wenn nicht {@code notRight})
zu einer Tastfläche hinzu und sorgt dadurch dafür, daß der Rand dieser Tastfläche
sichtbar ist.
@param button eine {@link android.widget.Button}-Referenz, die nicht gleich null
sein darf
@param notRight Wenn diese {@link boolean}-Flagge gesetzt ist, so wird kein rechter
Rand hinzugefügt. */

final static void setMargins
( final android.widget.Button button, final boolean notRight )
{ final android.widget.LinearLayout.LayoutParams params = Android.getParams( button );
params.setMargins( 0, 1, notRight ? 0 : 1, 0 ); /* left, top, right, bottom */
button.setLayoutParams( params ); }

/** Die Schriftart für Sichtflächen dieser Anwendung. */
private final static android.graphics.Typeface typeface =
android.graphics.Typeface.create( "serif-monospace", android.graphics.Typeface.BOLD );

/** Legt die Schriftart für eine Sichtfläche fest.
Diese Methode stellt den Wert für die Schriftart in der
übergebenen Sichtfläche {@code view} auf die Schriftart
dieser Anwendung (gemäß dem Feld {@codetypeface}) ein.
@param view eine {@link android.view.View}-Referenz, die
nicht gleich null sein darf */

final static void applyTypefaceTo( final android.widget.TextView view )
{ view.setTypeface( Application.typeface ); }}

/** Ein Objekt der Klasse {@code TextView} repräsentiert eine
speziell für {@code CounterView} gestaltetes Textfeld zur
Umsetzung der Vorgaben für das Erscheinungsbild des Programmes. */

class TextView extends android.widget.TextView
{

/** Konstruiert ein {@code TextView}-Objekt.
@param context Der für das neue Objekt zu verwendende Kontext.
Die Bedeutung des Parameters {@code context} für dieses Objekt ist wie unter
{@link android.view.View#View(android.content.Context)} für {@code View} angegeben. */

public TextView( final android.content.Context context )
{ super( context );
Application.applyTypefaceTo( TextView.this );
setIncludeFontPadding( false ); }

/** Paßt die Textgröße an.
Diese Methode wird in anderen Methoden dieser Klasse aufgerufen, um
nach möglichen Änderungen die Textgröße auf die gewünschte Größe zu
skalieren. (Da dieses Textfeld nur für Ziffern gedacht ist, die keine
Unterlängen haben, kann die Ziffer vergrößert werden, um den sonst
für Unterlängen gedachten Raum auszunutzen.) */

private void resizeText()
{ this.setTextSize
( android.util.TypedValue.COMPLEX_UNIT_PX,
this.getMeasuredHeight() * 1.25f ); }

/** Paßt die Textgröße an.
Diese Methode wird aufgerufen, um es einem View zu erlauben,
seine Größe unter Berücksichtigung der Vorgaben festzulegen.
Wir überschreiben sie hier, um nach der Festlegung der Größe,
unsere {@code resizeText}-Methode aufzurufen. */

@java.lang.Override protected void onMeasure
( final int widthMeasureSpec, final int heightMeasureSpec )
{ super.onMeasure( widthMeasureSpec, heightMeasureSpec ); resizeText(); }

/** Reagiert auf Veränderung des Textes.
Diese Methode wird aufgerufen, wenn ein neuer Text festgelegt
wurde.
Wir überschreiben sie hier, um nach der Festlegung eines neuen
Textes unsere {@code resizeText}-Methode aufzurufen. */

@java.lang.Override protected void onTextChanged
( final CharSequence text, final int start,
final int before, final int after ){ resizeText(); }

/** Reagiert auf Veränderung der Größe.
Diese Methode wird aufgerufen, wenn eine neue Größe für das
View festgelegt wurde.
Wir überschreiben sie hier, um nach der Festlegung einer neuen
Größe unsere {@code resizeText}-Methode aufzurufen. */

@java.lang.Override protected void onSizeChanged
( final int width, final int height, final int oldWidth,
final int oldHeight ){ if( height != oldHeight )resizeText(); }

/** {@inheritDoc}
Hier wird die Farbe und Schriftposition angepaßt. */

@java.lang.Override
protected void onDraw( final android.graphics.Canvas canvas )
{ Application.applyBackgroundColorTo( this );
Application.applyTextColorTo( this );
canvas.save();
{ canvas.translate( 0.0f, this.getMeasuredHeight() * 0.28f );
if( getLayout() != null )getLayout().draw( canvas );
canvas.restore(); }}}

/** Ein Objekt der Klasse {@code CounterView} repräsentiert eine
speziell für dieses Programm gestaltete Anzeigefläche für einen
Zähler mit einem Zählerstand. */

final class CounterView extends TextView
{

/** Der aktuelle Wert dieser Zählerfläche. */
private int i = -1;

/** Dieser Wert gibt an, ob der Zähler schon auf einen zuvor
gespeicherten Wert zurückgesetzt wurde. Falls ja, soll er
während der laufenden Wiederherstellung nicht erneut auf einen
anderen zuvor gespeicherten Wert zurückgesetzt werden. */

/* Programmteile, die zur Persistenz bei Beendigung der Anwendung (o. Ä.)
gedacht sind, sind in diesem Programm mit "persist" gekennzeichnet. */

/* persist */
private boolean set = false;

/** Zurücksetzen des Zählers.
Diese Methode stellt den Wert des Zählers auf {@code 0} zurück. */

private void reset() { CounterView.this.i = -1; CounterView.this.increment(); }

/** Inkrementieren des Zählers.
Diese Methode erhöht den Wert des Zählers um {@code 1}. */

private void increment() { CounterView.this.setText( ++CounterView.this.i + "" ); }

/* Programmteile, die zur Persistenz bei Rotieren des Gerätes (o. Ä.)
gedacht sind, sind in diesem Programm mit "rotate" gekennzeichnet. */
/* rotate */

private int counterValue() { return CounterView.this.i; }

/** Setzt den Wert dieser Zählerfläche auf den als Argument
angegebenen Wert.
@param arg Der neue Wert der Zählerfläche
@return Der alte Wert der Zählerfläche */

/* rotate */
private int counterValue( final int arg )
{ int old = CounterView.this.i; CounterView.this.i = arg;
CounterView.this.setText( CounterView.this.i + "" );
return old; }

/** Legt fest, was dieses Objekt beim Ereignis {@code onSaveInstanceState}
macht. In diesem Fall wird der Zählerstand in dem übergebenen Bündel
gespeichert.
@param bundle Ein Bündel zum Speichern von Daten, die bei dem Ereignis
Ereignis {@code onSaveInstanceState} gespeichert werden sollen */
/* rotate */

public void onSaveInstanceState( final android.os.Bundle bundle )
{ Android.println( "onSaveInstanceState" );
bundle.putInt( "", CounterView.this.counterValue() );
CounterView.this.set = false;
super.onSaveInstanceState( bundle ); }

/** Legt fest, was dieses Objekt beim Ereignis {@code onRestoreInstanceState}
macht. In diesem Fall wird der Zählerstand aus dem übergebenen Bündel
gelesen.
@param bundle Ein Bündel mit Daten, die bei dem Ereignis
Ereignis {@code onSaveInstanceState} wiederhergestellt werden sollen */
/* rotate */

public void onRestoreInstanceState( final android.os.Bundle bundle )
{ super.onRestoreInstanceState( bundle );
Android.println( "onRestoreInstanceState" );
if( bundle != null )
{ Android.println( "bundle != null" );
if( bundle.containsKey( "" ))
{ Android.println( "bundle containsKey" );
if( CounterView.this.set == false /* persist */ )
{ CounterView.this.counterValue( bundle.getInt( "" ));
CounterView.this.set = true; }}}}

/** Legt fest, was dieses Objekt beim Ereignis {@code onPause} macht.
In diesem Fall wird der Zählerstand in eine Präferenz geschrieben. */
/* persist */

public void onPause()
{ super.onPause();
Android.println( "onPause" );
android.content.SharedPreferences preferences
= android.preference.PreferenceManager.getDefaultSharedPreferences
( CounterView.this.getContext() );
if( preferences != null )
{ Android.println( "onPause : preferences != null" );
android.content.SharedPreferences.Editor editor = preferences.edit();
if( editor != null )
{ Android.println( "onPause : preferences != null : editor != null" );
editor.putInt( "", CounterView.this.counterValue() );
editor.apply(); }}
CounterView.this.set = false; }

/** Legt fest, was dieses Objekt beim Ereignis {@code onResume} macht.
In diesem Fall wird der Zählerstand aus einer Präferenz gelesen, falls
er nicht schon durch eine andere Wiederherstellungsmethode gesetzt wurde. */
/* persist */

public void onResume()
{ super.onResume();
Android.println( "onResume" );
if( CounterView.this.set )
{ Android.println( "onResume : CounterView.this.set" ); }
else
{ Android.println( "onResume : !CounterView.this.set" );
android.content.SharedPreferences preferences
= android.preference.PreferenceManager.getDefaultSharedPreferences
( CounterView.this.getContext() );
if( preferences != null )
{ Android.println( "onResume : !CounterView.this.set : preferences != null" );
CounterView.this.counterValue( preferences.getInt( "", 0 ));
CounterView.this.set = true; }}}

/** Ergibt einen Klickempfänger, der diesen Zähler bei einem Klick zurücksetzt.
@return ein Klickempfänger, der diesen Zähler bei einem Klick zurücksetzt */

android.view.View.OnClickListener resetListenerWithoutConfirmation()
{ return new android.view.View.OnClickListener()
{ @java.lang.Override public void onClick( final android.view.View view )
{ CounterView.this.reset(); }}; }

/** Ergibt einen Klickempfänger, der diesen Zähler bei einem Klick zurücksetzt.
@return ein Klickempfänger, der diesen Zähler bei einem Klick zurücksetzt */
/* Wir sind hier in der Klasse CounterView (extends TextView) */

android.view.View.OnClickListener resetListener()
{ return new android.view.View.OnClickListener()
{

/** Legt fest, was dieses Objekt beim Ereignis {@code onClick} macht.
In diesem Fall wird ein Dialog aufgebaut und angezeigt, der fragt, ob
der Zähler zurückgesetzt werden soll (dies bezieht sich auf den Zähler
dieses CounterView-Objekts). Bei Bejahung wird der Zähler zurückgesetzt
und ein entsprechender Toast ausgegeben. */

@java.lang.Override public void onClick( final android.view.View view )
{

{ final android.app.AlertDialog.Builder builder
= new android.app.AlertDialog.Builder( CounterView.this.getContext() );

builder.setTitle( "counter reset" );
builder.setMessage( "do you really want to reset the counter?" );

builder.setPositiveButton
( "yes!",
new android.content.DialogInterface.OnClickListener()
{ public void onClick
( final android.content.DialogInterface dialog, int button )
{ android.widget.Toast.makeText
( CounterView.this.getContext(), "ok, counter is reset.",
android.widget.Toast.LENGTH_SHORT ).show();
CounterView.this.reset(); }} );

builder.setNegativeButton
( "no!",
new android.content.DialogInterface.OnClickListener()
{ public void onClick
( final android.content.DialogInterface dialog, int button ){} } );

{ final android.app.AlertDialog confirmDialog = builder.create();
confirmDialog.show(); }}}}; }

/** Ergibt einen Klickempfänger, der diesen Zähler bei einem Klick inkrementiert.
@return ein Klickempfänger, der diesen Zähler bei einem Klick inkrementiert */

android.view.View.OnClickListener incrementListener()
{ return new android.view.View.OnClickListener()
{ @java.lang.Override public void onClick( final android.view.View view )
{ CounterView.this.increment(); }}; }

/** Konstruiert ein {@code CounterView}-Objekt.
@param context Der für das neue Objekt zu verwendende Kontext.
Die Bedeutung des Parameters {@code context} für dieses Objekt ist wie unter
{@link android.view.View#View(android.content.Context)} für {@code View} angegeben. */

CounterView( final android.content.Context context )
{ super( context );
CounterView.this.setGravity( android.view.Gravity.RIGHT | android.view.Gravity.BOTTOM );
Android.setWidth( CounterView.this, android.view.ViewGroup.LayoutParams.MATCH_PARENT );
Android.setHeight( CounterView.this, 0 );
Android.setWeight( CounterView.this, 1f );
CounterView.this.increment(); }}

/** Ein Objekt der Klasse {@code Button} repräsentiert eine
speziell für dieses Programm gestaltete Tastfläche. */

final class Button extends android.widget.Button
{

/** Konstruiert ein {@code Button}-Objekt.
@param context Der für das neue Objekt zu verwendende Kontext.
Die Bedeutung des Parameters {@code context} für dieses Objekt ist wie unter
{@link android.view.View#View(android.content.Context)} für {@code View} angegeben.
@param label die Beschriftung dieses Objektes
@param listener der bei einem Klick auf diese Tastfläche zu benachrichtigende Klickempfänger
@param isReset gibt an, ob dies die Tastfläche zum Zurücksetzen des Zählers werden soll. */

Button
( final android.content.Context context,
final java.lang.CharSequence label,
final android.view.View.OnClickListener listener,
final boolean isReset )
{ super( context );
Application.applyBackgroundColorTo( Button.this );
Application.applyTextColorTo( Button.this );
Application.setMargins( Button.this, isReset );
Button.this.setGravity( android.view.Gravity.LEFT | android.view.Gravity.TOP );
Android.setWidth( Button.this, 0 );
Button.this.setTransformationMethod( null ); /* keine Gross-Schreibung */
Button.this.setTextSize( Button.this.getTextSize() * 2 );
Application.applyTypefaceTo( Button.this );
Android.setHeight( Button.this, android.view.ViewGroup.LayoutParams.MATCH_PARENT );
Android.setWeight( Button.this, 1f );
Button.this.setText( label );
Button.this.setOnClickListener( listener ); }}

/** Ein Objekt der Klasse {@code HorizontalLayout} repräsentiert eine
speziell für dieses Programm gestaltete horizontale Anordnung. */

final class HorizontalLayout extends android.widget.LinearLayout
{

/** Konstruiert ein {@code HorizontalLayout}-Objekt.
@param context Der für das neue Objekt zu verwendende Kontext.
Die Bedeutung des Parameters {@code context} für dieses Objekt ist wie unter
{@link android.view.View#View(android.content.Context)} für {@code View} angegeben. */

HorizontalLayout
( final android.content.Context context )
{ super( context );
Android.setWidth
( HorizontalLayout.this,
android.view.ViewGroup.LayoutParams.MATCH_PARENT );
Android.setHeight( HorizontalLayout.this, 0 );
Android.setWeight( HorizontalLayout.this, 1f ); }}

/** Ein Objekt der Klasse {@code VerticalLayout} repräsentiert eine
speziell für dieses Programm gestaltete vertikale Anordnung. */

final class VerticalLayout extends android.widget.LinearLayout
{

/** Konstruiert ein {@code VerticalLayoutLayout}-Objekt.
@param context Der für das neue Objekt zu verwendende Kontext.
Die Bedeutung des Parameters {@code context} für dieses Objekt ist wie unter
{@link android.view.View#View(android.content.Context)} für {@code View} angegeben. */

VerticalLayout
( final android.content.Context context )
{ super( context );
VerticalLayout.this.setOrientation( android.widget.LinearLayout.VERTICAL );
Android.setWidth
( VerticalLayout.this, android.view.ViewGroup.LayoutParams.MATCH_PARENT );
Android.setHeight
( VerticalLayout.this, android.view.ViewGroup.LayoutParams.MATCH_PARENT );
Android.setWeight( VerticalLayout.this, 0f ); }}

/** Eine Aktivität, die einen bedienbaren Zähler implementiert. */
public final class MainActivity extends android.app.Activity
{

/** Diese Methode erstellt den Objektgraphen der Aktivität.
@param bundel ein Bündel, dessen Bedeutung durch Android festgelegt ist */

@java.lang.Override public void onCreate
( final android.os.Bundle bundle )
{ super.onCreate( bundle );
Android.println( "running" );
final android.app.Activity activity = this;
final android.content.Context context = this;
activity.requestWindowFeature( android.view.Window.FEATURE_NO_TITLE );
/* rotate */ /* CounterView <-- bug */ counterView = new CounterView( context );
final Button incrementButton
= new Button( context, "increment", counterView.incrementListener(), false );
final Button resetButton
= new Button( context, "reset", counterView.resetListener(), true );
final HorizontalLayout horizontalLayout = new HorizontalLayout( context );
final android.widget.LinearLayout verticalLayout = new VerticalLayout( context );
horizontalLayout.addView( incrementButton );
horizontalLayout.addView( resetButton );
verticalLayout.addView( counterView );
verticalLayout.addView( horizontalLayout );
activity.setContentView( verticalLayout ); }

/** Die Anzeigefläche für den Zählerstand dieses Zählerprogramms. */
/* rotate */

CounterView counterView = null;

/** Legt fest, was dieses Objekt beim Ereignis {@code onSaveInstanceState} macht.
@param bundle Ein Bündel zum Speichern von Daten, die bei dem Ereignis
Ereignis {@code onSaveInstanceState} gespeichert werden sollen */
/* rotate */

@java.lang.Override protected void onSaveInstanceState( final android.os.Bundle bundle )
{ counterView.onSaveInstanceState( bundle );
super.onSaveInstanceState( bundle ); }

/** Legt fest, was dieses Objekt beim Ereignis {@code onRestoreInstanceState} macht.
@param bundle Ein Bündel mit Daten, die bei dem Ereignis
Ereignis {@code onSaveInstanceState} wiederhergestellt werden sollen */
/* rotate */

@java.lang.Override protected void onRestoreInstanceState
( final android.os.Bundle bundle )
{ super.onRestoreInstanceState( bundle );
counterView.onRestoreInstanceState( bundle ); }

/** Legt fest, was dieses Objekt beim Ereignis {@code onPause} macht. */
/* persist */

@java.lang.Override
public void onPause()
{ super.onPause();
Android.println( "onPause (MainActivity)" );
/* Don't do this, or you'll miss saves: if( this.isFinishing() ) */
counterView.onPause(); }

/** Legt fest, was dieses Objekt beim Ereignis {@code onResume} macht. */
/* persist */

@java.lang.Override
public void onResume()
{ super.onResume();
counterView.onResume(); }}

Wir zeigen hier nun noch verschiedene Protokollen, denen sich entnehmen läßt, wann bei unseren Tests welche Ereignismethoden aufgerufen wurden.

Protokoll nach dem Start des Programmbaus
50_run.cmd
env.cmd
EXIT /B 0
Deleted file - project\bin\classes.dex
Deleted file - project\bin\ComExampleMain.apk
Deleted file - project\bin\ComExampleMain.unsigned.apk
Deleted file - project\obj\com\example\Android.class
Deleted file - project\obj\com\example\Application.class
Deleted file - project\obj\com\example\Button.class
Deleted file - project\obj\com\example\CounterView$1.class
Deleted file - project\obj\com\example\CounterView$2$1.class
Deleted file - project\obj\com\example\CounterView$2$2.class
Deleted file - project\obj\com\example\CounterView$2.class
Deleted file - project\obj\com\example\CounterView$3.class
Deleted file - project\obj\com\example\CounterView.class
Deleted file - project\obj\com\example\HorizontalLayout.class
Deleted file - project\obj\com\example\MainActivity.class
Deleted file - project\obj\com\example\TextView.class
Deleted file - project\obj\com\example\VerticalLayout.class
Deleted file - project\src\main\AndroidManifest.xml
Deleted file - project\src\main\java\com\example\MainActivity.java
The system cannot find the file specified.
List of devices attached
emulator-5554 device

javac
dex
aapt
jarsigner
install
1052 KB/s (7541 bytes in 0.007s)
Protokoll nach dem Start des Programmes
--------- beginning of main
D/AndroidRuntime( 1940): >>>>>> START com.android.internal.os.RuntimeInit uid 0 <<<<<<
D/AndroidRuntime( 1940): CheckJNI is ON
--------- beginning of system
I/AndroidRuntime( 1940): VM exiting with result code 0.
start
D/AndroidRuntime( 1989): >>>>>> START com.android.internal.os.RuntimeInit uid 0 <<<<<<
D/AndroidRuntime( 1989): CheckJNI is ON
D/AndroidRuntime( 1989): Shutting down VM
I/com.example( 2000): [0] running
I/com.example( 2000): [1] onResume
I/com.example( 2000): [2] onResume : !CounterView.this.set
I/com.example( 2000): [3] onResume : !CounterView.this.set : preferences != null
Protokoll nach dem Drehen des Emulators
I/com.example( 2000): [4] onPause (MainActivity)
I/com.example( 2000): [5] onPause
I/com.example( 2000): [6] onPause : preferences != null
I/com.example( 2000): [7] onPause : preferences != null : editor != null
I/com.example( 2000): [8] onSaveInstanceState
I/com.example( 2000): [9] running
I/com.example( 2000): [10] onRestoreInstanceState
I/com.example( 2000): [11] bundle != null
I/com.example( 2000): [12] bundle containsKey
I/com.example( 2000): [13] onResume
I/com.example( 2000): [14] onResume : CounterView.this.set
Protokoll nach dem Zurückdrehen des Emulators
I/com.example( 2000): [15] onPause (MainActivity)
I/com.example( 2000): [16] onPause
I/com.example( 2000): [17] onPause : preferences != null
I/com.example( 2000): [18] onPause : preferences != null : editor != null
I/com.example( 2000): [19] onSaveInstanceState
I/com.example( 2000): [20] running
I/com.example( 2000): [21] onRestoreInstanceState
I/com.example( 2000): [22] bundle != null
I/com.example( 2000): [23] bundle containsKey
I/com.example( 2000): [24] onResume
I/com.example( 2000): [25] onResume : CounterView.this.set
Protokoll nach Verwendung der Zurück-Taste
I/com.example( 2000): [26] onPause (MainActivity)
I/com.example( 2000): [27] onPause
I/com.example( 2000): [28] onPause : preferences != null
I/com.example( 2000): [29] onPause : preferences != null : editor != null

(Der Ausgabezeilenzähler begann in dem folgenden Protokoll nur dann wieder bei »[0]«, wenn die Anwendung zwischendurch aus der Liste der kürzlich verwendeten Anwendungen entfernt wurde oder etwas Äquivalentes gemacht wurde.)

Protokoll nach erneutem Start
I/com.example( 2267): [0] running
I/com.example( 2267): [1] onResume
I/com.example( 2267): [2] onResume : !CounterView.this.set
I/com.example( 2267): [3] onResume : !CounterView.this.set : preferences != null

Unter der für die Erstellung der Protokolle verwendeten Android -Version werden »onPause« und »onResume« anscheinend auch beim Drehen des Gerätes aufgerufen, so daß unter solchen Versionen die Verwendung von »onRestoreInstanceState« und »onSaveInstanceState« in Fällen, in denen die Daten sowieso in »onPause« gespeichert und in »onResume« wiederhergestellt werden, entbehrlich sein könnte. Wir stellen in diesem Kurs beide Mechanismen vor, da mal der eine oder mal der andere (oder manchmal beide) angebrachter sein könnten.

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723555 stefan_ram:723555 Präferenzpersistenz unter Android Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723555, slrprddef723555, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/praeferenzpersistenz_android