Getx не работает должным образом с FutureBuilder для списка обновлений

#flutter #dart #flutter-futurebuilder #flutter-getx

#flutter #dart #flutter-futurebuilder #flutter-getx

Вопрос:

Я использую контроллер Getx в своем проекте. Я создал контроллер для FutureBuilder для отображения списка, но.Obs не установлен для функции Future. Я делюсь кодом.

 class PPHomeController extends GetxController {
  Future<List<PPProductRenterModel>> listNearProduct;

  // i want to set .Obs end of the "listNearProduct" but it's not working because of Future.  

  FetchNearProductList({@required int price}) async {
      listNearProduct = CallGetNearProducts();// Http API Result
  }
} 



{
  PPHomeController _homeController = Get.put(PPHomeController());

  Widget mainProductListView() {
return FutureBuilder<List<PPProductRenterModel>>
  (builder: (context, AsyncSnapshot<List<PPProductRenterModel>> projectSnap){
    if(!projectSnap.hasData){
      if(projectSnap.connectionState == ConnectionState.waiting){
        return Container(
          child: Loading(),
        );
      }
    }
   
    return ListView.builder(
        itemCount: projectSnap.data.length,
        itemBuilder: (context, index) {

          PPProductRenterModel model = projectSnap.data[index];
          PPPrint(tag: "CheckId",value: model.productId);
          return ProductMainItemRow(model);
        });

},
  future: _homeController.listNearProduct,);
  

Ответ №1:

Существует более чистый способ реализации списка в getX, не беспокоясь о приведении типов:

Создайте его экземпляр:

 final myList = [].obs;
  

Назначьте его:

 myList.assignAll( listOfAnyType );
  

(Ссылка) Ошибка Flutter при использовании List.value :

«значение» устарело и не должно использоваться. List.value устарел. используйте [yourList.assignAll(новый список)] . Попробуйте заменить использование устаревшего элемента заменой.


Подробный пример кода

ProductController.dart

 class ProductController extends GetxController {
  final productList = [].obs;

  @override
  void onInit() {
    fetchProducts();
    super.onInit();
  }

  void fetchProducts() async {
    var products = await HttpServices.fetchProducts();
    if (products != null) {
      productList.assignAll(products);
    }
  }
}
  

HttpServices.dart

 class HttpServices {
  static var client = http.Client();

  static Future<List<Product>> fetchProducts() async {
    var url = 'https://link_to_your_api';
    var response = await client.get(url);
    if (response.statusCode == 200) {
      return productFromJson(response.body);
    } else {
      return null;
    }
  }
}
  

product.dart

 class Product {
  Product({
    this.id,
    this.brand,
    this.title,
    this.price,
    ....
  });
  ....
}
  

Комментарии:

1. Это сработало для меня. Спасибо…

Ответ №2:

Сформируйте документы:

3 — Третий, более практичный, простой и предпочтительный подход, просто добавьте .obs в качестве свойства вашего значения:

final items = <String>[].obs;

Следуя этой инструкции, это должно сработать:

 final listNearProduct = Future.value(<PPProductRenterModel>[]).obs;
  

Например.:

 // controller
final list = Future.value(<String>[]).obs;

@override
  void onInit() {
    super.onInit();
    fetchList();
}

Future<List<String>> callApi() async {
  await Future.delayed(Duration(seconds: 2));
  return ['test'];
}

void fetchList() async {
  list.value = callApi();
}


// screen
@override
Widget build(BuildContext context) {
  return GetX<Controller>(
    init: Controller(),
    builder: (controller) {
      return FutureBuilder<List<String>>(
        future: controller.list.value,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            print(snapshot.data[0]); // Output: test
            return Text(snapshot.data[0]);
          } else if (snapshot.hasError) {
            return Text("${snapshot.error}");
          }

          // By default, show a loading spinner.
          return CircularProgressIndicator();
        },
      );
    },
  );
};
  

Комментарии:

1. Спасибо за ответ, но я получаю сообщение об ошибке ниже: — тип ‘Future<dynamic>’ не является подтипом типа ‘Future<List<PPProductRenterModel>>’

2. При тестировании приведенного выше кода я наткнулся на ту же ошибку. Это было вызвано Future callApi() async { вместо Future<List<String>> callApi() async { . Где возникает ваша ошибка?

3. Да, я пропустил установку «Future<List<PPProductRenterModel>>» в методе вызова API. Большое вам спасибо, у меня все работает нормально. Еще раз спасибо, Матиас

4. Отлично, добро пожаловать @Alpit Panchal. Поскольку это решило вашу проблему, не могли бы вы пометить ее как принятую.

5. Не могли бы вы помочь мне еще раз. Как удалить элемент из списка в описанном выше процессе. Спасибо @Matthias.

Ответ №3:

На самом деле вы никогда не звоните FetchNearProductList .

Вам нужно вызвать его в каком-то месте, желательно до того, как FutureBuilder использует это будущее.