Открытие подоперации несколько раз вызывает InstanceCountViolation, несмотря на то, что оно уничтожено - PullRequest
8 голосов
/ 06 июля 2011

Я работаю над проектом с более низким уровнем активности, который называется RecordView, чтобы отобразить такие детали записи, как изображение, дата и время, когда он был сделан, а также информацию о широте / долготе. Вместо того, чтобы пытаться манипулировать камерой для геотегирования и доступа к данным exif, я пытаюсь внедрить слушатель местоположения, чтобы получить местоположение, где изображение было впервые снято (при нажатии кнопки). Этот подход работает - я получаю мое местоположение, чтобы отображать и корректно обновлять запись в базе данных (возврат к представлению позже отображает местоположение с начала). Однако, если я вернусь из текущего RecordView, а затем введу еще две (любая комбинация), программа завершится с ошибкой InstanceCountViolation (полная ошибка перепечатана ниже). Когда я переопределяю методы времени жизни RecordView для отображения при каждом вызове, мы обнаруживаем, что он уничтожается перед повторным вызовом. То есть не похоже, чтобы в любой момент времени существовало более одного RecordView.

Итак, мой вопрос сводится к следующему: откуда эта ошибка и как я могу ее исправить?

Что-то лжёт о разрушении? LocationListener где-то сидит и вызывает проблемы? Это что-то не связанное, что может быть фиктивной ошибкой?

Кроме того, я должен сделать ужасное жестко запрограммированное исправление и просто увеличить предел RecordView разрешенных экземпляров? Или продолжить поиск другого подхода (в качестве примера я пытаюсь запросить одно обновление с помощью вызова PendingIntent.getBroadcast(...))?

Для справки: эта ошибка появилась на эмуляторе 3.1 и на реальном планшете (Xoom, 3.1). Комментирование кода обновления слушателя, похоже, помогает избежать сбоя ( РЕДАКТИРОВАТЬ 2 : я, кажется, ошибался в этом). Код, относящийся к слушателю, приведен ниже (его можно найти в открытом методе updateLocation внутри класса RecordView).

    // Listener for the update request
    LocationListener locListener = new LocationListener() {
        // Store the currentRecord so the listener can update it after return
        Record currentRecord = record;
        GeoDatabase database = data;
        @Override
        public void onLocationChanged(Location location) {
            if (location != null) {
                myLocation = location;
                Log.d(TAG, "Location pulled as " + myLocation);
                String lat = Location.convert(myLocation.getLatitude(), 
                        Location.FORMAT_SECONDS);
                String lon = Location.convert(myLocation.getLongitude(), 
                        Location.FORMAT_SECONDS);

                // Update the record values
                currentRecord.setRecordLatitude(lat);
                currentRecord.setRecordLongitude(lon);
                database.updateRecord(currentRecord);
                Log.d(TAG, "Record values now listed as "+ record.getValues());

                // Update the text boxes
                latitude.setText(lat);
                longitude.setText(lon);

                Toast.makeText(getBaseContext(),"GPS location updated",
                        Toast.LENGTH_LONG).show();
            } else {
                Log.w(TAG, "Passed location is null!");
                Toast.makeText(getBaseContext(),
                        "GPS error - unusable location", 
                        Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onProviderDisabled(String provider) {
            Toast.makeText(getBaseContext(),
                    "GPS disabled", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onProviderEnabled(String provider) {
            Toast.makeText(getBaseContext(),
                    "GPS enabled", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    lm.requestSingleUpdate(LocationManager.GPS_PROVIDER, locListener, null);

Полная ошибка:

android.os.StrictMode$InstanceCountViolation:class [program path].RecordView; instances=3; limit=2
    at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)

EDIT:

Две вещи я определил.

Во-первых, когда Logcat показывает уничтожение действия RecordView, LocationListener корректно отключается (уничтожается? В любом случае, он нулевой). Однако слушатель, кажется, обновляется из-за могилы, то есть иногда я вижу свое тост-сообщение об обновлении GPS на экране действий более высокого уровня, и информация GPS, похоже, обновлена.

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

РЕДАКТИРОВАТЬ 2:

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

Intent intent = new Intent(this.getActivity()
        .getApplicationContext(), RecordView.class);
Bundle extras = new Bundle();
extras.putString("tableName", "table1");
extras.putInt("id", mId);
extras.putBoolean("newRecord", false);
extras.putLong("folder_id", mFolderId);
extras.putString("type", recordList.get(mId).getTableName());
intent.putExtras(extras);

startActivity(intent); 

Так что теперь мне интересно, есть ли проблема в том, как Intent обрабатывает создание и удаление действий.

Ответы [ 2 ]

0 голосов
/ 12 августа 2014

Я знаю, что это старый пост.Просто для парней, которые ищут решение и объяснение этой проблемы.

В случае возникновения исключения InstanceCountViolation это означает, что может быть реальная проблема с утечкой активности или проблема, связанная с тем, как в детекте SDK реализована проверка deteActivityLeaks,

Чтобы определить, является ли это проблемой, я могу порекомендовать следующее сообщение: Обнаружение утечки активности в Android .Если вы увидите, что есть объекты, содержащие ссылку на это действие, которые не связаны с Android Framework, то у вас есть проблема, которую вы должны решить.

В случае, если нет объектов, содержащих ссылку наэто действие, которое не относится к Android Framework, а означает, что вы столкнулись с проблемой, связанной с тем, как реализована проверка обнаруженияActivityLeaks.В этом случае, чтобы исправить проблему с неудачной активностью без отключения DetectionLeaks, вы можете просто запустить System.gc () перед началом активности в конфигурации отладки, как в следующем примере:

 if (BuildConfig.DEBUG)
 {         
     System.gc();
 }

 Intent intent = new Intent(context, SomeActivity.class);
 this.startActivity(intent);

Более подробная информация доступна в этом ответе .

0 голосов
/ 27 мая 2013

Кажется, что в этом нет необходимости, но вы пытались вызвать

lm.removeUpdates(locListener);

, чтобы отменить регистрацию слушателя?

...