Android Studio + Jetpack Compose - jak wyświetlić listę ( wynik )na ekranie telefonu

0

Zawężę nieco pytanie, które zadałem poprzednio :-)

W ViewModel mam funkcję, która odpowiednio wyświetla wyniki obliczeń
To fragment tego kodu:

var wynik_tablica_1 = 0
                    val zawodnicy: MutableList<RecordZawodnik> = mutableListOf()
                    for (numer in 1..rozmiar_tablicy){
                        wynik_tablica_1 = tablica_1[numer-1].toInt()
                        zawodnicy.add(RecordZawodnik("Z" + numer,wynik_tablica_1))
                    }

                    var lp= 0
                    println("--- ASC ---")
                    zawodnicy.sortByDescending { it.wynik_zawodnika } //sortowanie
                    zawodnicy.forEach{
                        lp += 1
                        print("lp$lp. " + it.nazwa_zawodnika + " ")
                        println(it.wynik_zawodnika)
                    val a = it.wynik_zawodnika
                    val b = it.nazwa_zawodnika

                       print("a= $a")
                       println("b= $b")


                        _recordZawodnik.value = recordZawodnik.value.copy( b,a )

                        println ("_record_Zawodnik.value=  "  + _recordZawodnik.value)
                        println ("record_Zawodnik.value.copy_ba = "  + recordZawodnik.value.copy(b,a))
                    }

Funkcja działa prawidłowo ale nie potrafię przekazać wyników do wyświetlenia na ekran telefonu.
To fragment wyników Println na Terminalu:

I/System.out: lp1. Z12 86
I/System.out: a= 86b= Z12
I/System.out: _record_Zawodnik.value=  RecordZawodnik(nazwa_zawodnika=Z12, wynik_zawodnika=86, a=0, b=test2)
I/System.out: record_Zawodnik.value.copy_ba = RecordZawodnik(nazwa_zawodnika=Z12, wynik_zawodnika=86, a=0, b=test2)

Mam kłopot z linią:

 _recordZawodnik.value = recordZawodnik.value.copy( b,a )

Nie potrafię tego prawidłowo zapisać.
( b , a ) się nie zmieniają .
Wyświetla się to co zadeklarowałem w ViewState:

data class RecordZawodnik (
    var nazwa_zawodnika: String ="",
    var wynik_zawodnika: Int =0,
    val a: Int = 0,
    val b: String = "test2"

)

Tu funkcja która ma wyświetlić wyniki:

@Composable
fun wyniki(
    viewModel: HomeViewModel = hiltViewModel()
){
    val state = viewModel.recordZawodnik.collectAsState()
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        Column(
            modifier = Modifier.fillMaxWidth(),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(
                text = stringResource(R.string.calculation_result, state.value.a)

            )

            Text(
                text = stringResource(R.string.calculation_result, state.value.b)
            )

        }
    }

Niestety a i b wyświetlają te same wartości jak w ViewModel...
:-)

Edit
Zmieniłem nieco zapis w ViewModel i coś się zaczęło dziać: :-)

_recordZawodnik.value = recordZawodnik.value.copy( b= it.nazwa_zawodnika,a =it.wynik_zawodnika )

Tak wygląda to na terminalu:

I/System.out: lp1. Z12 86
I/System.out: a= 86b= Z12
I/System.out: _record_Zawodnik.value=  RecordZawodnik(nazwa_zawodnika=, wynik_zawodnika=0, a=86, b=Z12)
I/System.out: record_Zawodnik.value.copy_ba = RecordZawodnik(nazwa_zawodnika=Z12, wynik_zawodnika=86, a=86, b=Z12)

a i b zaczęły pracować, tylko nie wiem czemu wcześniej to nie działało.

Teraz tylko to przekazać na ekran :-)
Coś tam niby jest szczątkowo: :-)
screenshot-20220517153425.png
Wyświetla się ostatni wynik...to akurat jest logiczne :-)

0

Kurde banalna rzecz. Nie wiem jak po każdym odczytaniu wyników przejść do następnej linii 🙂
Mogę wyświetlić 100 linii ale w każdej jest to samo.
screenshot-20220517210310.png

Tu filmik obrazujący to działanie:

[https://www.youtube.com/shorts/Gb_0YmfxGGQ]

0

Dobra, poradziłem sobie, choć to dosyć pokrętny sposób... jak na Jetpack Compose, który ma ułatwiać raczej niż utrudniać :-)
Mam nadzieję, że to tylko moja niewiedza...:-)

No więc tak:
Skorzystałem z LazyColumn.
Kod ( miejsce wyświetlania) wygląda tak:

@Composable
fun MainList(viewModel: HomeViewModel = hiltViewModel()){ // połączenie z ViewModel i data class( record ) HomeViewState
    val state = viewModel.viewState.collectAsState() //  Ta operacja gwarantuje  update ui przy każdej zmianie danych

val list2_ = state.value.result //list2_ (List<Any>) ( miejsce przekazania wyników z ViewModel - result)
    //Tak wygląda List2_ [lp1.   Zawodnik23 =  99, lp2.   Zawodnik19 =  95, lp3.   Zawodnik12 =  86, lp4.   Zawodnik9 =  83, lp5.   Zawodnik31 =  78, (...)
    
    // poniżej całe wyświetlanie
    LazyColumn(
        Modifier.fillMaxSize(),
        contentPadding = PaddingValues(12.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    )
    {
        items(list2_){ wyniki ->  // kluczowe miejsce. Program odczytuje ilość elementów ( list2_ )
            Card (
                modifier = Modifier.fillMaxWidth(),
                backgroundColor = Color(0xFFCFF5FA),
                elevation = 4.dp
                    )
            {
                Text(
                    text = (wyniki.toString()), // to co ma się wyświetlić czyli list2_ zamieniona na String no bo ...text :-)
                    textAlign = TextAlign.Left,
                    style = MaterialTheme.typography.h4,
                    modifier = Modifier.padding(12.dp)
                )
            }
        }
    }

}


Kluczowe jest przekazanie tablicy w postaci listy bo dzięki temu program potrafi przejść do kolejnej linii z następnym wynikiem.
Kluczowe jest też przekazanie od razu wszystkich wyników - dlatego lista, bo jak wyniki wpadają kolejno to nie wiem jak je wyświetlać w kolejnych liniach.
W każdym razie nie znalazłem prostego rozwiązania tego problemu.
Tu jeszcze fragment ViewModel:

ByteArrayOutputStream().use {
                    client.retrieveFile(plik, it)
                    val data = String(it.toByteArray())
                    val tablica_1 = data.lines() //pobrana tablica z pliku
                    println("tablica_1= " + tablica_1)
                    val rozmiar_tablicy =
                        (tablica_1.size - 1) // -1 ze wzgledu na pustą linię na końcu listy plików


                    //////// zapis rekordow,sortowanie, wyświetlanie - początek//       //////

                    //data class RecordZawodnik (var nazwa_zawodnika: String ="", var wynik_zawodnika: Int =0)
                    var wynik_tablica_1 = 0
                    val zawodnicy: MutableList<RecordZawodnik> = mutableListOf()
                    for (numer in 1..rozmiar_tablicy) {
                        wynik_tablica_1 = tablica_1[numer - 1].toInt()      // kolejne wyniki z tablicy
                        zawodnicy.add(RecordZawodnik("Zawodnik" + numer, wynik_tablica_1))
                    }

                    var lp = 0
                        zawodnicy.sortByDescending { it.wynik_zawodnika }        //sortowanie po wyniku
                    val listaZawodnicy: MutableList<Any> = mutableListOf() // zdefiniowana tablica ( listaZawodnikow) typu lista

                    // Pętla w której wstawiam wszytskie dane z data class RecordZawodnik do listy ( listaZawodnikow)
                    zawodnicy.forEach {
                        lp += 1
                        listaZawodnicy.add("lp$lp.   " + it.nazwa_zawodnika + " " + "=  " + it.wynik_zawodnika)
                    }

                    // Miejsce przekazania listy do funkcji wyświetlania wyników
                    // -  @Composable
                    //fun MainList(viewModel: HomeViewModel = hiltViewModel())
                    _viewState.value = viewState.value.copy(
                        result = listaZawodnicy
                    )

                }

                client.logout()
                client.disconnect()
            }

        })
    }


Pokażę jeszcze ( do kompletu ) jak wygląda fragment z ...tworzeniem viewState w ViewModel.

import androidx.lifecycle.ViewModel
//import com.mmajka.composemvvmsample.ui.main.displaying_results
import com.mmajka.composemvvmsample.ui.main.nazwa_sedzia_new
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import org.apache.commons.net.ftp.FTPClient
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import javax.inject.Inject


val executorService: ExecutorService = Executors.newFixedThreadPool(4) // bez tego nie wywoła się operacji z ftp.  

class HomeViewModel @Inject constructor() : ViewModel() {

    //tworzenie viewState - nie umiem nic więcej aktualnie na ten temat napisać :-)
    private val _viewState = MutableStateFlow(HomeViewState()) 
    val viewState: StateFlow<HomeViewState>
        get() = _viewState
    // w kazdym razie to jest tworzenie połączenia danych z wyświetlaniem  

No i jeszcze ViewState. Czyli inicjalizowanie tablic...tak bym to określił. :-)

// recor zawierający tablice typu lista, które posłużą do przekazania danych do wyświetlenia 
data class HomeViewState(
    val result: List<Any> = listOf(""),
    val listaZawodnicy: MutableList<Any> = mutableListOf()
)

// definiowanie recordu czyli tabeli z danymi, w Kotlinie to się nazywa data class
data class RecordZawodnik(
    var nazwa_zawodnika: String = "",
    var wynik_zawodnika: Int = 0,
)

No i tyle jak do tej pory :-)
Tu jeszcze filmik jakby ktoś był ciekawy jak to wygląda w praktyce :-)

1 użytkowników online, w tym zalogowanych: 0, gości: 1