SharedPreferences prefs 초기화 시기 문제
제 식대로 코드를 수정했습니다.
MultiProvider로 CatService(prefs)를 호출하는 시기와 prefs를 초기화하는 시기가 비슷하여, 문제가 생겼습니다. "CatService 내부에서 async로 초기화하게 만들고
생성자에서 바로 prefs를 쓰지 않도록 수정"하는 방식을 추천하는데 그게 맞을까요? 에러 메세지는 다음과 같습니다 [ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: PlatformException(channel-error, Unable to establish connection on channel: "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesApi.getAll"., null, null)
주요 코드
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences prefs = await SharedPreferences.getInstance();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => CatService(prefs)),
],
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
theme: ThemeData(textTheme: GoogleFonts.getTextTheme('Sunflower')),
);
}
}
class CatService extends ChangeNotifier {
SharedPreferences prefs;
List<String> catImages = [];
List<String> favoriteImages = [];
CatService(this.prefs) {
getRandomCatImages();
favoriteImages = prefs.getStringList("favorites") ?? [];
}
void getRandomCatImages() async {
Response result = await Dio().get(
'https://api.thecatapi.com/v1/images/search?limit=10&mime_types=jpg',
);
for (var i = 0; i < result.data.length; i++) {
catImages.add(result.data[i]["url"]);
}
notifyListeners();
}
void toggleFavoriteImages(String image) {
if (favoriteImages.contains(image)) {
favoriteImages.remove(image);
} else {
favoriteImages.add(image);
}
prefs.setStringList("favorites", favoriteImages);
notifyListeners();
}
}
<전체 코드>
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences prefs = await SharedPreferences.getInstance();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => CatService(prefs)),
],
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
theme: ThemeData(textTheme: GoogleFonts.getTextTheme('Sunflower')),
);
}
}
class CatService extends ChangeNotifier {
SharedPreferences prefs;
List<String> catImages = [];
List<String> favoriteImages = [];
CatService(this.prefs) {
getRandomCatImages();
favoriteImages = prefs.getStringList("favorites") ?? [];
}
void getRandomCatImages() async {
Response result = await Dio().get(
'https://api.thecatapi.com/v1/images/search?limit=10&mime_types=jpg',
);
for (var i = 0; i < result.data.length; i++) {
catImages.add(result.data[i]["url"]);
}
notifyListeners();
}
void toggleFavoriteImages(String image) {
if (favoriteImages.contains(image)) {
favoriteImages.remove(image);
} else {
favoriteImages.add(image);
}
prefs.setStringList("favorites", favoriteImages);
notifyListeners();
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Consumer<CatService>(
builder: (context, catService, child) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.yellow,
title: Center(child: Text("랜덤 고양이")),
actions: [
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => FavoritePage()),
);
},
icon: Icon(Icons.favorite, color: Colors.red),
),
],
),
body: SafeArea(
child: Container(
color: Colors.brown.shade100,
child: GridView.count(
crossAxisCount: 2,
mainAxisSpacing: 8,
crossAxisSpacing: 8,
padding: EdgeInsets.all(8),
children: List.generate(catService.catImages.length, (index) {
String catImage = catService.catImages[index];
return Stack(
children: [
Positioned.fill(
child: GestureDetector(
onTap: () {
catService.toggleFavoriteImages(catImage);
},
child: Image.network(catImage, fit: BoxFit.cover),
),
),
Positioned(
right: 0,
bottom: 0,
child: Icon(
Icons.favorite,
size: 40,
color: catService.favoriteImages.contains(catImage)
? Colors.pink.shade200
: Colors.transparent,
),
),
],
);
}),
),
),
),
);
},
);
}
}
class FavoritePage extends StatelessWidget {
const FavoritePage({super.key});
@override
Widget build(BuildContext context) {
return Consumer<CatService>(
builder: (context, catService, child) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.yellow,
title: Center(child: Text("좋아")),
),
body: SafeArea(
child: GridView.count(
crossAxisCount: 2,
mainAxisSpacing: 8,
crossAxisSpacing: 8,
padding: EdgeInsets.all(8),
children: List.generate(catService.favoriteImages.length, (
index,
) {
String catImage = catService.favoriteImages[index];
return Stack(
children: [
Positioned.fill(
child: GestureDetector(
onTap: () {
catService.toggleFavoriteImages(catImage);
},
child: Image.network(catImage, fit: BoxFit.cover),
),
),
Positioned(
right: 0,
bottom: 0,
child: Icon(
Icons.favorite,
size: 40,
color: catService.favoriteImages.contains(catImage)
? Colors.pink.shade200
: Colors.transparent,
),
),
],
);
}),
),
),
);
},
);
}
}
Câu trả lời 2
1
안녕하세요.
첨부해 주신 에러 메세지는 async와 관련이 없고, SharedPreferences 패키지를 설치하신 뒤 Hot Reload 방식으로 실행할 때 나오는 에러로 보입니다.
VSCode에서 현재 실행중인 연결을 종료했다가 다시 시작하시면 해결 될 것으로 보입니다. 만약 그렇게 해도 문제가 해결되지 않으신다면 문제 재현 방법을 공유 부탁드립니다.
감사합니다 🙂
0
안녕하세요, 인프런 AI 인턴입니다. kindjin12님.
질문해 주신 내용은 SharedPreferences 초기화와 관련된 문제로 보입니다. SharedPreferences가 비동기적으로 초기화되기 때문에, 클래스 생성자에서 바로 사용하려고 할 때 문제가 발생할 수 있습니다.
현재 코드에서는 SharedPreferences를 동기적으로 얻어와 CatService에 전달하므로, prefs가 초기화되기 전에 생성자를 호출하여 문제가 발생할 수 있습니다. 이를 해결하기 위해서는 SharedPreferences를 설정하는 시점을 비동기로 처리하는 것이 좋습니다. 이는 Future와 async를 통해 다룰 수 있습니다.
CatService에서 SharedPreferences를 비동기로 초기화하는 방법은 다음과 같이 수정할 수 있습니다:
prefs를 생성자에서 직접 설정하지 않고 비동기 메서드로 초기화합니다.
- 초기화가 완료될 때까지 기다린 후 나머지 로직을 수행합니다.
아래 예제를 통해 SharedPreferences의 비동기 초기화를 확인하실 수 있습니다:
class CatService extends ChangeNotifier {
SharedPreferences? prefs;
List<String> catImages = [];
List<String> favoriteImages = [];
CatService() {
initializePreferences();
getRandomCatImages();
}
Future<void> initializePreferences() async {
prefs = await SharedPreferences.getInstance();
favoriteImages = prefs?.getStringList("favorites") ?? [];
notifyListeners();
}
void getRandomCatImages() async {
Response result = await Dio().get(
'https://api.thecatapi.com/v1/images/search?limit=10&mime_types=jpg',
);
for (var i = 0; i < result.data.length; i++) {
catImages.add(result.data[i]["url"]);
}
notifyListeners();
}
void toggleFavoriteImages(String image) {
if (favoriteImages.contains(image)) {
favoriteImages.remove(image);
} else {
favoriteImages.add(image);
}
prefs?.setStringList("favorites", favoriteImages);
notifyListeners();
}
}
이렇게 초기화가 비동기로 처리되어 prefs가 준비된 후에 사용될 수 있습니다. 이로 인해 코드 실행 시점에 발생할 수 있는 문제를 방지할 수 있습니다.
참고 링크를 첨부합니다:
- Flutter에서 SharedPreferences 사용하기 - 유사한 질문과 답변
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
회차마다 있는 실습
1
38
2
user-not-found, wrong-password 코드가 더 이상 반환되지 않습니다
1
70
2
index로 삭제하게 되면, index가 고정되어 있으니 문제가 발생하지 않나요?
1
62
2
API 사이트가 안되네요
1
77
2
잘 되다가 sharedPreferences부터 에러
1
63
2
기존의 프로젝트
1
63
2
I/O라는 창이 윈도우에서는 없어요
1
61
2
수강 기간 연장 부탁드립니다.
1
59
2
설정 질문
1
54
2
수강 기간 연장 신청 요청드립니다.
1
49
2
수강기간 연장 부탁드립니다.
1
54
2
수강기간 연장 부탁드립니다.
1
55
2
수강기간 연장 부탁 드립니다.^^
1
66
3
강의계획 문의
1
63
2
안녕하세요. 강의 연장 문의드립니다..
1
72
2
수강기간 연장 부탁드립니다!
1
78
2
2회차 StatefulWidget 예제 dartpad 코드와 영상에서의 코드가 다릅니다.
2
95
2
dartpad 에러
1
103
2
cmd에 flutter doctor 입력하면 바로 튕겨버립니다...
1
108
2
애뮬레이터 실행시 무한로딩
1
132
2
저는 강사님 처럼 화면이 안뜨는데 머테리얼 버전이 다른걸까요??
1
64
2
수강기간 연장 부탁드립니다!
1
58
2
수강기간 연장 부탁드립니다.
1
67
2
에뮬레이터 실행 오류
1
119
3

