Stworzyłem listę obiektów gdzie można dodawać lub usuwać je z różnych klas. Jest jedna statyczna lista którą wyświetlam. I potrzebuje żeby każda zmiana od razu odświeżyła widok listy.
Automatycznie odświeżająca się lista
- Rejestracja: dni
- Ostatnio: dni
- Postów: 30
- Rejestracja: dni
- Ostatnio: dni
- Postów: 10231
Cześć @Kazik Kowalski!
Miło że jesteś na forum!
Kazik Kowalski napisał(a):
Stworzyłem listę obiektów gdzie można dodawać lub usuwać je z różnych klas. Jest jedna statyczna lista którą wyświetlam. I potrzebuje żeby każda zmiana od razu odświeżyła widok listy.
Pokaż kod jaki już napisałeś
- Rejestracja: dni
- Ostatnio: dni
- Postów: 30
class ListPage extends StatefulWidget {
const ListPage({super.key});
@override
State<ListPage> createState() => _ListPageState();
}
class _ListPageState extends State<ListPage> {
void _navigateDetails(ListItem item) => GoRouter.of(context).go('/itemslist/itemdetails', extra: item);
@override
Widget build(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
color: const Color(0xFFFF4B4B),
backgroundColor: const Color(0xFF26262A),
onRefresh: () async {
await Future.delayed(const Duration(seconds: 1));
setState(() {});
},
child: ListView.builder(
itemCount: MainModel.user.list.length,
itemBuilder: (context, index) {
final listItem = MainModel.user.list.elementAt(index);
return SizedBox(
height: 40,
child: Row(
children: [
Text(item.elapsedTime.inSeconds.toString()),
ElevatedButton(onPressed: () {_navigateDetails(listItem);}, child: const Text('Details'))
],
),
);
}
),
)
);
}
}
- Rejestracja: dni
- Ostatnio: dni
- Postów: 358
Powinieneś użyć setState() gdzie zmiana wartości ci odświeży cały widok automatycznie, tak ogólnie nie znam fluttera to ci nie powiem dokładnie jak to zrobić, jeśli zmodyfikujesz listę przez setState to ci się widok zaktualizuje po wykonaniu funkcji aktualizującej listę.
Pewnie da się to ręcznie też zrobić jak we frameworkach javascript typu react, gdzie ręcznie rerender gałęzi drzewa idzie zrobić, ale setState, po wykonaniu swojej funkcji wywołuje wewnętrzną funkcję rerenderowania, którą pójdzie namierzyć i potem jakoś w inny sposób wywołać jak się zagłębisz bardziej w to jak to działa. Ja akurat nie znam fluttera i nie wiem jak jedynie przez chatGPT mógłbym ci wygenerować jakiś kod, a pytałeś się chatGPT jak to rozwiązać bo to zaraz po wyszukiwarce w internecie następne miejsce do szukania odpowiedzi.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 30
.GodOfCode. napisał(a):
Powinieneś użyć setState() gdzie zmiana wartości ci odświeży cały widok automatycznie, tak ogólnie nie znam fluttera to ci nie powiem dokładnie jak to zrobić, jeśli zmodyfikujesz listę przez setState to ci się widok zaktualizuje po wykonaniu funkcji aktualizującej listę.
Pewnie da się to ręcznie też zrobić jak we frameworkach javascript typu react, gdzie ręcznie rerender gałęzi drzewa idzie zrobić, ale setState, po wykonaniu swojej funkcji wywołuje wewnętrzną funkcję rerenderowania, którą pójdzie namierzyć i potem jakoś w inny sposób wywołać jak się zagłębisz bardziej w to jak to działa. Ja akurat nie znam fluttera i nie wiem jak jedynie przez chatGPT mógłbym ci wygenerować jakiś kod, a pytałeś się chatGPT jak to rozwiązać bo to zaraz po wyszukiwarce w internecie następne miejsce do szukania odpowiedzi.
problem w tym że nie chec ręcznie odświeżać. Czasem potrzebuje uŻyć metoedy w której jest metoda która jest w klasie która nie jest wigetem i nie mogę dam użyć setState po to metoda z StatefilWidget. Myślałem i czymś w stylu ObservableCollection jak w .net. Ale nie znalazłem odpowiednika
- Rejestracja: dni
- Ostatnio: dni
- Postów: 358
Podasz jedną linijkę kodu, którą chcesz wykonać, z automatycznym rerenderingiem?
- Rejestracja: dni
- Ostatnio: dni
- Postów: 30
.GodOfCode. napisał(a):
Podasz jedną linijkę kodu, którą chcesz wykonać, z automatycznym rerenderingiem?
Potrzebuje automatycznego odświeżania ui po dodaniu lub usinięciu elementu więc oto dwie linijki po których ui powinno zostać odświeżone: MainModel.user.list.add(item) lub MainModel.user.list.remove(MainModel.user.items.firstWhere((i) => i.id == id))
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Jastrzębie-Zdrój
- Postów: 2180
To, że masz Add po stronie modelu nie znaczy, że się samo doda po stronie UI. Gdzie masz guzik z dodawaniem? W kodzie, który pokazałeś nie ma w ogóle takiej funkcjonalności, a piszesz o problemie odświeżania listy
- Rejestracja: dni
- Ostatnio: dni
- Postów: 30
AdamWox napisał(a):
To, że masz
Addpo stronie modelu nie znaczy, że się samo doda po stronie UI. Gdzie masz guzik z dodawaniem? W kodzie, który pokazałeś nie ma w ogóle takiej funkcjonalności, a piszesz o problemie odświeżania listy
jest w innej klasie
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Jastrzębie-Zdrój
- Postów: 2180
No spoko, kumam to, ale musisz jakąś akcje z UI wysłać jak chcesz coś dodać nie klikając palcem na ekranie?
- Rejestracja: dni
- Ostatnio: dni
- Postów: 10231
Kazik Kowalski napisał(a):
.GodOfCode. napisał(a):
Podasz jedną linijkę kodu, którą chcesz wykonać, z automatycznym rerenderingiem?
Potrzebuje automatycznego odświeżania ui po dodaniu lub usinięciu elementu więc oto dwie linijki po których ui powinno zostać odświeżone: MainModel.user.list.add(item) lub MainModel.user.list.remove(MainModel.user.items.firstWhere((i) => i.id == id))
Dobry problem do rozwiązania, i myślę że rozwiązanie jest tylko jedno - polimorfizm. W jakiś sposób Twoja część modelu musi wywołać kod w UI, żeby go odświeżyć. Kontrola przepływu musi iść model -> ui (alternatywa to jest polling, czyli UI co jakiś interwał sprawdza stan modelu i sam się odświeża, ale to jest słabe).
Normalnie wymagałoby to użycia kodu UI w modelu, gdyby nie dobrodziejstwa polimorfizmu. Dodaj polimorifczny kod w modelu który woła UI, np. ui.removeItemFromList(2) albo ui.syncListTo(list). Model nie musi wiedzieć dokładnie czy UI jest we flutterze, czy czymkolwiem innym.
Oczywiście znaczy to że musisz najpierw wywołać operację na modelu (żeby zrobić zmiane), a potem na UI (żeby odświeżyć UI), to jest niestety konieczne. Ale możesz to opakować w dodatkową klasę, na której zrobisz np. .remove(), .add(), etc. i ta opakowujaca klasa zaktualizuje model i UI; czyli dokładnie to co ObservableList robi.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 30
//inna klasa w której lista nie jest wyświetlana
void _saveItem()
{
_item.id = MainModel.generateId();
MainModel.user.list.add(_item);
GoRouter.of(context).pop(true);
}
void _dontSave() async => GoRouter.of(context).pop(true);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Save Item"),
),
body: Column(
children: [
Text(
_item.title.toString()
),
ElevatedButton(
onPressed: _dontSave,
child: const Text(
"Delete item"
)
),
ElevatedButton(
onPressed: _saveItem,
child: const Text(
"Save item"
)
)
],
),
);
}
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Jastrzębie-Zdrój
- Postów: 2180
Zamiast RefreshIndicator opakuj to w PopScope i tam zrób refresh listy itemów
PopScope(
canPop: false,
onPopInvoked : (didPop){
// logic
},
)
parametr didPop bierze się z GoRouter.of(context).pop(true);
- Rejestracja: dni
- Ostatnio: dni
- Postów: 30
AdamWox napisał(a):
Zamiast
RefreshIndicatoropakuj to wPopScopei tam zrób refresh listy itemówPopScope( canPop: false, onPopInvoked : (didPop){ // logic }, )parametr
didPopbierze się zGoRouter.of(context).pop(true);
Rozumiem że wystarczy wywołać tam setState puste w środku żeby widok się odświerzył? Jeśli tak to nie pomogło
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Jastrzębie-Zdrój
- Postów: 2180
A działało przy RefreshIndicator? Jeśli nie to pewnie ci się żaden item nie dodaje do listy, albo ją resetujesz. Debuguj, zrób sobie jakieś "print()" w odpowiednich miejscach i sprawdzaj co się pokazuje w konsoli. Pokaż też co robisz w MainModel.user.list.add(_item);
- Rejestracja: dni
- Ostatnio: dni
- Postów: 30
AdamWox napisał(a):
A działało przy
RefreshIndicator? Jeśli nie to pewnie ci się żaden item nie dodaje do listy, albo ją resetujesz. Debuguj, zrób sobie jakieś "print()" w odpowiednich miejscach i sprawdzaj co się pokazuje w konsoli. Pokaż też co robisz wMainModel.user.list.add(_item);
Działało. Dodam jeszcze że do nawigacji używam StatefulShellRoute jak by miało to coś zmienić. MainModel.user.list.add(_item); - to jest klasa w której jest statyczna instancja klasy User która ma statyczną listę gdzie jest wywołana podstawowa metoda add która jest wbudowana w język więc nie czego tu pokazywać.
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Jastrzębie-Zdrój
- Postów: 2180
No to już nie wiem jak mam pomóc. Tutaj masz przykład z dokumentacji jak to jest zrobione z PopScope
PopScope class
- Rejestracja: dni
- Ostatnio: dni
- Postów: 30
A może wie ktoś jak wykonać metodę na stronie za każdym razem gdy user do niej nawiguje?
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Miasto Spotkań
- Postów: 34
Zapewne przyda sie initState. Jak nawigujesz do strony to ona się wtedy tworzy i wywołać w tej metodzie możesz jakiś kod który inicjalizuje wszystko. Poczytaj proszę jak używać bloca. On separuję logikę od interfejsu na zasadzie event z interfejsu -> metoda w blocu która reaguje na event -> bloc robi update State i interfejs się zmienia wtedy.