본문 바로가기
삽질하는 개발자 hashblown

프론트엔드 개발자의 TIL #014

by hashblown 2019. 11. 21.

TIL #014

191121 목

 


오늘 배운 점

<Flutter>

1. Shared Preferences

  • key-value 형태의 데이터를 디스크에 저장해서 사용하는 방법..이라고 한다. 앱을 종료한 후 다시 시작해도 shared preference로 관리되는 데이터는 이전에 앱을 실행했을 때의 값을 저장해서 불러오기 때문에 저장된 데이터 값을 출력한다.
  • Flutter의 Hello World인 increment counter를 shared preference로 적용한 예시를 확인해보았다.
//@pubspec.yaml

dependencies:
	shared_preferences:


import 'package:shared_preferences/shared_preferences.dart';

// shared preference 값 얻기
final prefs = await SharedPreferences.getInstance();

// 데이터 저장
prefs.setInt('counter', counter);

// counter key에서 데이터 읽기. 존재하지 않으면 0 반환
final counter = prefs.getInt('counter') ?? 0;

// 데이터 삭제
prefs.remove('counter');

//예시
const MethodChannel('plugins.flutter.io/shared_preferences')
  .setMockMethodCallHandler((MethodCall methodCall) async {
    if (methodCall.method == 'getAll') {
      return <String, dynamic>{}; // set initial values here if desired
    }
    return null;
  });
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  @override
  void initState() {
    super.initState();
    _loadCounter();
  }

  //카운터 값 불러오기
  _loadCounter() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      _counter = (prefs.getInt('counter') ?? 0);
    });
  }

  //클릭할 때마다 카운터 숫자 증가
  _incrementCounter() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      _counter = (prefs.getInt('counter') ?? 0) + 1;
      prefs.setInt('counter', _counter);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
  • 아래는 조금 더 응용하여 로그인이 필요할 때 사용자의 ID와 패스워드 등을 기억하는 기능을 구현한 예시다.
SharedPreferences sharedPreferences;

@override
void initState() {
	super.initState();
    getCredential();
}


_onChanged(bool value) async {
	sharedPreferences = await SharedPreferences.getInstance();
	setState(() {
    	checkValue = value;
    	sharedPreferences.setBool("check", checkValue);
    	sharedPreferences.setString("username", username.text);
    	sharedPreferences.setString("password", password.text);
    	sharedPreferences.commit();
    	getCredential();
  	});
}

getCredential() async {
	sharedPreferences = await SharedPreferences.getInstance();
    setState(() {
    	checkValue = sharedPreferences.getBool("check");
    	if (checkValue != null) {
        	if (checkValue) {
        		username.text = sharedPreferences.getString("username");
        		password.text = sharedPreferences.getString("password");
        	} else {
          		username.clear();
          		password.clear();
          		sharedPreferences.clear();
        	}
      	} else {
        	checkValue = false;
      	}
    });
}

2. Performance profiling

  • 나중에 배포 단계가 되었을 때, 아이템 목록을 스크롤링하며 사용자 경험에 불편함이 없는지 테스트를 할 때 이런 식으로 테스트 코드를 작성한다고 한다.
  • 우선 이런식으로 스크롤링 테스트 파일을 작성하고,
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp(
    items: List<String>.generate(10000, (i) => "Item $i"),
  ));
}

class MyApp extends StatelessWidget {
  final List<String> items;

  MyApp({Key key, @required this.items}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final title = 'Long List';

    return MaterialApp(
      title: title,
      home: Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: ListView.builder(
          // Add a key to the ListView. This makes it possible to
          // find the list and scroll through it in the tests.
          key: Key('long_list'),
          itemCount: items.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(
                '${items[index]}',
                // Add a key to the Text widget for each item. This makes
                // it possible to look for a particular item in the list
                // and verify that the text is correct
                key: Key('item_${index}_text'),
              ),
            );
          },
        ),
      ),
    );
  }
}
  • 성능을 기록하는 파일을 생성한다.
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';

void main() {
  group('Scrollable App', () {
    FlutterDriver driver;

    setUpAll(() async {
      driver = await FlutterDriver.connect();
    });

    tearDownAll(() async {
      if (driver != null) {
        driver.close();
      }
    });

    test('verifies the list contains a specific item', () async {
      final listFinder = find.byValueKey('long_list');
      final itemFinder = find.byValueKey('item_50_text');

      // 성능 기록
      final timeline = await driver.traceAction(() async {
        await driver.scrollUntilVisible(
          listFinder,
          itemFinder,
          dyScroll: -300.0,
        );

        expect(await driver.getText(itemFinder), 'Item 50');
      });

      // 좀 더 읽고 이해하기 쉽게 TimelineSummary로 전환
      final summary = new TimelineSummary.summarize(timeline);

      // disk에 저장
      summary.writeSummaryToFile('scrolling_summary', pretty: true);

      // json 형태로 timeline을 disk에 작성. chrome://tracing 에서 열 수 있는 형태
      summary.writeTimelineToFile('scrolling_timeline', pretty: true);
    });
  });
}

내일 배울 점

<Flutter>

1. 다중 이미지와 텍스트를 함께 POST할 수 있는 글 작성 기능을 구현할 예정이다.

  • 예전에 실습으로 성공했던 이미지 3장 MultipartFile로 한번에 보내기와 TextEditingController로 TextField에 작성된 String을 handleSubmit 함수로 http.post 요청 보내기 기능을 활용하면 될 것 같다.

2. devops 과정에 필요한 내용들을 숙지할 필요가 있을 것 같아서 더 알아봐야겠다.

더보기

- 요즘은 과제하느라 Flutter보다 R을 더 많이 쓰고 있다 하하...

- TIL을 쓸 물리적인 시간이 너무 부족하지만 최대한 짬을 내서 기록해야 겠다.

 

댓글