What is the difference between package import and normal import in flutter? - flutter

Going through some flutter source code and found two different types of imports.
What is the difference between the two and which one is better ?
#1
import 'folder/filename.dart';
#2
import 'package:projectname/folder1/folder2/folder/filename.dart';

There's no performance differences or anything like that.
But.. it is better to use package paths because you won't need to edit all your imports in case you move your file to another location (as they're not relative paths).

Saying that there is no difference at all might be tricky. Because importing files as packages in some place and as simple files in another, dart will consider them two different namespaces. So it can cause type conflicts. The safe way to do it is to choose one method to do it and stick to it.

Related

How to import all files at once pointed out by Dart Analysis?

I just put some of my code from a/b.dart to a/b1.dart file and now I started getting lot of errors on importing.
Is there any command or any other fix to import all a/b1.dart file in these files instead of manually opening each file and importing one by one.
I understand that a function or a property can be defined in more than two files and Dart can't make the right choice but if a function or property is defined in just one place, I think there must be some way to import it except searching for a/b.dart and replacing it with a/b.dart + a/b1.dart and then optimizing all imports.
As much as I am aware, Plugins/Extensions for your specific IDE (for dart) can be found that will help you with this problem.
I would recommend using dartdev tools - dartfix

Is it a bad practice to export all different widgets inside a single widget then import these widgets by importing this single file wherever we need?

If I create a file like widgets.dart and put the exportation of all my widgets inside that like below:
export 'custom_app_bar.dart';
export 'content_header.dart';
export 'vertical_icon_button.dart';
Then import this file wherever I needed one of these widget inside another file like below:
import './widgets/widgets.dart';
Is it a bad practice and would have overhead process/memory issues?
I am also thinking about put more codes in the same file, for example define 3 different MobileSizeHomeScreen() , TabletSizeHomeScreen(), DesktopSizeHomeScreen() classes/widgets inside one file like home_screen.dart instead of creating 3 different mobile, tablet, desktop files, but don't know doing such a things would cause performance or maintenance issues while the project gets larger and more complexed or not?
As far as I know, that isn't a bad practice. However, Dart presents us with part and part of to do that kind of stuff. You can read more about Dart effective usage here.
Suppose all of those four files are within the same directory.
In the above's case, ./widget/widgets.dart would have this line (above the class declaration):
part 'custom_app_bar.dart';
part 'content_header.dart';
part 'vertical_icon_button.dart';
and in each of those three, they will have this line that indicates, they are part of the ./widget/widgets.dart:
part of 'widgets.dart';
Then, when you need one of the widgets, you only need to import widgets.dart
I see some of the other Dart developers also use the export stuff, so it is a matter of preference. Personally, I would prefer what Dart recommends, which is using part and part of.

Flutter imports: relative path or package?

In Flutter, for importing libraries within our own package's lib directory, should we use relative imports
import 'foo.dart'
or package import?
import 'package:my_app/lib/src/foo.dart'
Dart guidelines advocate to use relative imports :
PREFER relative paths when importing libraries within your own package’s lib directory.
whereas Provider package says to always use packages imports :
Always use package imports. Ex: import 'package:my_app/my_code.dart';
Is there a difference other than conciseness? Why would packages imports would reduce errors over relative imports?
From the same Dart guidelines, further down they give this reason for the relative imports:
There is no profound reason to prefer the former—it’s just shorter, and we want to be consistent.
Personally, I prefer the absolute method, despite it being more verbose, as it means when I'm importing from different dart files (in other folders), I don't have to work out where the file to be imported is, relative to the current file. Made-up example:
I have two dart files, at different folder levels, that need to import themes/style.dart:
One is widgets/animation/box_anim.dart, where the relative path import would be:
import '../../themes/style.dart';
The other is screens/home_screen.dart with the relative import:
import '../themes/style.dart';
This can get confusing, so I find it better to just use the absolute in both files, keeping it consistent:
import 'package:myapp/themes/style.dart';
And just stick that rule throughout. So, basically, whatever method you use - Consistency is key!
The Linter for Dart package, also has something to say about this, but is more about the Don'ts of mixing in the '/lib' folder:
DO avoid relative imports for files in lib/.
When mixing relative and absolute imports it's possible to create
confusion where the same member gets imported in two different ways.
An easy way to avoid that is to ensure you have no relative imports
that include lib/ in their paths.
TLDR; Choose the one you prefer, note that prefer_relative_imports is recommended in official Effective Dart guide
First of all, as mentioned in this answer, Provider do not recommands package imports anymore.
Dart linter provides a list of rules, including some predefined rulesets :
pedantic for rules enforced internally at Google
lints or even flutter_lints (previously effective_dart) for rules corresponding to the Effective Dart style guide
flutter for rules used in flutter analyze
Imports rules
There is actually more than two opposites rules concerning imports :
avoid_relative_lib_imports, enabled in pedantic and lints rulesets, basically recommend to avoid imports that have 'lib' in their paths.
The two following are the one you mention :
prefer_relative_imports, enabled in no predefined rulesets, but recommended in Effective Dart guide in opposition to :
always_use_package_imports, enabled in no predefined rulesets. Which means that it is up to you and to your preferences to enable it (be careful, it is incompatible with the previous rule)
Which one should I choose?
Choose the rule you want ! It will not cause any performance issue, and no rule would reduce errors over the other. Just pick one and make your imports consistent across all your project, thanks to Dart linter.
I personnaly prefer using prefer_relative_imports, as it is recommended by Dart team, with this VSCode extension which automatically fix and sort my imports.
Provider do not need packages imports anymore.
This was a workaround to an old Dart bug: Flutter: Retrieving top-level state from child returns null
TL;DR, by mixing relative and absolute imports, sometimes Dart created a duplicate of the class definition.
This led to the absurd line that is:
import 'package:myApp/test.dart' as absolute;
import './test.dart' as relative;
void main() {
print(relative.Test().runtimeType == absolute.Test().runtimeType); // false
}
Since provider relies on runtimeType to resolve objects, then this bug made provider unable to obtain an object in some situations.
My 5 cents on the topic are that absolute (package:my_app/etc/etc2...) imports cause much less trouble than relative ones (../../etc/etc2...) when you decide to reorganize/cleanup your project`s structure because whenever you move a file from one directory to another you change the "starting point" of every relative import that this file uses thus breaking all the relative imports inside the moved file...
I'd personally always prefer absolute to relative paths for this reason
This question already has good answers, but I wanted to mention an insanely annoying and hard-to-find problem I experienced with unit testing that was caused by a relative import.
The expect fail indicator for an exception-catching expect block
expect(
() => myFunction,
throwsA(isA<InvalidUserDataException>())
);
was showing the actual result as exactly the same as the expected result, and zero indication of why it's failing.
After massive trial-and-error, the issue was because the expected InvalidUserDataException (a custom-made class) was being imported to the test file in RELATIVE format vs PACKAGE format.
To find this, I had to compare side-by-side, line-by-line, call-by-call between this test file and another test file that uses the exact same exception expecters (It's lucky, we had this), and just by chance, I happened to scroll to the top of this file's imports and see the blue underline saying prefer relative imports to /lib directory.
No, they're not preferred; they're necessary, because the moment I changed that to a PACKAGE (absolute) import, everything suddenly started working.
What I learned from this is: Use absolute imports for test files (files outside the lib directory)
e.g. inside of src/test/main_test.dart
DON'T: use import '../lib/main.dart'
DO: use package:my_flutter_app/main.dart
Maybe other people knew this already, but I didn't, and I couldn't find anything online with searches about this issue, so I thought I would share my experience that might help others who got stuck around this.
Does anyone know why this happens?
Edit: For context, this happened while using Flutter 2.1.4 (stable) with Sound Null Safety
Do you use Integration Tests?
If the answer is yes, then in most cases you need to use package imports. When you attempt to run your integration tests on a physical device, any relative imports will not be able to find what they're looking for.
Example: https://github.com/fluttercommunity/get_it/issues/76
You can enforce package imports in your project by using these two linting rules:
always_use_package_imports
avoid_relative_lib_imports
I also prefer package imports because they stick even when rearranging your files and folders. Relative imports frequently break and it's a pain to have to remove them and reimport the offending dependency.
One very simple reason to not use package imports: rename your package without editing every dart file
Renaming can happen a few times while the product does not have a definitive name, and you or your product owner decides to change it.
It is much more painful to rename with package imports as your package name is in every import.
Of course you can change it with a find/replace query, but it's a useless edit on every dart file you can avoid with relative imports.
Plus, vscode allows to automatically update relative imports on file move/rename and I have never had any issue with this feature.

I cant import another file

I can't import a file in Pycharm.
I use this code:
import useful_tools
This is the error:
Unused import statement, this inspection detects names that should resolve but don't. Due to dynamic dispatch and duck typing, this is possible in a limited but useful number of cases. Top level and class level items are supported better than instance items
The warning means you did not uses useful_tools in the code after the import. It will work in runtime, but it's useless if PyCharm is not mistaken of course. Please provide the whole script code, as it's hard to tell more.

Is there a way to tell Eclipse how to resolve ambiguous java names?

My eclipse is configured so that when I save the java source file, it automatically inserts the missing import declarations. Except when the reference is ambiguous. Fpr instance, the most annoying ambiguity is with List<T> - both java.util and java.awt declare it. Here eclipse demands manual resolution.
I was wondering if it was possible to configure somewhere that whenever List<T> is used then java.util should be imported. Or alternatively, since I am not using java.awt, I could just remove it from the list of possible suggestions.
Any ideas?
Thanks.
This sounds like a possible duplicate of Exclude packages from Eclipse's organize imports.
Basically, you want to change your Type Filters preference to exclude java.awt.* packages. Keep in mind that doing so will make things harder/confusing if you ever try to write AWT/Swing code.
One thing that pops into my mind is altering the class template in the preferences to include the line:
import java.util.List
Unless you are going to use the AWT version of a List, or care about unused import statements, that should solve this annoying issue ..
Manually invoke Organize Imports and it will ask you when an ambiguity is found.