объявление глобальных констант в Java - но избегание ошибок NullPointerException - PullRequest
0 голосов
/ 04 ноября 2011

Я следовал совету, данному здесь в нескольких постах, как объявлять глобальные константы:

public class Constants {

    public static final int i1 = 1;
    public static final int i2 = 2; 
    }

Я просто включаю этот класс в свой проект и ссылаюсь на константы, подобные этому:

in any other class...
    GlobalsVars.gi1 = Constants.i1;

(ps Я надеюсь, что это нормально, и не нужно ничего делать с классом Constants, например, инициализацией или чем-то еще.)

Но, как я выяснил здесь: присваивание int целому числу с использованием статических глобальных переменных - не очень хорошая идея. Мое приложение иногда падает при доступе к константам.

Хотя я нахожу это действительно странным, поскольку мое приложение довольно маленькое, но, возможно, это класс Constants, а не активность, в некоторых случаях он действительно удаляется из памяти, хотя я и обращаюсь к его константам во всех своих действиях. Вот почему я думаю, что его все равно не следует удалять из памяти.

Но наверняка в некоторых случаях происходит сбой моего приложения при доступе к значению Constants.i1.

Что было бы лучшим способом просто объявить некоторые константы надежным способом. (В c-Derivatives есть простые в использовании макросы) Но в Android нет ничего подобного.

-> все, что мне нужно, это «надежные» константы в Java ...

EDIT:

добавлено объявление класса GlobalVars

public class GlobalVars {
    public static Integer gi1;
    public static Integer gi2;
}

Большое спасибо

EDIT: добавлен журнал аварий

java.lang.RuntimeException: невозможно запустить действие ComponentInfo {com.xxxx.xxxx / com.xxxx.xxxx.screens.One_screen}: java.lang.NullPointerException на android.app.ActivityThread.performLaunchActivity (ActivityThread.java:1830) на android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:1851) на android.app.ActivityThread.access $ 1500 (ActivityThread.java:132) на android.app.ActivityThread $ H.handleMessage (ActivityThread.java:1038) на android.os.Handler.dispatchMessage (Handler.java:99) на android.os.Looper.loop (Looper.java:150) на android.app.ActivityThread.main (ActivityThread.java:4293) в java.lang.reflect.Method.invokeNative (родной метод) в java.lang.reflect.Method.invoke (Method.java:507) на com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:849) на com.android.internal.os.ZygoteInit.main (ZygoteInit.java:607) в dalvik.system.NativeStart.main (собственный метод) Вызывается: java.lang.NullPointerException на com.xxxx.xxxx.screens.Settings_screen.presentOnScreen (One_screen.java:172) на com.xxxx.xxxx.screens.Settings_screen.onCreate (One_screen.java:49) на android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1072) на android.app.ActivityThread.performLaunchActivity (ActivityThread.java:1794) ... еще 11

и строка 172 в One_screen:

if (GlobalVars.gi1 == Constants.i1){

Ответы [ 4 ]

3 голосов
/ 04 ноября 2011

Более общая проблема, с которой вы сталкиваетесь, заключается в том, как сохранить состояние нескольких действий и всех частей вашего приложения. Статическая переменная (например, синглтон) является распространенным способом достижения Java. Однако я обнаружил, что более элегантный способ в Android - связать ваше состояние с контекстом приложения.

Как вы знаете, каждое действие также является контекстом, который представляет собой информацию о его среде выполнения в самом широком смысле. Ваше приложение также имеет контекст, и Android гарантирует, что оно будет существовать как единое целое в вашем приложении.

Способ сделать это - создать свой собственный подкласс android.app.Application , а затем указать этот класс в теге приложения в манифесте. Теперь Android автоматически создаст экземпляр этого класса и сделает его доступным для всего вашего приложения. Вы можете получить к нему доступ из любого контекста, используя метод Context.getApplicationContext () (Activity также предоставляет метод getApplication (), который имеет точно такой же эффект):

class MyApp extends Application {

  private String myState;

  public String getState(){
    return myState;
  }
  public void setState(String s){
    myState = s;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    ...
    MyApp appState = ((MyApp)getApplicationContext());
    String state = appState.getState();
    ...
  }
}

По сути, это тот же эффект, что и при использовании статической переменной или синглтона, но довольно хорошо интегрируется в существующую платформу Android. Обратите внимание, что это не будет работать между процессами (если ваше приложение является одним из редких, в котором есть несколько процессов).

1 голос
/ 04 ноября 2011

Ваш NullPointerException происходит, потому что GlobalVars.gi1 - это null, , а не Constants.i1. Вы всегда должны полагаться на жестко запрограммированные целочисленные значения, так как они являются частью определения класса.

Если вы просто хотите сохранить небольшое количество долгоживущих целочисленных переменных. Я предлагаю изучить SharedPreferences для их хранения (вместо GlobalVars).

Вы можете узнать больше здесь .

Если вы хотите передать данные только от одного Activity к другому, посмотрите на добавление значений к дополнительным элементам Intent, используя Intent.putExtra, и получите дополнительные значения Bundle в следующем Activity, используя Intent.getExtras на Intent получено с Activity.getIntent.

1 голос
/ 04 ноября 2011

Пожалуйста, разместите журналы аварии.Прочитав ваш другой пост (тот, на который вы ссылались), я уверен, что проблема кроется в другом месте.Например, в вашем другом вопросе , который вы упоминаете в комментарии к ответу:

I got a crash report of my app in a place where it compares if (GlobalVars.gi1 == Constants.i1)

Автобокс в Java5 + поддерживает этот тип сравнения.Данный код работает универсально.

1 голос
/ 04 ноября 2011

Вам не нужно статическое в Java, чтобы сделать их постоянными. Вы можете сделать их final и public и получить к ним доступ относительно одинаково. Разница, однако, заключается в том, что вам придется создавать экземпляр класса со ссылкой каждый раз, когда вы хотите получить доступ к константам, которые потребляют память без реальной причины. Вы можете решить эту проблему, следуя шаблону Singleton , который создаст один экземпляр класса, доступ к которому можно получить с помощью статического метода getInstance().

...