[Flutter] 앱 실행시 데이터 가져오기

merci·2023년 4월 6일
0

Flutter

목록 보기
18/24
post-thumbnail

앱을 처음 실행했을 경우 로딩화면이 나오고 메인화면을 실행하도록 하는 방법을 알아보자

몇가지 방법이 있겠지만 구현한 2가지 방법을 소개한다.

FutureBuilder

void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}
class PostHomePage extends ConsumerWidget {
  const PostHomePage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context, WidgetRef ref) {
    PostController pc = ref.read(postController);
    return Scaffold(
      body: Column(
        children: [
          Expanded(
          
            // FutureBuilder
            child: FutureBuilder(
              future: pc.findPosts(),
              builder: (BuildContext context, AsyncSnapshot snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  if (snapshot.hasData) {
                    return _buildMainScreen( // 화면 그리기
                        snapshot.data);
                  } else {
                    return _buildErrorScreen(); //  실패한다면
                  }
                } else {
                  return _buildLoadingScreen(); // 로딩중 화면
                }
              },
            ),
          ),
          // buildButton(pc),
        ],
      ),
    );
  }

future 속성에는 Future<>를 리턴하는 메소드를 넣는다.
비동기처리를 하므로 완료가 되면 future 다음 라인부터 다시 실행된다.

AsyncSnapshot

AsyncSnapshotFutureBuilderStreamBuilder와 함께 사용되는 클래스로, 비동기 작업의 결과를 포함하고 이에 대한 상태 정보를 제공한다.
snapshot.data를 통해 비동기 작업의 결과를 제공하고
snapshot.connectionState를 통해 현재 상태 정보를 제공한다.

none: 아직 비동기 작업이 수행되지 않은 상태
waiting: 비동기 작업이 실행 중이며 결과를 기다리고 있는 상태
active: 스트림에서 이벤트가 발생하고 있는 상태
done: 비동기 작업이 완료되었으며, snapshot.data에서 결과가 사용 가능한 상태

  Widget _buildMainScreen(List<Post> posts) {
    return ListView.builder(
      itemCount: posts.length,
      itemBuilder: (context, index) {
        return Column(
          children: [
            Container(
              decoration: BoxDecoration(color: Colors.green[100]),
              height: 100,
              child: ListTile(
                leading: Text("${posts[index].id}"),
                title: Text("${posts[index].title}"),
              ),
            ),
            Divider(),
          ],
        );
      },
    ); 
  }
  
  Widget _buildErrorScreen() {
    return Container(
      child: Center(
        child: Text("실패"),
      ),
    ); 
  }

  Widget _buildLoadingScreen() {
    return Container(
      child: Center(child: CircularProgressIndicator())
    ); 
  }
}


Consumer

ProviderScope 지정은 위와 같다.
변화가 필요한 부분만 Consumer로 감싼다.
builder속성을 가지면 메소드를 호출할 수 있다.

class PostHomePage extends StatelessWidget {
  const PostHomePage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: Consumer(
              builder: (context, ref, child) {
    			PostController pc = ref.read(postController);
                pc.findPosts();  
                PostHomePageModel? pm = ref.watch(postHomePageProvider);
                return pm != null
                    ? buildListView(pm.posts)
                    : Center(child: CircularProgressIndicator());
              },
            ),
          ),
        ],
      ),
    );
  }

  Widget buildListView(List<Post> posts) {
    return ListView.builder(
      itemCount: posts.length,
      itemBuilder: (context, index) {
        return Column(
          children: [
            Container(
              decoration: BoxDecoration(color: Colors.green[100]),
              height: 100,
              child: ListTile(
                leading: Text("${posts[index].id}"),
                title: Text("${posts[index].title}"),
              ),
            ),
            Divider(),
          ],
        );
      },
    );
  }
}
profile
작은것부터

0개의 댓글