2011-02-10 10 views
6

Badałem alternatywne metody zapisywania danych z mojej gry między kolejkami i zastanawiam się, czy ktoś może wskazać mi właściwy kierunek.Najlepsza metoda zapisywania danych - preferencje, sqlite, serializowalne lub inne?

Mam około 32k danych, które muszą zostać zapisane w trybie onPause. Wykluczyłem preferencje ze względu na ogromną ilość danych. Spędziłem kilka dni bawiąc się z SQLite, ale nie mogłem zapisać danych w czasie krótszym niż dwie sekundy (chociaż czas z pewnością nie został zmarnowany).

Zdecydowałem, że użyję bazy danych do załadowania stałych danych na początku gry. To z pewnością ułatwi dostrojenie różnych parametrów i wartości domyślnych w grze. Ale to wciąż pozostawia mi poszukiwanie idealnej metody zapisu danych.

Dane, które należy zapisać to zasadniczo dziewięć wystąpień klasy A i dziewięć wystąpień klasy B. Jestem intensywnym miesiącem na krzywej uczenia się Androida (i niuansów Java, pochodzących z tła C++) i szukałem go jak szalonego. Ten przyniósł dwie możliwości umysłu -

1) serializacji (ObjectOutputStream)

myślałem, że to byłoby idealne rozwiązanie, ale po przeczytaniu kilku innych stanowisk dotyczących tematu, gromadzić, że nie jest zalecane na Platforma Android ze względu na szybkość i alokację pamięci, które prowokują śmieciarza do potencjalnego gniewu.

2) Klasa DataOutputStream

Mój obecny myśl jest dodanie wczytywać i zapisywać funkcje obu klas i używać DataOutputStream i DataInputStream wywołuje w nich do zapisu i odczytu danych odpowiednio.

Dane w klasach są prymitywami (głównie ciągi i int) i tablicami prymitywów, więc nie ma nic zbyt skomplikowanego, aby się zepsuć. Czy to drugie rozwiązanie wydaje się dobre, rentowne? Czy są jeszcze inne rozwiązania, których nie jestem jeszcze świadomy?

+0

Najważniejszą kwestią, którą należy wziąć pod uwagę, jest to, że zapis na flash może być długotrwałą operacją, niezależnie od wielkości danych. Nawet zapisanie 1 bajta może zająć zauważalną ilość czasu. Dlatego upewnij się, że twoje rozwiązanie buforuje wszystkie dane i zapisuje je w jak najmniejszej liczbie operacji. – Jems

+1

Dzięki za poradę. Przeszedłem za pomocą metody DataOutputStream, a czas potrzebny do zapisania danych jest teraz znikomy (około 0,1 sekundy). Cieszę się, że udało mi się omijać bazy danych SQLite, ponieważ na pewno będą bardzo przydatne :) – Rok

Odpowiedz

2

należy użyć zadania Async, aby zapisać dane, użyłem tej metody, aby pobrać najlepsze wyniki na starcie gry:

new HighscoreTask().execute(this); 

zadanie asynchroniczny wygląda następująco:

public class HighscoreTask extends AsyncTask<MainView, Void, Void> { 

    protected void onPreExecute() { 
    } 

    protected void onPostExecute(final Void unused) { 
    } 
    @Override 
    protected Void doInBackground(MainView... params) { 
     HighScoreFactory.syncScores(); 
     return null; 
    } 
} 

Wszystko interakcja z bazą danych dzieje się w HighScoreFactory.syncScores() może to potrwać tak długo, jak to konieczne, ponieważ dzieje się to w tle. W moim przypadku wysyła żądanie HTTP do zewnętrznego serwera i ładuje je do bazy danych. To nigdy nie powodowało żadnych problemów i działa bezproblemowo.

+0

Dzięki - na pewno o tym pamiętam. Zapisuję dane gry jako nieprzetworzone pliki binarne, które działają szybciej *. Ale na pewno zbadamy Async, tak jak kilka osób zasugerowało to teraz. – Rok

1

Czy próbowałeś wstawić dane do bazy danych w transakcji?

try{ 
db.beginTransaction(); 

//here insert data to database  

db.setTransactionSuccessful(); 
} finally { 
db.endTranscation(); 
} 

Może to przyspieszyć działanie.

+0

Eksperymentowałem z wykorzystaniem transakcji do momentu, w którym wszystkie moje zapisy zostały wykonane w jednej transakcji - to przyniosło czas od 8 sekund do 2 sekund. Wydawało mi się, że w tym momencie uderzyłem w ceglaną ścianę i, dawałem lub zajmowałem jedną dziesiątą sekundy, nie mogłem się obniżyć. To jest pierwsze kodowanie SQLite, które zrobiłem, ale czułem, że nie mogłem go osiągnąć szybciej (chociaż z przyjemnością dowiedziałbym się, że jest inaczej). – Rok

0

Utwórz nowy wątek, który zapisuje dane za pomocą Context.openFileOutput (nazwa ciągu, tryb int) z tym kontekstem. Następnie możesz napisać go w tle z nowym wątkiem i pobrać go ponownie: Context.openFileInput (nazwa ciągu) ponownie jako kontekst. Mam nadzieję, że to pomaga.

2

Dlaczego masz 2-sekundowy limit zapisu bazy? Jeśli jest to wyłącznie ze względu na responsywność interfejsu użytkownika, istnieje inne podejście, które można podjąć.

W rzeczywistości nie musisz wykonywać zapisu w ramach samej metody , możesz po prostu uruchomić nowy Thread, który faktycznie robi zapis dla ciebie.

private void backgroundSave(){ 
    Thread backgroundThread = new Thread() { 
     @Override 
     public void run() { 
      //do save here 
     } 
    }; 
    backgroundThread.start(); 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    backgroundSave(); 
} 

Można alternatywnie użyć do tego celu AsyncTask.

Być może trzeba będzie rozważyć przypadek, gdy użytkownik spróbuje ponownie uruchomić aplikację przed ukończeniem składowania, ale nie powinno to być zbyt trudne do wzięcia pod uwagę.

+1

Zapisywane dane są w ciągłym użyciu we wszystkich działaniach. Pomysł przypisania zapisu do wątku tła brzmi dobrze, ale nie miałem jeszcze czasu, aby zapoznać się z rozwiązywaniem problemów z synchronizacją. Jest to coś, na co na pewno zajrzę, gdy tylko dostanę szansę. Na razie odkryłem, że mogę zapisać dane w pliku binarnym w około 0,1 sekundy. Doceniam jednak radę. Tyle się nauczyć, tak mało czasu ... :) – Rok

Powiązane problemy