Flutter Error - ynjch97/YNJCH_WIKI GitHub Wiki

UI κ΄€λ ¨ 였λ₯˜

1. The following assertion was thrown during performResize

The following assertion was thrown during performResize():
Horizontal viewport was given unbounded height.
Viewports expand in the cross axis to fill their container and constrain their children to match
their extent in the cross axis. In this case, a horizontal viewport was given an unlimited amount of
vertical space in which to expand.
  • μœ„μ™€ 같은 였λ₯˜ λ°œμƒ 원인 : Column 으둜 감싼 ListView 에 μ„€μ •λœ 높이가 μ—†μŒ -> μ œν•œ μ—†λŠ” 높이값이 λ„˜μ–΄μ˜΄
return Column(
  children: [
    const SizedBox(
      height: 200,
    ),
    makeList(snapshot), // => return ListView.separated( ~
  ],
);
  • Expanded(child: makeList(snapshot),) : ν™”λ©΄μ˜ λ‚¨λŠ” 곡간을 μ°¨μ§€ν•˜λŠ” Widget μ„€μ •

2. The following ProgressEvent object was thrown resolving an image codec

The following ProgressEvent object was thrown resolving an image codec:
  [object ProgressEvent]

When the exception was thrown, this was the stack

Image provider:
  NetworkImage("https://image-comic.pstatic.net/webtoon/823999/thumbnail/thumbnail_IMAG21_db3ba875-37f1-4d05-a7c9-73d9bb43fc62.jpg",
  scale: 1.0)
  • Chrome ν™˜κ²½μ—μ„œ Image.network Debug ν…ŒμŠ€νŠΈ μ‹œ μœ„ 였λ₯˜ λ°œμƒ
  • ~\toonflix\web\index.html > <script> > window.flutterWebRenderer = "html"; μΆ”κ°€

2-1. Exception caught by image resource service

════════ Exception caught by image resource service ════════════════════════════
HTTP request failed, statusCode: 403, https://image-comic.pstatic.net/webtoon/784248/thumbnail/thumbnail_IMAG21_20a8aca7-23d3-4bc0-9916-a31ebc884ca8.jpg
  • Android Mobile ν™˜κ²½μ—μ„œ Image.network Debug ν…ŒμŠ€νŠΈ μ‹œ μœ„ 였λ₯˜ λ°œμƒ
  • headers μΆ”κ°€
  headers: const {
    "User-Agent":
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
  },

2-2. Chrome + Android Mobile

  • Chrome + Android Mobile ν™˜κ²½μ—μ„œ λͺ¨λ‘ 이미지가 λ‚˜μ˜€λ„λ‘
  • main.dart > MyHttpOverrides() μΆ”κ°€
class MyHttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context)
      ..userAgent =
          'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36';
  }
}

void main() {
  HttpOverrides.global = MyHttpOverrides();
  runApp(const App());
}

3. BoxConstraints forces an infinite width.

  • case: Column > Row μ•ˆμ— FractionallySizedBox κ°€ 쑴재 (widthFactor: 1 => 100% 의 곡간 μ°¨μ§€)
  • box κ°€ λ¬΄ν•œλŒ€μ˜ width λ₯Ό κ°€μ§€κΈ° λ•Œλ¬Έμ— μ—λŸ¬ λ°œμƒ
  • FractionallySizedBox 을 κ°μ‹ΈλŠ” Expanded μ‚¬μš©, λΆ€λͺ¨λ‘œμ„œ 크기λ₯Ό κ²°μ •ν•˜λ„λ‘ 함
BoxConstraints forces an infinite width.
These invalid constraints were provided to RenderDecoratedBox's layout() function by the following function, which probably computed the invalid constraints in question:
  RenderFractionallySizedOverflowBox.performLayout (package:flutter/src/rendering/shifted_box.dart:1171:14)
The offending constraints were: BoxConstraints(w=Infinity, 0.0<=h<=Infinity)

3-1. Horizontal viewport was given unbounded height

  • νŠΉμ •ν•œ λ†’μ΄λ‚˜ λ„ˆλΉ„λ₯Ό μ§€μ •ν•΄μ£Όμ§€ μ•Šμ•„μ„œ λ°œμƒν•˜λŠ” 였λ₯˜
  SizedBox(
    width: MediaQuery.of(context).size.width,
    height: MediaQuery.of(context).size.height,
    child: const TabBarView(
      children: [
  • TabBarView λŠ” 기본적으둜 λ¬΄ν•œλŒ€μ˜ 크기λ₯Ό 가짐
    • SizedBox λ₯Ό μ΄μš©ν•΄ width, height κ°’ μ§€μ •

Variable, Function 였λ₯˜

1. The argument type 'void Function()' can't be assigned ~

  • The argument type 'void Function()' can't be assigned to the parameter type 'void Function(Timer)'
  • μœ„μ˜ κ²½μš°λŠ” Timer λ₯Ό νŒŒλΌλ―Έν„°λ‘œ ν• λ‹Ήν•΄μ£Όμ§€ μ•Šμ•˜λ‹€λŠ” 뜻
  • Timer λ₯Ό 인자둜 λ„£μ–΄μ£Όλ©΄ 됨

2. Non-nullable instance field 'timer' must be initialized.

  • Timer timer; 의 경우, μ΄ˆκΈ°ν™”κ°€ ν•„μš”ν•œλ° μ΄ˆκΈ°ν™”ν•˜μ§€ μ•Šμ€ μƒνƒœ
  • 미리 μ΄ˆκΈ°ν™” ν•˜μ§€ μ•Šκ³  μ‚¬μš©μžκ°€ λ²„νŠΌμœΌ λˆ„λ₯Ό λ•Œλ§Œ 타이머가 μƒμ„±λ˜κ²Œ ν•˜λ €λ©΄ late variable modifier μ‚¬μš©
  • late Timer timer;

3. This class is marked as '@immutable' ~

  • This class (or a class that this class inherits from) is marked as '@immutable', but one or more of its instance fields aren't final: [클래슀λͺ…].[λ³€μˆ˜λͺ…]
  • ν•΄λ‹Ή λ³€μˆ˜λ₯Ό final 둜 μ„€μ •ν•΄μ£Όλ©΄ 됨 (immutable: λΆˆλ³€)

4. A nullable expression can't be used as an iterator in a for-in loop.

  • for (var webtoon in snapshot.data)
  • List 데이터가 null 일 수 μžˆμœΌλ―€λ‘œ Null Safety 였λ₯˜ λ°œμƒ
  • 데이터가 μžˆλ‹€κ³  ν™•μ‹ ν•˜κΈ° μœ„ν•΄ ! 기호 μ‚¬μš©ν•˜μ—¬ 였λ₯˜ 제거 -> for (var webtoon in snapshot.data!)

5. The instance member 'webtoon' can's be accessed in an initializer.

  • The instance member 'webtoon' can's be accessed in an initializer. Try replacing the reference to the instance member with a different expression
final Future<WebtoonDetailModel> webtoonDetail = ApiService.getToonById(webtoon.id);
  • getToonById() λŠ” νŒŒλΌλ―Έν„°λ‘œ webtoon.id λ₯Ό λ°›μŒ
  • webtoonDetail ν”„λ‘œνΌν‹°λ₯Ό μ΄ˆκΈ°ν™”ν•  λ•Œ webtoon ν”„λ‘œνΌν‹°μ— μ ‘κ·Ό λΆˆκ°€
    • StatelessWidget -> StatefulWidget λ³€κ²½ν•˜μ—¬ ν•΄κ²°
    • νŒŒλΌλ―Έν„°λŠ” initState() μ—μ„œ widget.webtoon.id ν˜•νƒœλ‘œ μ‚¬μš©

6. The method 'validate' can't be unconditionally invoked ~

  • The method 'validate' can't be unconditionally invoked because the receiver can be 'null'. Try making the call conditional (using '?.') or adding a null check to the target ('!').
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

_formKey.currentState.validate();
  • currentState κ°€ 없을 μˆ˜λ„ 있기 λ•Œλ¬Έμ— validate() 호좜 λΆˆκ°€
    • μ•„λž˜ 두 κ°€μ§€ 방법 쀑 택 1
if (_formKey.currentState != null) {
  _formKey.currentState!.validate(); // null 체크 ν›„ ν™•μ‹€νžˆ μ‘΄μž¬ν•¨μ„ ν‘œμ‹œ
}

_formKey.currentState?.validate();

7. (Failed assertion: 'items.length >= 2' : is not true.)

  • _AssertionError : μ–΄λ–€ 쑰건이 참이지 μ•Šμ„ λ•Œ λ°œμƒν•˜λŠ” 였λ₯˜
  • items.length >= 2 : item ν•˜μœ„μ— 2개 μ΄μƒμ˜ item 이 μ‘΄μž¬ν•΄μ•Ό 함

8. Don't user 'BuildContext's across async gaps.

  • Don't user 'BuildContext's across async gaps. Try rewriting the code to not use the 'BuildContext', or guard the user with a 'mounted' check.
  • async ν™˜κ²½μ—μ„œ context μ‚¬μš© μ‹œ λ°œμƒν•˜λŠ” 였λ₯˜
  • mounted μ²΄ν¬ν•˜μ—¬ 였λ₯˜ 제거
if (!mounted) return;
    
Navigator.push(
  context, (μƒλž΅)
);

Const 였λ₯˜

1. Use 'const' with the constructor

  • νŒŒλž€ 밑쀄과 ν•¨κ»˜ Use 'const' with the constructor to improve performance. 문ꡬ 확인(constant constructor λŠ” const λ₯Ό μ“°λŠ” κ±Έ μΆ”μ²œν•œλ‹€)
  • backgroundColor: const Color(0xFF181818), const SizedBox(...
  • const 둜 λ§Œλ“€μ–΄μ£ΌλŠ” 것이 효과적, const 뢙이면 밑쀄 사라짐
  • Command Palette (Ctrl + Shift + P) > open user settings > settings.json 파일 μ—΄κΈ°
    • editor.codeActionsOnSave μΆ”κ°€ : μžλ™μœΌλ‘œ const κ°€ ν•„μš”ν•œ 곳을 μˆ˜μ •ν•΄μ€Œ
    • dart.previewFlutterUiGuides μΆ”κ°€ : λΆ€λͺ¨-μžμ‹ 식별을 μœ„ν•œ κ°€μ΄λ“œλΌμΈ ν‘œμ‹œ
  "[dart]": {
    "editor.tabSize": 2,
    "editor.insertSpaces": true,
    "editor.detectIndentation": false,
    "editor.suggest.insertMode": "replace",
    "editor.defaultFormatter": "Dart-Code.dart-code",
    "editor.inlayHints.enabled": "offUnlessPressed"
  },
  "editor.codeActionsOnSave": {
    "source.fixAll": true
  },
  "dart.previewFlutterUiGuides": true,

6

2. Arguments of a constant creation must be constant expressions

  child: const Padding(
    padding: EdgeInsets.symmetric(vertical: 20, horizontal: 50),
    child: Text(
      text, // λ³€μˆ˜ text λ₯Ό 받도둝 ν•˜λ‹ˆ, μ΄κ³³μ—μ„œ λΉ¨κ°„ 밑쀄 λ°œμƒ
      style: TextStyle(
        fontSize: 20,
        color: textColor,
      ),
    ),
  ),
  • μœ„ μ½”λ“œμ—μ„œ 였λ₯˜κ°€ λ°œμƒν•˜λŠ” 이유
    • Text 의 λΆ€λͺ¨κ°€ Padding 이고, Padding 은 const μƒμ„±μžλ₯Ό κ°€μ§€κ³  있음
    • Text κ°€ const(μƒμˆ˜)일 땐 κ°€λŠ₯ν•œ μ΄μ•ΌκΈ°μ΄λ‚˜, ν˜„μž¬λŠ” const κ°€ μ•„λ‹Œ μ»€μŠ€ν„°λ§ˆμ΄μ§•λœ text λ³€μˆ˜
  • const λ₯Ό μ§€μ›Œμ€€ ν›„ μ €μž₯, source.fixAll 에 μ˜ν•΄ μ μ ˆν•œ μœ„μΉ˜μ— const κ°€ 생성됨
  • 즉, 컴파일 μ‹œ 미리 μ•Œ 수 μžˆλŠ” μ˜μ—­μ„ λ¬Άμ–΄ const κ°€ μ“°μ—¬μ§€λŠ” 것

μž‘λ™ μ‹œ λ°œμƒ 문제

1. sleep()

  • λ‘œλ”© 쀑 ν™”λ©΄ ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•΄ sleep() 을 μ‚¬μš©ν–ˆμœΌλ‚˜, μ„€μ •ν•œ Duration μ΄ν›„λ‘œλ„ sleep μƒνƒœμ— μžˆλŠ” 문제
    • Async μ½”λ“œμ—μ„œλŠ” Future.delayed() μ‚¬μš©
// In Async Code
await Future.delayed(Duration(seconds: 1));
// In Sync Code
sleep(Duration(seconds:1));

2. Set 'android:enableOnBackInvokedCallback="true"' in the application manifest.

  • android/app/src/main/AndroidManifest.xml 에 μ•„λž˜μ™€ 같이 μΆ”κ°€
    • Android μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ κΈ°λ³Έ 섀정을 μ •μ˜ν•˜λŠ” κ³³
    <application
        android:label="your_app_name"
        android:icon="@mipmap/ic_launcher"
        android:enableOnBackInvokedCallback="true"> <!-- μ—¬κΈ° μΆ”κ°€ -->
  • VSCode > Terminal > μ•„λž˜ λͺ…λ Ήμ–΄ μž…λ ₯
flutter clean
flutter pub get
  • Android 12(API 레벨 31) μ΄μƒμ˜ κΈ°κΈ°μ—μ„œ μ‹œμŠ€ν…œμ˜ λ’€λ‘œκ°€κΈ° κΈ°λŠ₯을 더 μœ μ—°ν•˜κ³  ν†΅μ œ κ°€λŠ₯ν•˜κ²Œ μ‚¬μš©ν•˜κΈ° μœ„ν•¨

3. ImagePicker().pickImage() - PlatformException

  • PlatformException (PlatformException(channel-error, Unable to establish connection on channel: "dev.flutter.pigeon.image_picker_android.ImagePickerApi.pickImages"., null, null))
  • image_picker: ^1.1.2 μ‚¬μš©, final xfile = await ImagePicker().pickImage(); μ‹€ν–‰ν•˜λ©΄ 였λ₯˜ λ°œμƒ
  • android/app/src/main/AndroidManifest.xml 에 μ•„λž˜μ™€ 같이 μΆ”κ°€
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <!-- μ—¬κΈ° μΆ”κ°€ -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- μ—¬κΈ° μΆ”κ°€ -->
    <application
        android:label="RiFFest"
⚠️ **GitHub.com Fallback** ⚠️