Общие настройки, вызывающие исключение нулевого указателя при переключении фрагментов

Я работаю над Android-приложением на основе фрагментов. В этом приложении он собирает некоторую информацию с веб-сайтов и сохраняет ее в SharedPreferences сравнить то, что пользователь хочет отобразить. Таким образом, пользователь вводит какую-то карту, которую он ищет, приложение очищает сеть каждые 12 секунд и, если она совпадает с вводом пользователя, отправляет уведомление. Теперь это работает на таймере, который является обработчиком, когда вы переключаете фрагменты, через 12 секунд он останавливается и выдает исключение нулевого указателя.

Почему это происходит, если он работает нормально, когда фрагмент активен? Вот часть кода.

При создании метода

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
  // Inflate the layout for this fragment
  v = inflater.inflate(R.layout.fragment_map, container, false);

  textView = (AutoCompleteTextView) v.findViewById(R.id.map_list);

  final ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_dropdown_item_1line, Maps1);
  textView.setThreshold(3);
  textView.setAdapter(adapter);
  mButton1 = (Button) v.findViewById(R.id.MapButton1);
  mButton2 = (Button) v.findViewById(R.id.MapButton2);
  mButton3 = (Button) v.findViewById(R.id.MapButton3);
  mButton1.setOnClickListener(onClick());
  mButton2.setOnClickListener(onClick());
  mButton3.setOnClickListener(onClick());
  dButton1 = (Button) v.findViewById(R.id.DeleMap1);
  dButton2 = (Button) v.findViewById(R.id.DeleMap2);
  dButton3 = (Button) v.findViewById(R.id.DeleMap3);
  dButton1.setOnClickListener(onClick());
  dButton2.setOnClickListener(onClick());
  dButton3.setOnClickListener(onClick());

  MapTV1 = (TextView) v.findViewById(R.id.topText1);
  MapTV2 = (TextView) v.findViewById(R.id.topText2);
  MapTV3 = (TextView) v.findViewById(R.id.topText3);
  LowTV1 = (TextView) v.findViewById(R.id.belowText1);
  LowTV2 = (TextView) v.findViewById(R.id.belowText2);
  LowTV3 = (TextView) v.findViewById(R.id.belowText3);
  LowTV4 = (TextView) v.findViewById(R.id.testView);

  final Handler handler = new Handler();
  Timer timer = new Timer();
  TimerTask doAsynchronousTask = new TimerTask() {
    @Override
    public void run() {
    handler.post(new Runnable() {
      @SuppressWarnings("unchecked")
      public void run() {
        try {
          //new Description().execute();
          startTimer(120000);
        } catch (Exception e) {
          // TODO Auto-generated catch block
        }
      }
    });
   }
  };
  timer.schedule(doAsynchronousTask, 0, 120000);

  //Notification area again *****************************************************************
  userNotification = new NotificationCompat.Builder(getActivity());
  userNotification.setAutoCancel(true);
  // Done ***********************************************************************************

  // Set user preferred maps on build *******************************************************
  SharedPreferences spFirstWanted = getActivity().getSharedPreferences("first_map", 17);
  String FirstWanted = spFirstWanted.getString("Firstwantedmap", "");
  MapTV1.setText(FirstWanted);

  SharedPreferences spSecondWanted = getActivity().getSharedPreferences("second_map", 18);
  String SecondWanted = spSecondWanted.getString("Secondwantedmap", "");
  MapTV2.setText(SecondWanted);

  SharedPreferences spThirdWanted = getActivity().getSharedPreferences("third_map", 19);
  String ThirdWanted = spThirdWanted.getString("Thirdwantedmap", "");
  MapTV3.setText(ThirdWanted);

  return v;
}

Одна из Asynctasks, которая выбрасывает исключение нулевого указателя

class Medium extends AsyncTask<String, String, String> {
  String desc;

  protected String doInBackground(String... params) {
    try {
      Document document = Jsoup.connect(mediumURL).get();
      Element table = document.select("table").get(0); //select the first table.
      Elements rows = table.select("tr:eq(6) > td.infodata > a ");

      for (Element td : rows) {
        System.out.println("TD" + td.text());
        return (td.text());
      }
      //return (td.text());
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }

  protected void onPostExecute(final String result3) {
    if (!result3.equals(null)) {
      new CountDownTimer(6000, 1000) {
        public void onTick(long millisUntilFinished) {
        }

        public final void onFinish() {
          SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
          //SharedPreferences sp = getActivity().getSharedPreferences("medium", 23);
          SharedPreferences.Editor sedt = sp.edit();
          sedt.putString("MediumMap", result3);
          sedt.commit();

        }
      }.start();
      LowTV4.setText(result3);

    } else if (result3.equals(null)) {
        MapTV3.setText("Choose a map");
    } else if (result3.equals("")) {
        MapTV3.setText("Choose a new map");
    }
  }
}

Таймер

 private void startTimer(long milliseconds) {
   CountDownTimer counter = new CountDownTimer(milliseconds, 1200000){
     public void onTick(long millisUntilDone) {

     }

     public void onFinish() {
       new Description().execute(url);
       new Map2().execute(url2);
       new EasyTwo().execute(easyTwoURL);
       new Medium().execute(mediumURL);

       SharedPreferences spFirstWanted = PreferenceManager.getDefaultSharedPreferences(getActivity());
       String FirstWanted = spFirstWanted.getString("Firstwantedmap", "");

       SharedPreferences spSecondWanted = getActivity().getSharedPreferences("second_map", 18);
       String SecondWanted = spSecondWanted.getString("Secondwantedmap", "");

       SharedPreferences spThirdWanted = getActivity().getSharedPreferences("third_map", 19);
       String ThirdWanted = spThirdWanted.getString("Thirdwantedmap", "");

       MapTV3.setText(FirstWanted);

       SharedPreferences beginnerSP = getActivity().getSharedPreferences("beginner", 20);
       String BeginnerValue = beginnerSP.getString("BeginnerMap", "");

       SharedPreferences easySP = getActivity().getSharedPreferences("easy", 21);
       String EasyValue = easySP.getString("EasyMap", "");

       SharedPreferences easyTwoSP = getActivity().getSharedPreferences("easyTwo", 22);
       String EasyTwoValue = easyTwoSP.getString("EasyTwoMap", "");

       SharedPreferences mediumSP = getActivity().getSharedPreferences("medium", 23);
       String mediumValue = mediumSP.getString("MediumMap", "");

       //Toast.makeText(getActivity(),/*"beginner " + prefs2 + " and easy " + prefs3 + " and easy2 " + prefs4 +*/ " medium " + mediumValue,Toast.LENGTH_LONG).show();

       if (BeginnerValue.equals(FirstWanted)) {
           setUserNotification(BeginnerValue, "Beginner");
       } else if(EasyValue.equals(FirstWanted)) {
           setUserNotification(EasyValue, "Easy");
       } else if(EasyTwoValue.equals(FirstWanted)) {
           setUserNotification(EasyTwoValue, "Easy Two");
       } else if(mediumValue.equals(FirstWanted)) {
           setUserNotification(mediumValue, "Medium");
       } else {
         System.out.print("They Don't Match!");
         LowTV3.setText("They don't match!");
       }
     }
   };
   counter.start();
 }

Некоторые вещи просто выводят тестовые данные на экран, чтобы убедиться, SharedPreferences работает, спасибо за вашу помощь.

Журнал ошибок

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
    at android.preference.PreferenceManager.getDefaultSharedPreferencesName(PreferenceManager.java:376)
    at android.preference.PreferenceManager.getDefaultSharedPreferences(PreferenceManager.java:371)
    at com.horizonservers.horizon.MapFragment$Medium$1.onFinish(MapFragment.java:658)
    at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:127)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:7325)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

2 ответа

Решение

Это потому SharedPreferences context был уничтожен при переключении фрагмента, поэтому теперь он указывает на нулевой объект, который был уничтожен ранее.

Либо используйте WeakReference, либо используйте Singleton для утилиты предпочтений.

Для утилиты синглтонных настроек вы можете взглянуть на Prefs.java из https://github.com/Pixplicity/EasyPreferences.

Кажется, что getActivity() вернуть null после удаления фрагмента

Поэтому вы должны хранить стоимость getActivity() или же getActivity().getApplicationContext() первый. (И в экземпляре Runnable, и в экземпляре Medium)

Затем используйте значение вместо getActivity(),

Другие вопросы по тегам