Удалить данные постоянного хранилища при удалении / удалении приложения

У меня есть приложение BlackBerry, которое запускается (загрузка приложения) с экрана регистрации при первой установке приложения. Позже приложение загрузится с главным экраном. Экран регистрации появляется только при первой загрузке. Я добиваюсь этого, сохраняя значение boolean в PersistentStore. Если значение существует, то экран регистрации не появится.

PersistentStoreHelper.persistentHashtable.put("flagged",Boolean.TRUE);
PersistentStoreHelper.persistentObject.commit();
UiApplication.getUiApplication().pushScreen(new MyScreen());

Мне известно, что для удаления постоянного хранилища при удалении / удалении приложения я должен сделать Hashtable своим собственным подклассом, и поэтому я объявил Hashtable в отдельном классе:

public class PersistentStoreHelper extends Hashtable implements Persistable{

    public static PersistentObject persistentObject;
    public static final long KEY = 0x9df9f961bc6d6daL;
    public static Hashtable persistentHashtable;

}

Однако это не помогло, и значение boolean флага не сбрасывается с PersistentStore. Пожалуйста посоветуй.


ИЗМЕНИТЬ: когда я изменяю вышеупомянутый класс PersistentStoreHelper на

public static PersistentObject persistentObject =
    PersistentStore.getPersistentObject(KEY);

и удалить

PersistentStoreHelper.persistentObject = 
    PersistentStore.getPersistentObject(PersistentStoreHelper.KEY);

из класса B, где сохраняется значение boolean, я заметил, что значение boolean удаляется каждый раз, когда приложение закрывается. Этого не должно происходить, и значение следует удалять только в случае удаления / удаления приложения. Есть указатели?


person Sarah    schedule 01.04.2013    source источник


Ответы (1)


Это работает так: BlackBerry OS смотрит на объекты, которые вы храните в PersistentStore. Если он распознает, что эти объекты могут использоваться только вашим приложением, он удалит их при удалении приложения. Однако, если классы хранимых объектов являются классами, которые используются другими приложениями, ваши данные не будут удалены.

Вы объявили свой вспомогательный класс следующим образом:

public class PersistentStoreHelper extends Hashtable implements Persistable{

но вспомогательный класс - это не то, что сохраняется. Ваш вспомогательный класс - это просто помощник, который хранит для вас другие вещи. В вашем случае он хранит это:

public static Hashtable persistentHashtable;

но этот объект имеет тип java.util.Hashtable, который является классом, используемым многими приложениями. Таким образом, он не будет удален при удалении приложения. Что вам следует сделать, это примерно так:

public class PersistentStoreHelper implements Persistable {  // so inner class = Persistable

    public static PersistentObject persistentObject;
    public static final long KEY = 0x9df9f961bc6d6daL;
    /** 
      * persistentHashtable is now an instance of a class that
      * only exists in your app 
      */
    public static MyAppsHashtable persistentHashtable;

    private class MyAppsHashtable extends Hashtable implements Persistable {
        // don't need anything else ... the declaration does it all!
    }
}

Я не вижу его здесь, но предполагаю, что где-то у вас есть этот код:

persistentObject = PersistentStore.getPersistentObject(KEY);

а затем, когда вы хотите сохранить данные обратно в магазин, вы делаете что-то вроде этого;

persistentHashtable.put("SomeKey", someNewData);
persistentObject.setContents(persistentHashtable);
persistentObject.commit();

простое добавление данных в persistentHashtable не сохраняет их (навсегда). Надеюсь, эта часть у вас уже была где-то.


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

persistentHashtable = (MyAppsHashtable)persistentObject.getContents();

потому что последняя версия вашего кода не использовала класс MyAppsHashtable, поэтому загруженные данные не будут этого типа. Это одна из причин, по которой важно сделать это правильно с первого раза. В общем, я всегда заканчиваю сохранение данных в PersistentStore, который содержится в одном Hashtable подклассе верхнего уровня, который реализует Persistable. Позже я могу изменить то, что в нем содержится, но я никогда не буду менять подпись этого объекта хранилища верхнего уровня. Надеюсь, вы еще не выпустили свое приложение.


Обновление: в ответ на ваш комментарий / вопрос ниже:

if (PersistentStoreHelper.persistentObject.getContents() == null) {   
    PersistentStoreHelper.persistentHashtable = new MyAppsHashtable();    
    PersistentStoreHelper.persistentObject.setContents(PersistentStoreHelper.persist‌entHashtable); 
} else { 
    PersistentStoreHelper.persistentHashtable = 
        (MyAppsHashtable)PersistentStoreHelper.persistentObject.getContents(); 
} 
person Nate    schedule 01.04.2013
comment
Спасибо, @Nate. Я пытаюсь обойти это. Раньше я использовал следующий способ getContents: if (PersistentStoreHelper.persistentObject.getContents() == null) { PersistentStoreHelper.persistentHashtable = new Hashtable(); PersistentStoreHelper.persistentObject.setContents(PersistentStoreHelper.persistentHashtable); } else { PersistentStoreHelper.persistentHashtable = (Hashtable)PersistentStoreHelper. persistentObject.getContents();} Я не могу редактировать: persistentHashtable = (MyAppsHashtable)persistentObject.getContents(); Как это сделать? - person Sarah; 02.04.2013
comment
@Sarah, пожалуйста, посмотрите мое второе обновление в ответе выше. Спасибо. - person Nate; 02.04.2013
comment
Я работал с предоставленным вами Edit, но это не помогает; Я получаю несоответствие типа: Cannot convert from Hashtable to PersistentStoreHelper.MyAppsHashtable. Не могли бы вы помочь? РЕДАКТИРОВАТЬ: проблема теперь в PersistentStoreHelper.persistentObject.setContents(PersistentStoreHelper.persist‌entHashtable);. Эта строка выдает ошибку: persist‌entHashtable не может быть разрешен или не является полем. - person Sarah; 03.04.2013
comment
@Sarah, я не вижу вашего точного кода, но могу предположить, что ваша проблема связана с тем, что вы не используете PersistentStoreHelper как настоящий класс. Вы просто сбрасываете туда вещи. Что вам следует сделать, так это сохранить весь код, необходимый для загрузки и сохранения из постоянного хранилища внутри этого класса, и обрабатывать инициализацию хранилища внутри этого класса. Я почти уверен, что ты этого не делаешь. Прежде всего, все public static переменные в вашем коде должны быть private. Тогда код внизу моего ответа действительно должен быть внутри конструктора, или initialize() ... - person Nate; 03.04.2013
comment
.. метод класса PeristentStoreHelper. Когда вы это сделаете, вам не нужно писать PersistentStoreHelper.persistentHashtable. Вы просто пишете persistentHashtable. Весь этот код должен быть внутри PersistentStoreHelper метода (или конструктора). Тогда компилятор сможет увидеть закрытый класс MyAppsHashtable. Очень важно понять эту концепцию, прежде чем идти дальше, иначе в вашем Java-коде будет много проблем. Я рекомендую посмотреть что-нибудь вроде этого руководства в Интернете. - person Nate; 03.04.2013
comment
@Sarah, Кроме того, я поместил образец реализации класса PersistentStoreHelper, который, как мне кажется, будет намного чище, чем то, с чем вы пытаетесь работать, онлайн здесь. Пример того, как использовать его извне класса, показан в комментариях к классу в верхней части файла. - person Nate; 03.04.2013
comment
Спасибо, @Nate. Хотя я еще не реализовал класс полностью, ваш ответ хорошо объяснен и проясняет ситуацию. Я буду над этим работать. - person Sarah; 04.04.2013
comment
Я знаю, что ответ принят, но не могли бы вы мне помочь? Я выполнил описанное выше, и приложение отлично загружается на симуляторе, но на устройстве выдает ошибку Class Cast Exception. Вы можете прокомментировать? - person Sarah; 08.04.2013
comment
где возникает это исключение? какая линия? Вы проверили мое Примечание: в ответе о запуске после изменения кода для использования MyAppsHashtable? - person Nate; 08.04.2013
comment
Да, я проверил вашу заметку. Я нигде в своем коде не звонил persistentHashtable = (MyAppsHashtable)persistentObject.getContents();. Я вызываю свой основной класс (запускать приложение) следующим образом: PersistentStoreHelper.getInstance(); PersistentStoreHelper.persistentObject= PersistentStore.getPersistentObject(PersistentStoreHelper.KEY); if (PersistentStoreHelper.getInstance().get("flagged")!=null) { boolean booleanVal = ((Boolean) PersistentStoreHelper.getInstance().get("flagged")).booleanValue(); - person Sarah; 09.04.2013
comment
отладка не помогает, поскольку приложение работает на симуляторе, но не на реальном устройстве. - person Sarah; 09.04.2013
comment
@Sarah, ну, в коротком фрагменте кода, который вы только что опубликовали, единственное место, где вы могли бы получить ClassCastException, - это преобразовать результат get("flagged") в Boolean. Если вы изначально вызвали put("flagged", value) со значением, не являющимся объектом Boolean, вы получите это исключение. Кроме того, вы можете работать в отладчике с приложением на своем устройстве, если оно подключено через USB-кабель. - person Nate; 09.04.2013