이제 외부 라이브러리를 이용하는 방법을 배울 것이다.
우선, pub.dev > image_picker를 선택해보자.
나의 경우 여기서 에러가 생겼는데, command로 "$ flutter pub add image_picker"를 하는 과정에서 다음과 같은 에러가 발생했다
Building with plugins requires symlink support.
Please enable Developer Mode in your system settings. Run
start ms-settings:developers
to open settings.
https://stackoverflow.com/questions/68089177/flutter-building-with-plugins-requires-symlink-support
stackoverflow에서 나와 같은 문제를 겪고 있는 분을 찾았다. 윈도우11의 경우는 개발자모드를 켜야 하나보다
시스템 > 개발자 모드로 들어가서 개발자 모드를 켜주자.
성공적으로 빌드가 완료되었다.
우선 이미지 피커를 사용하기 위해서는 해당 라이브러리를 어떻게 사용하는지 알 필요가 있다.
https://pub.dev/packages/image_picker 해당 사이트의 read.me를 잘 읽어보면 된다.
아무래도 라이브러리는 계속 버전이 바뀌다 보니, 버전이 바뀌면 사용하는 방법 자체가 바뀔 수 있다.
그러므로 라이브러리 공식 사이트에서 read.me, example을 통해 적용하는 방법을 스스로 익히는 것을 습관화 하는 것이 좋다!
나도 공부하는 입장이니 여기에 과정을 자세하게 풀어보도록 하겠다.
final ImagePicker picker = ImagePicker();
// Pick an image.
final XFile? image = await picker.pickImage(source: ImageSource.gallery);
// Capture a photo.
final XFile? photo = await picker.pickImage(source: ImageSource.camera);
// Pick a video.
final XFile? galleryVideo =
await picker.pickVideo(source: ImageSource.gallery);
// Capture a video.
final XFile? cameraVideo = await picker.pickVideo(source: ImageSource.camera);
// Pick multiple images.
final List<XFile> images = await picker.pickMultiImage();
// Pick singe image or video.
final XFile? media = await picker.pickMedia();
// Pick multiple images and videos.
final List<XFile> medias = await picker.pickMultipleMedia();
우선 readme의 example을 통해 사용법을 익혀보도록 하자.
위의 과정을 통해 빌드가 완료되었으므로 해당 방법을 사용해서 이미지 피커를 사용할 수 있다.
final ImagePicker picker = ImagePicker();
우선 이 코드를 통해 ImagePicker를 사용할 준비를 마친다.
final XFile? image = await picker.pickImage(source: ImageSource.gallery);
이를 통해 갤러리에서 이미지를 가져올 수 있도록 하는 것이다. await는 늦게 값을 받아오는 경우 사용하는 것이다.
XFile의 경우 이미지 피커에서 사용하는 객체이다. ?는 NULL이 들어올 수 있으므로 nullable을 붙여둔 것이다. 자세한건 nullable참고
https://pub.dev/packages/image_picker/example
이외의 main.dart에서 사용한 example은 다음을 참고하면 된다.
나의 경우는 클론 코딩에 사용해야 할 기본 기능들은 전부 익혔으니 일단 넘어가도록 한다.
복잡한 로직을 가진 경우, 한 화면에서 정의하는 것 보단 별도의 class로 빼는 것이 좋다. 그게 재 사용성도 좋고 나중에 코드 공유할 때도 편하다.
그러므로 우선 이미지 피커를 사용하기 위한 부분은 따로 CreateModel로 정의해서 새로운 class를 만들도록 하겠다.
ElevatedButton(
onPressed: () async {
_image = await model.getImage();
//화면 갱신 코드
setState(() {});
},
child: const Text('이미지 선택'),
),
다음과 같이 새로운 파일을 생성하였다.
import 'dart:io';
import 'package:image_picker/image_picker.dart';
class CreateModel{
final _picker = ImagePicker();
Future<File?> getImage() async {
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
if(image == null){ //image가 null이면 null을 return 하도록 File?에 null이 들어 올 수도 있다.
return null;
}
return File(image.path);
}
}
Future<File?> getImage() async {
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
if(image == null){ //image가 null이면 null을 return 하도록 File?에 null이 들어 올 수도 있다.
return null;
}
return File(image.path);
}
Future
Flutter에서의 Future는 비동기 작업을 수행할 때 사용되는 객체이다. Future는 작업이 완료될 때까지 기다리고 결과를 반환하는 데 사용된다. 예를 들어, 네트워크 호출, 파일 읽기 또는 다른 비동기 작업을 수행할 때 Future를 사용할 수 있다.
?을 넣어줬으므로, null이 반환될 수도 있다. 그럴 경우를 대비하기 위해 null 검사 및 return을 넣어준다.
해당 이미지의 path를 받아오면 file로 변환이 가능하다.
XFILE의 경우 이미지 피커에서만 사용하는 객체이기 때문에 File로 묶어서 형태를 바꿔준다.
final model = CreateModel();
...
ElevatedButton(
onPressed: () async {
_image = await model.getImage();
//화면 갱신 코드
setState(() {});
},
child: const Text('이미지 선택'),
),
if (_image != null)
Image.file(
_image!,
width: 300,
),
이제 Elavated 버튼에 이를 적용해줄 것이다.
위에서 CreateModel을 가져왔다.
이 model에서 만들었던 getImage()를 await로 가져온다.
그 다음, 상태 변화를 나타내는 setState를 써야한다.
setState안에 _image를 넣으면 되지 않느냐..하고 생각할 수 있지만
setState의 경우 await를 넣으면 사용해야 하는 async를 사용핳 수 없기 때문에, 밖에 정의해준다.
if (_image != null)
Image.file(
_image!,
width: 300,
),
image가 null이 아닐 경우, 선택한 이미지 파일이 나와야 한다.
Image.file()을 통해 파일 이미지를 꺼낼 수 있다.
그러나 _image의 경우 file이 아닌 file?라서 null을 가질 수 있다.
그러므로 null이 아님을 증명하는 !를 붙여서 file로 쓸 수 있도록 해준다.