【Flutter】 always_use_package_importsを理解する

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/af459c3b-4234-3a3d-bfac-85cfc24bb678.png)

こんにちわ。いせりゅーです。今回はFlutterの静的解析の一つにある`always_use_package_imports`について記載していこうと思います。

自分のインプットした内容をアウトプットするためでもあるので少しでも役に立てたら嬉しいです😁

# 公式サイト

https://dart.dev/tools/linter-rules/always_use_package_imports



# 解説を要約して理解してみよう

>`Avoid relative imports for files in lib/.`

<b>lib/の中にあるファイルで相対インポートを避ける（翻訳）</b>

Flutterを作成した際に、以下のようなフォルダーになると思います。（人によって作られるフォルダが変わります）

```
.dart.tool
.idea
android
build
ios
lib　//☜これ！
test

...その他
```

lib/内での相対インポートと絶対インポートを混合すると、2つの異なる方法でインポートされるため、混乱が生じる可能性があります。これを回避する1つの方法は、ディレクトリ内のファイルに対して絶対インポートを一貫して使用することです。

:::note info

このルールは Dart 2.10.0 以降で利用可能です。
:::

ここで相対インポート？？となる方がいるかなと思います。ちゃんと以下で解説しますよ👌

## 相対インポートとは

インポートには「絶対インポート」と「相対インポート」の2つがあります。

### 絶対インポート (Absolute Import)
- インポートする際に、完全なパスを使用する方法
- 例えば、package:プレフィックスを使ってパッケージから直接インポートする場合などがこれに該当します。
- Dartパッケージの外部からのインポートや、アプリケーションのルートからの絶対パスを使用する場合に役立ちます。
- インポートされるファイルの場所が変わっても、インポート文自体の変更は不要です。

### 相対インポート (Relative Import)
- インポートする際に、現在のファイルに対する相対的なパスを使用します。
- 「.」 や 「..」などの相対パス記法を使用する。
- 同じパッケージ内や隣接するディレクトリ内のファイルをインポートする際に便利です。
- ただし、ファイルの場所が変わると、インポート文も変更する必要があります。

どちらもメリットとデメリットがありますが、FlutterやDartのコミュニティでは、特に大規模なプロジェクトでは、絶対インポートを使用することが推奨されている場合が多いです。絶対インポートを使用すると、ファイル構造の変更があった際に、インポートの修正が少なく済むため、保守性が向上します。


# コードから理解してみよう


## フォルダ構成


:::note info
フォルダー構造について一部を省略しています。
:::

```
・
├── android
├── ios
├── lib
│   ├── main.dart
│   ├── my_home_page.dart
├── test
├── analysis_options.yaml
```


`analysis_options.yaml`に以下の記載を行います。もっと追加したほうがいいとは思いますが、今回は、` always_use_package_imports`を理解するために一つだけの記載になっています。


```yaml:analysis_options.yaml

include: package:flutter_lints/flutter.yaml

linter:
  rules:
    - always_use_package_imports
```



```dart:my_home_page.dart

import 'package:flutter/material.dart';

//相対パス→これだと
import '../my_home_page.dart';

//絶対パス
import 'package:always_use_package_imports/my_home_page.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

```

```dart:my_home_page.dart
import 'package:flutter/material.dart';

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

```

相対importを使用すると、以下のwarningが出現します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/a85aaef0-8f2e-e5d3-1f5f-ae83fd5933c1.png)

この場合では、「Convert to 'package: import'」のボタンを教えていただけると自動で修正してくれます。重大なエラーやwarningではないとは思いますが、いいコード書くためにはとても大切であると僕は思います。


# リポジトリ

https://github.com/iseruuuuu/always_use_package_imports