Flutter: как использовать функцию result как var в нескольких классах, не повторяя функцию - PullRequest
1 голос
/ 18 марта 2020

Я получаю несколько страниц и зависимый контент из API, используя несколько выборок. Здесь getClass() и getValue() вызывают API из другого класса, возвращая будущее.

List<dynamic> pIds, ps;
apiStart() async {
  pageIds = new List();
  siteCls = await _baseApi.getClass(siteCName);
  siteCId = siteCls.data.classId.toString();

  pageCls = await _baseApi.getClass(pageCName);
  pageCId = pageCls.data.classId.toString();

  siteIns = await _baseApi.getValue(siteCId);
  pageIns = await _baseApi.getValue(pageCId);

  pageIds = getPageIds();
  pages = getPagesData();
}

List getPageIds() {
  //Doing some work here
  return pIds;
}

List getPagesData() {
  //Doing some work here
  return ps;
}

Теперь я хочу получить доступ к переменным, таким как "страницы", из других / нескольких классов без повторения функций. Как я могу это сделать?

Обновление:

Это пример кода. Он возвращает «добро пожаловать test1!». Когда я удаляю content = "test1"; из apiStart(), возвращается «добро пожаловать!». Что-то не так с использованием await?

class AppData {
  factory AppData() {
    return _singleton;
  }
  static final AppData _singleton = AppData._internal();
  AppData._internal() {
    print("Instance created App-Data");
  }

  BaseApi _baseApi = new BaseApi();

  var content = "hi";
  Future body() {
    return Future.value(content);
  }

  void apiStart() async{
    content = "test1";//OK when I put content here 
    print(content);

    _ids = await _baseApi.fetchIds();
    //Does not change when I put content here
    //I need to use await because I need ids for next function
    content = "test2";  
    print(content);

    //Doing some work with result and get ids as list
    List id = idList();

    _pages = await _baseApi.fetchPages(id[0]);
    //Doing some work with result and get page content
    contents = contentList();
  }
}

Если я сделаю что-то вроде ниже, он возвращает «test2». Но я не знаю, как проверить, закончилась ли работа; Должен ли я добавить логическое значение var в конце функции и проверять его каждые секунды? Это эффективно?

Future body() {
  return Future.delayed(Duration(seconds: 10)).then((value) => content);
}

Где я запускаю синглтон

void main() {
  runApp(MyApp());
  AppData().apiStart();
}

Я показываю часть результатов следующим образом:

class ContentWidget extends StatefulWidget {
  ContentWidget({Key key}) : super(key: key);

  @override
  _ContentWidgetState createState() => _ContentWidgetState();
}

class _ContentWidgetState extends State<ContentWidget> {
  Future<dynamic> futureContent;

  @override
  void initState() {
    super.initState();

    futureContent = AppData().body();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<dynamic>(
      future: futureContent,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Text("Welcome ${snapshot.data}!", style: plainTextStyle);
        } else {
          //return Text("Welcome ${snapshot.error}!", style: plainTextStyle);
        }
        // By default, show a loading spinner.
        return CircularProgressIndicator();
      },
    );
  }
}

1 Ответ

0 голосов
/ 19 марта 2020

Вы можете использовать шаблон Singleton для создания класса обслуживания: он дает вам доступ к этому классу из любого места в вашем коде.

Не используйте его чрезмерно, потому что он может превращается в очень грязную глобальную нехватку инкапсуляции.

Примечание: это огромное упрощение, но оно будет работать. Прочитайте aroudn singletons и сервисы, чтобы узнать больше.

class ApiService {
  // next 5 lines is a typical singleton pattern
  static ApiService _singleton;
  factory ApiService() {
    return _singleton ??= new ApiService._internal();
  }
  ApiService._internal();

  //here you'll keep your data
  List<dynamic> pageIds, pages; //store your data in these variables

  //run this on the beginning of your app to get your data. Don't forget this!
  void apiStart() async {
    // your code here where you hit the API and get all your data,
    // eg methods getPageIdsFromAPI and getPagesDataFromAPI that you need to write. They return your data
    //    pageIds = getPageIdsFromAPI();
    //    pages = getPagesDataFromAPI();
  }
}

тогда из любого места в вашем коде вы можете получить доступ к переменным и функциям из этого класса

ApiService().pageIds
ApiService().pageIds.length
ApiService().pageIds.contains(some_id)

--- EDIT ---

вам нужно решить, когда произойдет ожидание. Либо вы ждете данные перед тем, как отобразить экран, либо вы показываете экран в режиме ожидания / ожидания (как это делает Facebook), а затем ждете.

, чтобы сделать второй:

@override
void initState() { 
  WidgetsBinding.instance.addPostFrameCallback((_) { 
    futureContent = await AppData().body();
    setState(() { 
      // refresh whatever changed. it's a good practice to specify what 
    });
  });
}
...