라벨이 개발인 게시물 표시

flutter 방향 고정. 가로, 세로.

아래 한 줄이면 어플의 방향을 고정할 수 있습니다. SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); 방향 옵션 입니다.. enum DeviceOrientation { portraitUp , landscapeLeft , portraitDown , landscapeRight , }

flutter license 표시 페이지.

손쉽게 어플에서 표시할 라이센스를 표시합니다.. pubspec.yaml 파일 dependencies 에 추가한 라이브러리도 자동으로 표시합니다. 아래 한 줄만 넣으면 됩니다. Navigator.of(context).push(MaterialPageRoute(builder: (_) => const LicensePage())); 만약 수동으로 추가한 추가 라이센스가 있다면 아래와 같이 추가할 수 있습니다. void licenseAdd () { LicenseRegistry. addLicense (() => Stream <LicenseEntry>. value ( const LicenseEntryWithLineBreaks ( <String>[ '라이브러리 이름' ] , ''' 라이센스 본문을 복사한다. ''' , ) , )) ; }

dart (flutter) 문법 - 생성자.

플러터는 생성자의 구문이 매우 다양 합니다. https://dartpad.dev 에 아래 코드를 복사해서 실행해 보세요. factory 는 다음 페이지에 정리되어 있습니다. https://abel9999.blogspot.com/2022/07/dart-flutter-factory.html class Animal { String name = '' ; int id = 0 ; // 이름 없는 생성자 . Animal() {} // 이름 없는 생성자는 하나이상 만들수 없다 . // Animal(int i) { } // 에러 . // 이름 있는 생성자 . Animal. name () {} // 생성자를 여러개 만들수 있고 // 멤버변수의 기본값을 설정할 수 있다 . Animal. nameNew () : name = 'test' {} // 생성자에서 파라메터를 받을수 있다 . // 아래 생성자는 동일한 동작을 한다 . Animal. arg (String n) { name = n ; } Animal. arg2 (String n) : name = n {} Animal. arg3 ( this . name ) ; // {} 로 둘러산 부분은 호출시에 이름을 지명해야 한다 . // 예 ) Animal a = Animal.argName(name:'go', id:2); Animal. argName ({ required this . name , required this . id }) ; // [] 로 둘러싼 부분은 호출시에 값이 없으면 기본값을 지정한다 . // 예 ) // Animal a = Animal.argName2(); // Animal a2 = Animal.argName2('go'); // Animal a3 = Animal.argName2('go'. 33); // Animal a4 = Animal.argName

dart (flutter) 문법 - null 관련 문법 정리.

dart문법에서 아래 키워드를 코드와 주석으로 설명 합니다. ?  !  ??  ??=  ?.  ?.. https://dartpad.dev 에 아래 코드를 복사해서 실행해 보세요. void main () { String? strTest ; // '?' 는 null 이 가능하다는 표시 . // '!' 는 strTest 가 null 이 아니라는 표시 . // Uncaught TypeError 예외가 난다 . //print("'!' $strTest!"); print(strTest) ; // null 을 print 하면 null 출력한다 . strTest = "test" ; print(strTest) ; // getString() {} 은 null 을 리턴할 수 있다는 암시적 표현이다 . print( "'getString()' ${getString()} " ) ; // String? getString2() {} 은 null 을 리턴할 수 있다는 명시적 표현이다 . print( "'String? getString2()' ${getString2()} " ) ; // String getString3() {} 은 반드시 String 을 리턴하는 명시적 표현으로 // return "test" 가 없으므로 예외가 난다 . int? nInt ; int res = nInt ?? 5 ; // '??' 는 nInt 가 null 이면 5 를 반환한다 . print( "'??' $res " ) ; nInt ??= 5 ; // '??=' 는 nInt 가 null 이면 nInt 에 5 를 할당한다 . print( "'??=' = $res " ) ;

android studio emulator만 독립 실행하는 방법.

안드로이드 개발할 때 사용하는 에뮬레이터를 독립 실행하는 방법입니다. 안드로이드 스튜디오 실행 없이 에뮬레이터를 사용하고 싶거나, 빠르게 에뮬레이터를 실행하고 싶을 때 사용 합니다. https://developer.android.com/studio 안드로이드 스튜디오를 설치하고 안드로이드 스튜디오에 있는 디바이스 매니저로 가상 디바이스를 만듭니다. https://www.nirsoft.net/utils/nircmd.html 다운 받아 압축을 풀고 nircmd 파일을 아래 배치 파일과 같은 경로에 복사 합니다. 배치파일을 실행하면 검은 콘솔이 같이 뜨는데 콘솔을 보이지 않게 해 줍니다. 아래 스크립트를 콘솔(cmd.exe)에서 실행하거나 배치파일(bat)을 만들어 실행하면 됩니다. bat로 만드는게 더 편합니다. * 에뮬레이터에 생성된 가상 디바이스 목록을 보여줍니다. %localappdata%\Android\Sdk\emulator\emulator -list-avds @pause * 에뮬레이터를 실행합니다. nircmd exec hide %localappdata%\Android\Sdk\emulator\emulator -avd <디바이스이름> 위 경로는 sdk가 설치되어 있는 기본 경로 입니다. 다른 폴더에 설치했다면 경로를 변경해 줘야 합니다. 

flutter - ChangeNotifierProvider 사용법 설명.

* provider 가 필요한 이유.  - 예를 들면 flutter에서 버튼을 클릭한 경우 다른 위젯이나 상위 위젯의 리빌드를 구현하기 위해 필요하다. * 설명.  - ChangeNotifierProvider에 ChangeNotifier 상속 받은 클래스를 등록하면 하위 위젯에서 등록한 것을 찾아 사용할 수 있습니다. 즉 상위 위젯에서 하위 위젯으로 흐르는 데이터의 이동 통로를 만든다 생각하면 됩니다.  - 리빌드가 필요한 위젯을 지정합니다.   + Consumer, context.watch, Provider.of<Counter>(context, listen: true) 사용.  - 갱신이 필요한 경우 ChangeNotifierProvider에 등록한 ChangeNotifier 상속 받은 클래스를 찾아 notifyListeners() 호출하면, 위에서 지정한 리빌드가 필요한 위젯을 리빌드 합니다.   + 데이터 사용은 context.read<Counter>(), Provider.of<Counter>(context, listen: false)으로 합니다.  * 중요 - 아래 함수의 차이를 알아야 합니다.  - context.read<Counter>(), Provider.of<Counter>(context, listen: false)   + 데이터에 접근만 합니다.  - context.watch, Provider.of<Counter>(context, listen: true), Consumer   + 데이터에 접근도 하고, notifyListeners() 호출시 리빌하는 위젯을 지정하는 기능도 있습니다.   + 이 함수나 클래스를 사용하지 않으면 notifyListeners() 호출해도 리빌드 하지 않습니다.  * 공식 사이트.  -  https://pub.dev/packages/provider * 코드 구현.  - https://pub.dev/packages/provider/example 의 샘플 코

dart (flutter) 문법 - factory 키워드.

dart (flutter)에서 지원하는 factory 기능에 대해 정리 합니다.  * 설명.  - 생성자는 원래 리턴할 수 없지만, factory 키워드를 사용하면 현재 클래스와 자식 클래스의 인스턴스를 생성자에서 리턴할 수 있게 됩니다.  - 아래 코드의 주석으로 설명 합니다. 동작과 제한 사항을 알 수 있습니다.

dart (flutter) 문법 - ! (느낌표, exclamation mark)

// 리턴값이 항상 null이 아니지만 예를 위한 함수. // int? 는 getInt()가 null을 리턴할 수 있다고 명시해 준다. int? getInt () { return 3 ; } void main () { // int? 는 변수에 null 을 허용하는 표현 . int? a = getInt() ; // ERROE int b 는 null 을 허용하지 않는데 // getInt() 는 null 을 리턴할 수도 있으므로 에러가 난다 . //int b = getInt(); // getInt()! 에서 null 을 리턴하지 않는다고 // getInt() 의 끝에 ! 를 명시해 에러가 나지 않는다 . int c = getInt()! ; } null 에러가 많이 나서 이런 기능을 추가 했다고 하는데 그다지 좋은 해결법이 아닌거 같다. !를 붙여도 에러가 날 수 있는 구멍이 많다.

dart (flutter) 문법 - 클래스. class, abstract, implements, factory

클래스 기본 예제. dart에서는 단일 상속만 가능하다. class Point { double? x ; double? y ; // 이름 없는 생성자 . 하나만 가능하다 . Point(double x , double y) { this . x = x ; this . y = y ; } // 이름있는 생성자 . Point. init () : x = 0 , y = 0 { } // 이름 없는 생성자 호출 . Point. init2 () : this ( 0 , 0 ) { } int GetV () { return 1 ; } } class Point3D extends Point { final bool i3D = true; double z = 0 ; // 생성시 부모 클래스 생성자 호출 . Point3D(double x , double y , double z) : super (x , y) { this . z = z ; } // 부모의 함수를 재정의 할 수 있다 . @override int GetV () { return 2 ; } } void main () { var p1 = Point ( 2 , 2 ) ; var p2 = new Point3D ( 2 , 2 , 2 ) ; print( 'The type of a is ${p1. runtimeType } ' ) ; } 추상 클래스. 인스턴스화 되지 않는 클래스로 주로 인터페이스 정의에 사용된다. abstract class AbstractContainer { void updateChildren () ; // 추상 함수 . } class ClassA extends AbstractContainer { // 추상 함수 정의 . void updateChildren () {} } implements (인터페이스) 상속받지 않고 다른 클래스의 인터페이스를 지원할 수 있다. 여러 클래스의 인터페이스를 지원합니다.

dart (flutter) - 함수.

알림 - dart는 함수 표현법이 다양합니다.  이 문서에서는 제가 선호하는 유형만 다룹니다. 아래 3가지 함수는 동일한 동작의 함수 입니다. bool isOne (int one) { return one == 1 ; } isOne2 (one) { return one == 1 ; } bool isOne3 (int one) => one == 1 ; 보통 함수. // 호출 . int n = test( true, 1 ) ; // 정의 . int test (bool isB , int numN) { return numN ; } 이름 있는 함수. test2 (isB: true, numN: 1 ) ; test2(numN: 1 ) ; // test2(true, 1); // error // {} 로 둘러싸면 호출시 변수명을 명시해야 한다 . void test2({bool? isB , int? numN}) {} test2_1 (isB: true, numN: 1 ) ; test2_1(isB: true ) ; // error test2_1(numN: 1 ) ; // required 를 붙여주면 실행하는데 꼭 필요한 함수 . void test2_1({bool? isB , required int numN}) {} 옵션 인수 함수.   test3(true, 1);   test3();   test3(false); // [] 로 둘러싸면 호출시 인수를 입력하지 않으면 기본값을 지정해 줍니다. void test3 ([bool isB = true, int numN = 1 ]) {} forEach 에서 익명함수. var intList = [ 1 , 2 , 3 ] ; intList.forEach((item) { print(item) ; }) ; int List.forEach((item) => print(item)) ;

dart (flutter) 문법 - typedef.

// 기존 타입의 별칭을 만들수 있다 . typedef IntList = List<int> ; // 함수의 형태를 타입으로 사용 가능 . typedef Compare(int n , int m) ; bool maxLeft (int a , int b) { return a > b ; } bool compareAB (int a , int b , Compare cp) { return cp(a , b) ; } void main () { IntList il = [ 1 , 2 , 3 ] ; int a = 2 ; int b = 1 ; bool isLeftMax = compareAB(a , b , maxLeft ) ; }

dart (flutter) 문법 - 제어문. if, for, forEach, switch

- if 문. if (isRaining()) { you.bringRainCoat() ; } else if (isSnowing()) { you.wearJacket() ; } else { car.putTopDown() ; } - for, forEach 문. var message = StringBuffer ( 'Dart is fun' ) ; for ( var i = 0 ; i < 5 ; i++) { message.write( '!' ) ; } for ( final candidate in candidates) { candidate.interview() ; } var collection = [ 1 , 2 , 3 ] ; collection. forEach (print) ; // 1 2 3 - while, do while 문. while (!isDone()) { doSomething() ; } do { printLine() ; } while (!atEndOfPage()) ; - switch 문.  test () { var command = 'OPEN' ; switch (command) { case 'OPEN' : executeOpen() ; break; default : executeUnknown() ; } } 참고. https://dart.dev/guides/language/language-tour#control-flow-statements

dart (flutter) - 예외.

test () { try { throw OutOfLlamasException( 'Expected at least 1 section' ) ; throw 'Out of llamas!' ; } on OutOfLlamasException { // A specific exception buyMoreLlamas() ; } on Exception catch (e) { // Anything else that is an exception print( 'Unknown exception: $e ' ) ; } catch (e) { print( 'Error: $e ' ) ; // Handle the exception first. } finally { cleanLlamaStalls() ; // Then clean up. } }

dart (flutter) 문법 - 연산자.

* 주의 설명과 연산자의 구분자는 '=>' 입니다. 단항 접미사 => expr++    expr--    ()    []    ?[]    .    ?.    ! 단항 접두사 => -expr    !expr    ~expr    ++expr    --expr      await expr    곱셈 나눗셈 => *    /    %  ~/ 더하기 빼기 => +    - 비트 쉬프트 => <<    >>    >>> 비트연산자 AND => & 비트연산자 XOR => ^ 비트연산자 OR => | 값비교 및 형식비교 =>  >=    >    <=    <    as    is    is! 같은지, 다른지 => ==    !=    논리 AND => && 논리 OR => || null 인지 => ?? 삼항 연산자 => expr1 ? expr2 : expr3 캐스케이드(동일한 인스턴스 멤버 호출) => ..    ?.. 할당연산자 => =    *=    /=   +=   -=   &=   ^=   etc. 참고. https://dart.dev/guides/language/language-tour#operators - 단항 접미사, 단항 접두사, 곱셈 나눗셈, 더하기 빼기, 할당연산자 int i = 1; i++; // i == 2 i = 1; int y = i + i; // i == 2 i = 1; int y = i * i; // i == 1 i = 1; i += 2; // i == 3 - 비트 쉬프트, 비트연산자  int i = 1; // 예를  들어 1의 비트가 0001 이라면 i << 1; // 연산으로 0010가 되고 int값으로 2가 됨. 1 | 2; // 0001 | 0010 = 0011 이 되고 int값으로 3이 됨. - 값비교, 논리 (3 == 3);

dart (flutter) 문법 - 주석.

void main() {      // 주석1      /*     * 주석2 - 여러줄.    */   /// 주석으로 문서를 직접 만들수 있다.    /// 마크다운도 지원   /// 문서화에 대한 자세한 사용법은 아래 링크 참조.   /// https://dart.dev/guides/language/effective-dart/documentation }

dart (flutter) 문법 - final, const 차이.

final, const  공통점 - 초기값을 할당한 이후 값 변경할 수 없다. 차이 - const는 컴파일 타임에 상수화 된다. 초보는 이해하기 어려울 수 있다. const는 초기화시에 항상 값을 대입해야 한다는 것만 알면 된다. 예) const int i2 = 123; void main () { final int i = 123 ; //i = 456; // Error const int i2 = 123 ; //i2 = 456; // Error final int i3 = getInt() ; /* * const 는 컴파일 시점에 상수화되어 * 런타임에 초기값을 넣을수 없다 . */ const int i4 = getInt() ; // Error } int getInt () { return 5 ; }

dart (flutter) 문법 - 데이터 타입.

데이터 타입. int, double, num, String, bool, Lists, Set, Map, ,Runes void main () { int i = 123 ; // 정수형 . double d = 1.23 ; // 실수형 . num n1 = 123 ; // num 은 정수 , 실수 모두 가능 . num n2 = 1.23 ; String s1 = 'abc' ; // 문자열 . String s2 = 'abc $n2 ' ; // 문자열에 변수 입력 가능 . print(s2) ; print(s2. runes ) ; // 문자열을 UTF-16 인코딩 bool b = true; // 참과 거짓 . b = false; List l = [ 1 , 2 , 3 ] ; // 배열 , 중복가능 . print(l[ 0 ]) ; // 중복불가 . 이외에도 여러가지 구문으로 초기화 가능 . Set<String> se = { 'a' , 'b' , 'c' } ; // ( 키 , 값 ) 으로 조합 , 키는 중복 불가 . 초기화 구문 다양함 . Map<int , String> m = { 1 : '11' , 2 : '22' , 3 : '33' } ; print(n2) ; }

dart (flutter) 문법 - dynamic, var 차이.

dynamic - 항상 다른 타입을 허용한다. var - 처음 추론된 타입만 허용된다. // dynamic 예제 . void main () { int a = 123 ; String b = 'abc' ; dynamic test = a ; test = b ; // 다른 타입도 허용된다 . print(test) ; } // var 예제 . void main() { int a = 123 ; String b = 'abc' ; var test = a ; test = b ; // Error 다른 타입이 허용되지 않는다 . print(test) ; }

가벼운 git 클라이언트 SourceGit

이미지
https://github.com/sourcegit-scm/sourcegit 1메가보다 작은 실행파일 하나인 GIT클라이언트. git명령어를 래핑한 가벼운 프로그램이다. 소스가 깔끔하고 구조가 쉽게 잘되어 있으니 필요한 기능이 있다면 추가하기 쉽다. 따로 설치할 필요없고 실행파일 하나만 복사해서 사용하면 된다. 사전에 git, .net6.0 이 설치되어 있어야 한다. - git https://git-scm.com/   - .net6.0 https://dotnet.microsoft.com/en-us/download/dotnet/6.0 윈도우나 visual studio에 사전 설치되어 있을 수 있으니  실행해 보고 안되면 그때 설치하면 된다.

dev.azure.com에서 초대 오류 해결 error 401

- 문제. dev.azure.com 에서 조직을 만들고 프로젝트를 설정한 뒤  동료와 공동작업을 위해 조직에 초대를 했는데  자꾸 401 오류가 났습니다. - 시도. 유저 삭제 후 다시 초대  웹검색으로 브라우저 시크릿 모드, 쿠키 모두 날리기, 새로운 브라우저 설치 후 시도  등 여러 방법을 했지만 오류가 났습니다. - 해결. 요약 - MS계정에 github 연결을 풀고 다시 초대해서 해결 했습니다. MS계정에 github가 연결되어 있어 연결을 풀었습니다. https://account.microsoft.com/security 에 접속해 "고급 보안 옵션" 을 누르고 github 연결을 해제하면 됩니다. 이후 dev.azure.com -> 조직 옵션 -> 유저 에서 해당 유저를 삭제후 다시 초대하면 됩니다. - 참고. https://developercommunity.visualstudio.com/t/unable-to-accept-invite-from-devazurecom-error-401/1684419