Never give up

Flutter 2.0 - Hive fixed length list problem and solution 본문

Flutter

Flutter 2.0 - Hive fixed length list problem and solution

대기만성 개발자 2021. 3. 31. 19:51
반응형

이전에 Migration을 하면서 fixed length list에 대한 문제에 대해 말씀드린적 있습니다

(링크 : devmemory.tistory.com/55)

 

그래서 issue에 올려보니 제작자가 다른 소리만 하고 해결할 의지가 별로 없어보였습니다..

 

먼저 간단한 예제 코드와 설명으로 시작해보겠습니다

 

Splash

class TestSplash extends StatefulWidget {
  @override
  _TestSplashState createState() => _TestSplashState();
}

class _TestSplashState extends State<TestSplash> {
  @override
  void initState() {
    super.initState();
    init();
  }

  void init() async {
    await Hive.initFlutter();

    await Hive.openBox('test');

    ListData data = ListData();
    await data.init();

    Navigator.push(
        context,
        MaterialPageRoute(
            builder: (_) => ListTest(title: 'List test example', data: data)));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold();
  }

main

class ListTest extends StatefulWidget {
  final String title;
  final ListData data;

  ListTest({required this.data, required this.title});

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

class _ListTestState extends State<ListTest> {
  late ListData _data;

  @override
  void initState() {
    super.initState();
    _data = widget.data;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: ListView.builder(
          itemCount: _data.list.length,
          itemBuilder: (_, index) {
            String title = _data.list[index];
            return Card(
              child: ListTile(
                leading: CircleAvatar(child: Text(index.toString())),
                title: Text(title),
                onTap: () {
                  setState(() {
                    _data.removeData(index);
                  });
                },
              ),
            );
          }),
      floatingActionButton: FloatingActionButton(
          child: Icon(Icons.edit),
          onPressed: () {
            showDialog(
                context: context,
                builder: (_) => AlertDialog(
                        title: Text('Add'),
                        content: TextField(onChanged: (value) {
                          _data.title = value;
                        }),
                        actions: [
                          TextButton(
                              onPressed: () {
                                _data.title = '';
                                Navigator.pop(context);
                              },
                              child: Text('Cancel')),
                          TextButton(
                              onPressed: () {
                                setState(() {
                                  _data.addData();
                                });
                                Navigator.pop(context);
                              },
                              child: Text('Confirm')),
                        ]));
          }),
    );
  }
}

data

class ListData {
  List<String> list = [];
  String title = '';
  late Box box;

  Future<void> init() async {
    box = Hive.box('test');
    list = box.get('list') ?? [];
  }

  void addData() {
    list.add(title);
    box.put('list', list);
  }

  void removeData(int index) {
    list.removeAt(index);
    box.put('list', list);
  }
}

 

간단한 ListView와 Hive를 이용한 예제입니다

 

2.0 이전 버전에서는 문제없이 잘 작동하는 코드입니다

 

그런데 2.0 업데이트된 이후로 Hive도 null safety버전으로 올라가면서

 

코드에 문제가 생긴거 같습니다

 

이대로 작동하면 처음에는 잘 작동합니다만

 

재부팅 후 리스트를 조작해보면 이런 에러들이 환영(?)을 해줄겁니다

Unsupported operation: Cannot add to a fixed-length list

Unsupported operation: Cannot remove from a fixed-length list

에러를 보면 알겠듯이 크기가 고정된 list를 변경할 때 발생하는 문제입니다

 

이번에 업데이트 되면서 List를 box에서 가져올 때 Fixed length List 형태로 가져오는 문제가 있습니다

 

그래서 새로운 버전으로 업데이트 될 때, 이 부분도 업데이트 해줄줄 알았는데 안해주더군요..

 

그래서 임시방편으로 해결방법을 고민해보게 되었고

 

필자가 생각하기에 가장 합리적이라고 생각한 방식은 reference 대신 value로 저장하는것이였고

 

테스트 해보니 정상적으로 작동이 되었습니다

Future<void> init() async {
    box = Hive.box('test');
    //list = box.get('list') ?? []; 이거 대신
    list.addAll(box.get('list') ?? []); // 이거
  }

사실 이것도 제작자가 조금만 더 신경써주면 해결되는 문제인데

 

조금 아쉬운거 같습니다..

반응형
Comments