MODE_PRIVATE cannot be resolved to a variable

  • Antworten:10
  • Bentwortet
Hans Maisser
  • Forum-Beiträge: 20

26.01.2012, 03:38:33 via Website

Hallo.

Ich habe folgendes Problem:

Ich möchte Funktionen in einer eigenen Class außerhalb einer onCreate() oder anderen Methode meiner "Activity-Klassen einrichten.
Diese Funktionen sollen später das Schreiben und Lesen der Prefs aus allen anderen Klassen der app übernehmen. Über Sinn oder Unsinn des Inhaltes jeder einzelnen Routine lässt sich hier streiten. Wichtig ist im Moment allerdings Funktionalität.

Dazu habe ich folgenden Code:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package app.Bluemax;

import android.content.SharedPreferences;

public class app_settings {


private static final SharedPreferences settings = getSharedPreferences("Bluemax_Settings",MODE_PRIVATE);
private static final SharedPreferences.Editor editor = settings.edit();


public static boolean set_str_Settings(String name, String Value) {

boolean valid = true;
editor.putString(name,Value);
editor.commit();
return valid;
}


public static String get_str_Settings(String name,String default_val) {

String return_str = null;
return_str = settings.getString(name, default_val);
return return_str;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Wonach ich jetzt ewig lese und keine Antwort bekomme ist: MODE_PRIVATE erzeugt in dieser Form einen "cannot be resolved to a variable" Error.
ich kann MODE_PRIVATE mit

private static final int MODE_PRIVATE;

in meiner eigenständigen "app_settings" Klasse zwar extra deklarieren. Aber in allen anderen Klassen ( die üblichen Activityclasses u.u.) wird die Konstante auch ohne diesen Schritt erkannt. Ich glaube nicht dass hier eine Neudeklaration der richtige Weg ist. Zumal sich dann die getSharedPreferences() mit dem Error "The method getSharedPreferences(String, int) is undefined for the type app_settings" meldet. Der Hase liegt hier im Pfeffer begraben und mir tränen die Augen.

Es ist sicher ein Anfängerfehler den ich hier begehe. Ich bin sehr viel am Lesen. Aber das Problem kann ich noch nicht lösen.


Vielen Dank für jede Hilfe!!!

Antworten
Mike W.
  • Forum-Beiträge: 87

26.01.2012, 06:09:48 via App

getSharedPrefererences sowie MODE_PRIVATE sind Methoden bzw. Konstanten der Klasse Context.
Du benötigst daher eine Referenz auf den Kontext der aufrufenden Klasse.
Am besten machst dus so, dass du beim Erstellen der Helfer-Klasse im Konstruktor this mitgibst (in der Helper-Klasse als Context-Variable deklariert) und dann darüber die SharedPrefs holst.

Antworten
Rafael K.
  • Forum-Beiträge: 2.359

26.01.2012, 09:32:29 via Website

Das gilt zwar jetzt nicht für diese Methoden, aber bei static Methoden und Konstanten kann man auch static Importe machen:

1import static de.mypackage.MyClass.myStaticHelperMethod;
2import static de.mypackage.MyClass.MY_STATIC_CONSTANT;

Dann kann man in seiner eigenen Klasse diese Methoden/Konstanten so nutzen, als wären sie in der aktuellen Klasse deklariert.
Nur mal der Vollständigkeit halber sei das hier erwähnt :)
Ob das im Einzelfall guter Stil ist und nicht eher verwirrt, kann jeder selbst entscheiden :)
Bei static Hilfsmethoden kann das durchaus sinnvoll sein, um die Logik zentral zu haben und den Code leserlicher zu halten.

Antworten
Hans Maisser
  • Forum-Beiträge: 20

26.01.2012, 12:46:28 via Website

Mike W.
...dass du beim Erstellen der Helfer-Klasse im Konstruktor this mitgibst (in der Helper-Klasse als Context-Variable deklariert) und dann darüber die SharedPrefs holst.

Mir ist klar, dass getSharedPrefererences sowie MODE_PRIVATE von android.content.context abstammen. Sie sind in den anderen Klassen ja auch bekannt. Nur steht da nicht mehr deklariert als in meiner Klasse?! Könntest du mir konkret was Code vorsetzen zu deiner Erläuterung, damit ich es verstehen kann?

import android.content.*; importiert mir doch alle Klassen von content oder? Also auch Context?!!

Vielen Dank!

— geändert am 26.01.2012, 12:49:14

Antworten
Gelöschter Account
  • Forum-Beiträge: 24

26.01.2012, 12:56:56 via Website

Du arbeitest static! Ich mach's immer so:

1public class MyPreferenceActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
2
3 private static final String PREF_SERVICEAKTIV = "serviceaktiv";
4
5 private static long serviceAktiv = MyService.MyBroadcastReceiver.STATUS_STOPPED;
6
7 public static long isServiceAktiv() {
8 return serviceAktiv;
9 }
10
11 static void setServiceAktiv(final Context context, final long value) {
12 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
13 SharedPreferences.Editor sharedPreferenceseditor = sharedPreferences.edit();
14 sharedPreferenceseditor.putLong(PREF_SERVICEAKTIV, value);
15 sharedPreferenceseditor.commit();
16
17 serviceAktiv = value;
18 }
19}

Gruß
Harald

— geändert am 26.01.2012, 12:59:08

Antworten
Rafael K.
  • Forum-Beiträge: 2.359

26.01.2012, 13:41:18 via Website

Hans Maisser
import android.content.*; importiert mir doch alle Klassen von content oder? Also auch Context?!!

Alles was der Import bewirkt ist, dass du die importierte Klasse innerhalb deiner Klasse nutzen kannst OHNE den vollen Package-Namen mit anzugeben.

Ohne Importe:
1android.content.Context c = new de.myapp.MyCoolActivity();

Mit Importen:
1Context c = new MyCoolActivity();

Deine Klasse erbt aber NICHT automatisch die Methoden und Felder der importierten Klassen.

Das sind aber echt Basics.
Zur Schonung der eigenen Nerven sollte man sowas wissen, bevor man mit App Programmierung anfängt :)

— geändert am 26.01.2012, 13:42:33

Antworten
Hans Maisser
  • Forum-Beiträge: 20

27.01.2012, 11:56:38 via Website

Ok. Zur Schonung meiner Nerven hab ich natürlich straight on gelesen,gelernt und umgekehrt. Es sind nur eben ne Menge Basics, die man erstmal lernen und dann im richtigen Moment beachten muss.

Ich habe die Sache jetzt so gelöst, nachdem ich aus meinen statics heraus keine Objekterzeugung hin bekam:

public class my_settings{

public static SharedPreferences mySharedPrefs;
public static Editor SPEditor;
public static boolean mode;

public static boolean set_mode(String name, String Value) {

mode = mySharedPrefs.getString(name, default_val); //Example
SPEditor.putboolean(name,Value).commit(); //Example

return true;
}

}

In meiner ersten Activityclass erzeuge ich ein SharedPreferences Object und ein Editor Object und übergebe es beim Start EINMAL an meine static-Helperclass.

SharedPreferences settings = getSharedPreferences("Bluemax_Settings", MODE_PRIVATE);
SharedPreferences.Editor SPedit = settings.edit();
mysettings.mySharedPrefs = settings;
mysettings.SPEditor = SPedit;

Der Sinn hinter dem Gedanken ist, dass eine static ja ÜBER DEN GESAMTEN ZEITRAUM DES PROGRAMMES gültig ist. Also nicht wie bei Activities, die ja durch die Livecycles terminiert sind und damit auch deren Objekte und Klassen. Somit bleiben zur Laufzeit meine zwei Objekte sicher erhalten und ich muss nicht ständig nachfragen oder neu erzeugen.

Ist der Gedanke richtig?

— geändert am 27.01.2012, 12:09:31

Antworten
Rafael K.
  • Forum-Beiträge: 2.359

27.01.2012, 12:09:56 via Website

Also mit den static Geschichten wäre ich extrem vorsichtig! Das führt, ohne Sinn angewandt, zu übelsten Seiteneffekten.
Es gab hier schon soooo viele Threads wo das zu völlig wirschen Fehlern führt, die ein Newbie dann einfach nicht mehr debuggen kann.
Android reagiert auch teilweise ziemlich zickig, wenn man Context-bezogene Objekte zwischen Activities (die ja selbst einen Context darstellen) teilt.

Genauso wie man Felder einer Klasse idR. nicht public macht. -> Siehe Kapselung von Daten.
Auch schreibt man Klassennamen in Camel-Schreibweise und 1. Buchstabe groß -> MySettings
Methodennamen ebenso und 1. Buchstabe klein -> setMode

Ganz simpel könntest du es so machen:

Eine NICHT statische Klasse nehmen, der einen Context im Konstruktor übergeben wird (die Activity).
In jeder Activity eine Instanz der Klasse erzeugen.
Die SharedPreferences sind eh zentral abgelegt und es läuft immer nur eine Activity auf einmal.
Du musst dich also garnicht darum kümmern den Zugriff auf die SharedPreferences zu zentralisieren.
Wenn du Threads verwendest kannst du das ja immernoch synchronisieren.

Möglichkeit 2:
Eine Custom Application Implementierung nehmen.
http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/

Antworten
Hans Maisser
  • Forum-Beiträge: 20

27.01.2012, 12:22:39 via Website

Rafael K.

Auch schreibt man Klassennamen in Camel-Schreibweise und 1. Buchstabe groß -> MySettings
Methodennamen ebenso und 1. Buchstabe klein -> setMode

Das weiss ich. Nur ist es meine App. Sie geht an keine anderen Entwickler und ich komme aus anderen Sprachen zu Java. Da sind die Konventionen wieder andere und ich möchte nicht jedesmal meine Gewohnheiten ändern. Auch wenn es so Regel ist in Java. Ich benenne z.B. Activities mit frm_... oder Buttons mit cmd_... . Eben weil es für mich Formen und Commands sind. Und das bleibt ( solange ich nicht professionell Javen muss ) auch so.

Mit dem Rest deines Beitrages werde ich mich genauer beschäftigen und danke dir schonmal sehr dafür.

Antworten
Rafael K.
  • Forum-Beiträge: 2.359

27.01.2012, 12:41:11 via Website

Ich würde dir dennoch raten dir zumindest die Grundzüge der Java Coding Conventions anzueignen.
Umso früher du das machst, desto weniger Code musst du später ändern, wenn dir einfällt, dass es doch sinnvoll ist :)

1. macht es anderen einfacher mit dir über deinen Code zu reden
2. Spätestens sobald du anfängst Methoden zu überschreiben hast du einen gigantischen Mischmasch aus Notationen und es wird extrem unleserlich...auch für dich.
3. kannst du bestimmte Reflection-basierte Libraries nicht nutzen, wenn deine getter und setter Methoden nicht dem getParam/setParam Schema folgen
4. Kannst du garnicht die tollen Code-Templates von Eclipse nutzen, die einem ungefähr 90% der Tipparbeit abnehmen :)

Ist deine Entscheidung.
Ist nur ein gut gemeinter Ratschlag auf den auch keine weitere Diskussion folgen sollte ;)

— geändert am 27.01.2012, 12:45:58

Antworten
Hans Maisser
  • Forum-Beiträge: 20

27.01.2012, 12:47:43 via Website

Das du dich hinsetzt Rafael und deine Zeit für meine Angelegenheiten opferst ist wirklich nett und ich danke dir SEHR dafür! Explizit sozusagen :)

— geändert am 27.01.2012, 12:48:02

Antworten