2013-10-09 3 views
0

Если я ошибаюсь, вызов getSharedPreferences ("someName", 0) должен только создать новый файл, если он не существует в памяти телефона, не так ли?NullPointerException при создании нового файла SharedPreferences

К сожалению, для меня это просто дает мне NPE. Код и LogCat приведены ниже.

NewCity класс:

public class NewCity extends Activity implements OnClickListener, OnCheckedChangeListener { 
    public static City city; 
    private Generator gen; 
    RadioGroup popGroup; 
    RadioButton random, specific; 
    Spinner cityType, supplies; 
    EditText cityName, customPop; 
    CheckBox fishing, mining, forestry; 
    Button next; 
    TextView errorList; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.newcity); 
     initializeRefs(); 
    } 

    private void initializeRefs() { 
     popGroup = (RadioGroup) findViewById(R.id.popGroup); 
     random = (RadioButton) findViewById(R.id.radioRandomCity); 
     specific = (RadioButton) findViewById(R.id.radioSpecificCity); 
     cityType = (Spinner) findViewById(R.id.spinCityType); 
     supplies = (Spinner) findViewById(R.id.spinSupplies); 
     cityName = (EditText) findViewById(R.id.textCityName); 
     customPop = (EditText) findViewById(R.id.textCustomPop); 
     fishing = (CheckBox) findViewById(R.id.checkFishing); 
     mining = (CheckBox) findViewById(R.id.checkMining); 
     forestry = (CheckBox) findViewById(R.id.checkForestry); 
     next = (Button) findViewById(R.id.bNewNext); 
     errorList = (TextView) findViewById(R.id.errorList); 

     popGroup.setOnCheckedChangeListener(this); 
     next.setOnClickListener(this);  
     customPop.setEnabled(false); 
    } 

    @Override 
    public void onClick(View view) { 
     boolean canGenerate = true; 
     ArrayList<String> errors = new ArrayList<String>(); 

     switch(view.getId()) { 
     case R.id.bNewNext: 
      if(cityName.getText().toString().matches("")) { 
       errors.add("! Settlement must have a name.\n"); 
       canGenerate = false; 
      } 

      if(specific.isChecked() && customPop.getText().toString().matches("")) { 
       errors.add("! Enter a population figure.\n"); 
       canGenerate = false; 
      }   
      break; 
     } 

     if(canGenerate) { 
      gen = new Generator(getBaseContext()); 
      errors.clear(); 
      sendCityData(cityName.getText().toString()); 
        gen.createCity(); 
     } else { 
      StringBuilder builder = new StringBuilder(); 
      for(String value : errors) { 
       builder.append(value); 
      }   
      errorList.setText(builder.toString()); 
      errors.clear(); 
     } 
    } 
    .... Unrelated code .... 
} 

Генератор Класс:

public class Generator { 
    private Context context; 
    private City city; 
    private SharedPreferences storage; 

    public Generator(Context context) { 
     this.context = context; 
     city = NewCity.city; 
     storage = context.getSharedPreferences(city.getName(), Context.MODE_PRIVATE); 
    } 

    public float random(float low, float high) { 
     Random random = new Random(); 
     return ((low + (high - low)) * random.nextFloat()); 
    } 

    public void createCity() { 
     Editor edit = storage.edit(); 
     edit.putString("NAME", city.getName()).apply(); 
    } 
} 

LogCat:

10-08 20:22:28.598: E/AndroidRuntime(21336): FATAL EXCEPTION: main 
10-08 20:22:28.598: E/AndroidRuntime(21336): java.lang.NullPointerException 
10-08 20:22:28.598: E/AndroidRuntime(21336): at com.flawedspirit.android.citygen.Generator.<init>(Generator.java:17) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at com.flawedspirit.android.citygen.NewCity.onClick(NewCity.java:77) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at android.view.View.performClick(View.java:4203) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at android.view.View$PerformClick.run(View.java:17189) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at android.os.Handler.handleCallback(Handler.java:615) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at android.os.Handler.dispatchMessage(Handler.java:92) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at android.os.Looper.loop(Looper.java:137) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at android.app.ActivityThread.main(ActivityThread.java:4961) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at java.lang.reflect.Method.invokeNative(Native Method) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at java.lang.reflect.Method.invoke(Method.java:511) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771) 
10-08 20:22:28.598: E/AndroidRuntime(21336): at dalvik.system.NativeStart.main(Native Method) 

Оператор обижая на линии 17 класса Generate. Я не понимаю, почему это не сработает. Это передается Контекст и String ("city.getName()"), который инициализируется перед передачей, поэтому я знаю, что THAT не является нулевым. Является ли конструктор класса Generator помещенным в неправильное место? Я знаю, что это должно произойти после инструкции super.onCreate().

EDIT: Конструктор моего городского класса; действительно ли это работает?

public class City { 
    private static final int PEOPLE_PER_SQACRE = 61; 
    private static final int PEOPLE_PER_SQMILE = 38850; 

    private String name; 
    private String type; 
    private int population; 
    private float sizeMi; 
    private float sizeAc; 
    private int gpLimit; 
    private long wealth; 
    private float lowPop; 
    private float highPop; 
    private boolean fishing; 
    private boolean mining; 
    private boolean forestry; 

    public City(String name) { 
     this.name = name; 
    } 
    .... Unrelated code .... 
} 
+0

Мое предположение в строке 17, город имеет значение null, поскольку NewCity.city имеет значение null. – nedaRM

+0

Я убедился, что это имеет значение, поэтому оно не было нулевым. Чтобы убедиться, я изменил его на статическую строку, и это дало мне ту же ошибку. – Flawedspirit

+0

Я все еще не уверен, но как насчет создания нового конструктора, который также принимает «Город» явно и получает доступ к имени из него? –

ответ

0

Отредактировано: Хорошо, так nowi знаю, что проблема: вы обращаетесь к city, прежде чем вы его создали. Поэтому см. Код ниже

@Override 
    public void onClick(View view) { 
     boolean canGenerate = true; 
     ArrayList<String> errors = new ArrayList<String>(); 

     switch(view.getId()) { 
     case R.id.bNewNext: 
      if(cityName.getText().toString().matches("")) { 
       errors.add("! Settlement must have a name.\n"); 
       canGenerate = false; 
      } 

      if(specific.isChecked() && customPop.getText().toString().matches("")) { 
       errors.add("! Enter a population figure.\n"); 
       canGenerate = false; 
      }   
      break; 
     } 

     if(canGenerate) { 
      // Here, you should run this method first 
      sendCityData(cityName.getText().toString()); 
      gen = new Generator(getBaseContext()); 
      errors.clear(); 
      gen.createCity(); 
     } else { 
      StringBuilder builder = new StringBuilder(); 
      for(String value : errors) { 
       builder.append(value); 
      }   
      errorList.setText(builder.toString()); 
      errors.clear(); 
     } 
    } 
+0

Может ли класс City быть инициализирован только в методе onCreate? Я спрашиваю, потому что в моем коде я инициализирую его в методе sendCityData (тот, который вызывается в onClick), потому что я извлекаю вход пользователя из EditText и отправляю его в класс как имя города. – Flawedspirit

+0

@Flawedspirit см. Мой отредактированный ответ –

Смежные вопросы