IllegalStateException для фрагмента, не присоединенного к Activity - PullRequest
2 голосов
/ 26 октября 2011

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

java.lang.IllegalStateException: фрагмент MainHomeFragment {40544bd8} не присоединен к действию

Это происходит, если я тестирую по телефону или с помощью эмулятора. Похоже, что проверка лицензии не завершается достаточно быстро, поэтому, когда она раздувает фрагмент, нет действия, к которому его можно присоединить. Сначала я просто запускал приложение, а затем нажимал кнопку «Назад», как только оно загрузилось, и сразу же попробовал снова. Я подумал, что программа проверки лицензии все еще работает с первой попытки, поэтому в следующий раз я подождал 5 минут, прежде чем использовать клавишу возврата, и все еще получил ту же проблему. Странно то, что после того, как приложение взорвалось во 2-й раз, если я попробую его снова, оно заработает, но на 4-й попытке снова не получится, поэтому что-то не должно очищаться с первой успешной попытки. Если я закомментирую код LicenseChecker и запустлю его снова, он будет работать каждый раз. Я попытался поместить вызов LicenseChecker в новый класс в качестве потока, чтобы он не задерживал создаваемое действие, но все равно получал ту же проблему. Любые идеи о том, что я должен попытаться это исправить?

Вот код onCreate для моей основной функции Fragment:

public void onCreate(Bundle savedInstanceState) {      
  super.onCreate(savedInstanceState);

  ConnectivityManager connectivityManager 
    = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
  NetworkInfo activeNetwork = 
    connectivityManager.getActiveNetworkInfo();

  if (activeNetwork != null) { 
    android_id = Secure.getString(this.getContentResolver(), 
      Secure.ANDROID_ID);
    mObsfuscator = new AESObfuscator(SALT, getPackageName(), android_id);
    ServerManagedPolicy serverPolicy = new 
      ServerManagedPolicy(this, mObsfuscator);
    mLicenseCheckerCallback = new MyLicenseCheckerCallback();
    mChecker = new LicenseChecker(this, serverPolicy,
      BASE64_PUBLIC_KEY);
    mChecker.checkAccess(mLicenseCheckerCallback);
  } 

  setContentView(R.layout.fragment_layout);
}

Ответы [ 2 ]

0 голосов
/ 20 декабря 2013

Я знаю, что это действительно старая версия, но я все равно добавлю свои 2 цента.

В вашем вопросе неясно, как вы добавляете Fragment (через XML <fragment>или с тегом FragmentTransaction. Что бы вы ни делали, если вы хотите, чтобы Fragment был добавлен только в определенном случае (если средство проверки лицензий возвращает ОК или что-то еще), я бы порекомендовал добавить фрагмент программно.

Таким образом, в основном, определите ваше представление «Загрузка ...» внутри FrameLayout или любого другого макета, а затем, с помощью FragmentTransaction, замените все, что находится в этом объекте макета, на ваш новый Fragment.

Я делаю это с Thread. Мне очень не нравится AsyncTask, поскольку все фоновые задания совместно используют один поток. Это немного облегчает синхронизацию, но может реально повлиять на производительность, если у вас многозагрузок / сетевых заданий, например, потому что это своего рода очереди одна за другой, и запуск длинного задания задержит выполнение всех других фоновых заданий.

Я определяю ДВА Runnable объектов ((implements Runnable) потому что вам нужен еще один для выполнения в потоке пользовательского интерфейса (если вы манипулируете пользовательским интерфейсом из фонового потока, вы получите Exception).

Таким образом, в основном, в первом Runnable объекте, который будет выполненпо Thread вы получаете ссылку на вызывающий Activity и сохраняете ее как переменную экземпляра.Затем вы используете эту ссылку для выполнения второго Runnable объекта в потоке пользовательского интерфейса, как показано ниже (я делаю это в конце метода run: callingActivity.runOnUiThread(new RunnableToRunOnUIThread());, и там вы добавляете Fragment программно.

0 голосов
/ 27 октября 2011

Почему вы изначально не делаете setContentView с представлением загрузки, а затем, после завершения процедуры лицензирования, вы делаете "настоящий" setContentView со своим фрагментом?

Я думаю, это будет нормально.

...