2017-11-05 12 views
6

Przeczytałem dokumenty dla Anko SQLite.Co to jest prosty MapRowParser w Anko?

wiem, że tworzenie prostych RowParser iScan zrobić wykonując val rowParser = classParser<Person>()

classParser to funkcja zdefiniowana w kodzie źródłowym Anko-SQLite.

Jak mogę uzyskać prosty MapRowParser?

+0

Zobacz https://stackoverflow.com/a/47076693/9204 –

+0

Dziękuję, masz na myśli, że Anko nie ma predefiniowanych MapRowParser podobnie jak classParser? Muszę napisać sam MapRowParser? – HelloCW

Odpowiedz

3

Jeśli przejdziesz na Github i zrobisz this search, zobaczysz, że istnieją dwa pliki, do których odwołuje się MapRowParser w jakikolwiek sposób.

Pierwszy plik zawiera to:

interface MapRowParser<out T> { 
    fun parseRow(columns: Map<String, Any?>): T 
} 

który pokazuje MapRowParser jako interfejs.

Jednak. Według wyszukiwania są dwa pliki, w których wymieniono MapRowParser. Jeśli przejrzysz pliki, zobaczysz, że nie ma klas. Według this question, która pokazuje ręczną implementację klasy, musi być ręcznie zaimplementowana. Ponadto kod dla Anko nie pokazuje żadnych klas, które implementują MapRowParser.

Musisz więc stworzyć klasę, która implementuje MapRowParser na własną rękę. Jeśli przeczytałem dokument i kod poprawnie, sama mapa jest automatycznie przekazywana, ale to, co robi analizator, obsługuje otrzymywane dane.


Równoważnie z RowParser. to interfejs. Jednak there is a method that returns a specific parser. Nic takiego nie ma w przypadku RowMapParser.

Edycja:

Wchodząc the source code pokazuje, że oba rodzaje pojedyńczych parserów rzędzie stosuje się kilka różnych typów. Myślę, że powodem, dla którego nie ma MapRowParser, jest zbyt trudne pisanie dobrego, ogólnego parsera map. Mapy mają różne zachowania w ogóle, ponieważ mają klucz i wartość, podczas gdy lista ma jedynie wartość, którą odlany jako typ i powrotu:

private class SingleColumnParser<out T> : RowParser<T> { 
    override fun parseRow(columns: Array<Any?>): T { 
     if (columns.size != 1) 
      throw SQLiteException("Invalid row: row for SingleColumnParser must contain exactly one column") 
     @Suppress("UNCHECKED_CAST") 
     return columns[0] as T//Right here it just casts the column as the type defined when creating 
    } 
} 

można zrobić to samo z Mapami, ale kluczem będzie być zagubionym. Ponadto podczas sprawdzania kodu źródłowego widać, że dane przekazywane do analizatora składni zawierają tylko jedną kolumnę.

Kopanie do źródła nieco dalej również ujawnia tę metodę:

private fun readColumnsMap(cursor: Cursor): Map<String, Any?> { 
    val count = cursor.columnCount 
    val map = hashMapOf<String, Any?>() 
    for (i in 0..(count - 1)) { 
     map.put(cursor.getColumnName(i), cursor.getColumnValue(i)) 
    } 
    return map 
} 

Jeśli Czytałem właściwego źródła, powyższa metoda konwertuje cały wiersz na jednej mapie i bierze nazwę kolumny z tym.Więc skończyć z czymś takim w jednym rzędzie:

Col1 -> Row1col1val 
Col2 -> Row1col2val 
... 

System działa na kursory, które można zobaczyć w metodach analizowania wielu pozycji na liście lub mapie:

moveToFirst() 
while (!isAfterLast) { 
    list.add(parser.parseRow(readColumnsMap(this)))//adds the result into a pre-defined list to return 
    moveToNext() 
} 

Co znowu pokazuje, że pisanie generycznego jest trudne, ponieważ musi istnieć wartość zwracana, która ma sens, co jest trudne, jeśli nie wiesz, jakie dane umieścić w pojedynczej wartości zwracanej.

To jest coś, co jest zbyt trudne * do napisania ogólnego parsera, ponieważ nigdy nie możesz być pewny co do liczby wierszy, co ma być zrobione z wartościami itp. Więc aby napisać własny parser , tworzysz klasę, która implementuje MapRowParser i używasz jej do analizy danych, których potrzebujesz. Na przykład, przypisując identyfikatory do klasy przechowywanej jako obiekt typu blob, umieszczając dane w klasie danych, bez względu na to, czego używasz.

* Pisanie jest zbyt trudne, ponieważ nigdy nie można mieć pewności, w jaki sposób jeden deweloper będzie potrzebował danych. Kiedy masz go jako mapę, nie możesz po prostu zwrócić pojedynczej wartości, ponieważ wszystkie pozostałe dane zostaną utracone. Musimy więc zwrócić go jako mapę, jeśli jest potrzebny do generowania analizatora składni, a następnie programista wciąż będzie musiał analizować dane. Dzięki Listom łatwo jest zwrócić pojedynczą wartość. Ale w przypadku Map, aby nie utracić żadnych danych, analizator składni staje się zasadniczo bezużyteczny, jeśli jest napisany w znormalizowanym celu.

+0

Dzięki! Dlaczego Anko pisze classParser? ale dlaczego Anko nie pisze narzędzi MapRowParser? Czuję, że to bardzo dziwne! – HelloCW

+0

Nie wiem, dlaczego go nie wdrożyli. Możliwe, ponieważ jest to zbyt skomplikowany typ do zastosowania ogólnego. Jednak jeśli chcesz dokładnej odpowiedzi na to pytanie, musisz zapytać twórców. – Zoe

+0

@HelloCW zrobił trochę więcej kodu i edytował odpowiedź. – Zoe