List<Photo> _photos = [];
V2에서 home_screen에서 Photo를 담는 부분이 포함되어 ui와 분리가 되지 않은 상태였습니다.
최대한 screen(UI)와 model 및 controller를 분리화 시켜야 합니다.
변경 예)
InheritedWidget 은 불변값만 받을 수 있으므로, StreamController을 이용
class PhotoProvider extends InheritedWidget {
final PixabayApi api;
final _photoScreamController = StreamController<List<Photo>>()..add([]); //기존 photo를 담아주는 데이터를 없에고 controller로 대체합니다. 최초에는 데이터가 없으므로 circulr가 보이는데 add를 추가하여 빈 값을 출력하게 합니다.
Stream<List<Photo>> get photoStream => _photoScreamController.stream;
PhotoProvider({Key? key, required this.api, required Widget child})
: super(key: key, child: child);
static PhotoProvider of(BuildContext context){ //위젯트리의 정보를 가지고 있는 객체
final PhotoProvider? result = context.dependOnInheritedWidgetOfExactType<PhotoProvider>(); // 가장 가까운 PhotoProvider를 찾아서 return
assert(result != null,'No PixabayApi found in context'); //null 이면 문구가 나옵니다. 널이 아니다라는 검증
return result!;
}
Future<void> fetch(String query) async {
final result = await api.fetch(query);
_photoScreamController.add(result);
}
@override //이전 상태와 현재 상태가 다른지 확인하는 위젯
bool updateShouldNotify(PhotoProvider oldWidget) {
return oldWidget.api != api;
}
}
변경 예)
기존
Expanded(
child: GridView.builder(
padding: EdgeInsets.all(16.0),
shrinkWrap: true,
itemCount: _photos.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 16,
mainAxisSpacing: 16, //간격조절
),
itemBuilder: (context, index) {
final photo = _photos[index];
return PhotoWidget(photo: photo);
},
),
)
],
),
);
}
}
변경
값이 변경된 값을 적용하기 위해 StreamBuilder를 감싸줍니다.
snapshot을 검증을 통하는데 최초에는 검색 하지 않은 이상 로딩표시가 발생합니다. PhotoProvider 에 add 위젯에 빈 리스트값을 보여줍니다.
StreamBuilder<List<Photo>>(
stream: photoProvider.photoStream,
builder: (context, snapshot) {
if (!snapshot.hasData){
return const CircularProgressIndicator();
}
final photos = snapshot.data!;
return Expanded(
child: GridView.builder(
padding: EdgeInsets.all(16.0),
shrinkWrap: true,
itemCount: photos.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 16,
mainAxisSpacing: 16, //간격조절
),
itemBuilder: (context, index) {
final photo = photos[index];
return PhotoWidget(photo: photo);
},
),
);
}
)
],
),
StreamBuilder를 이용하면서 리스트에 있는 업데이트 되는 값을 가져오게 되면, 코드가 길어지게 되고 준비 과정이 InheritedWidget 포함해서 많아지게 되는 이슈가 있습니다.
그렇기 때문에 상태관리 패키지를 이용해야 합니다.