I am currently working on two Flutter apps that share about 90% of their functionality. Because of this, I have built most of the code as a library, and then have the two projects set up to import that library. I can then plug in two different CMS instances, and different Firebase services ... super-efficient.
The problem I have is that my library code has certain references that I would need to override in my projects to allow for bespoke menu items, theme settings etc.
A good example is a MenuItem enum that is used throughout my library code for navigation and routing etc. It builds the entire app structure off a list of these MenuItem types. I need to define a MenuItem enum for both of my projects, but the error I get is a conflict between the project and the library.
{MenuItem menuItem}
The argument type 'MenuItem (where MenuItem is defined in /Users/xx/Documents/dev/xx Creative/dev/AR_Trails_app/ar_trails_app/lib/utils/menu_items.dart)' can't be assigned to the parameter type 'MenuItem (where MenuItem is defined in /Users/xx/Documents/dev/xx Creative/dev/AR_Trails_Lib/weald_ar_trails/lib/utils/menu_items.dart)'.dartargument_type_not_assignable
menu_items.dart(7, 6): MenuItem is defined in /Users/xx/Documents/dev/xx Creative/dev/AR_Trails_app/ar_trails_app/lib/utils/menu_items.dart
menu_items.dart(8, 6): MenuItem is defined in /Users/xx/Documents/dev/xx Creative/dev/AR_Trails_Lib/weald_ar_trails/lib/utils/menu_items.dart
I know that there is an option to use dependency_overrides in Dart but this is for overriding the entire library I think: https://dart.dev/tools/pub/dependencies#dependency-overrides
How can I do this but for just one file? Or maybe two or three?
UPDATE:
To be clear on the use-case here: my file menu_items.dart is in the library package, and it is used throughout to build the navigation and drawer etc. But it is only used in the library. What I need to do is override that file in each project so that the reference the library uses is the project's local version and NOT the one that is being referenced in the library. I thought that if I used as a path reference to the file like ../../utils/menu_items, and mirrored that in my project, it might use the local project version. It doesn't.
Related
I am using Flutter. As you are aware, Flutter doesn't have protected keyword to make classes package private. But interestingly, the same could be achieved using library, part, part of keywords once I name widgets starting with underscore. But, I am a bit worried about performance issues.
Question: Is it ok to use library/part/part of keywords inside ordinary projects?
public classes inside lib/src are considered package private. Only classes in lib are truly public, so are files in lib/src when they get exported by a file in lib.
enchilada/
lib/
enchilada.dart <-- public
src/
beans.dart <-- package private unless exported
While technically you can access everything in lib/src, you get a warning when you use implementation files.
Don't use part
The part keyword can not be used to hide code, it inherits the same visibility as the library. All it does is splitting a file into multiple files. It should only be used for code generation these days https://stackoverflow.com/a/27764138/669294
Note: You may have heard of the part directive, which allows you to split a library into multiple Dart files. We recommend that you avoid using part and create mini libraries instead.
source
Performance
Visibility doesn't affect performance in any way.
Naming your entity starting with an underscore (for example _test) should make it private.
Libraries not only provide APIs, but are a unit of privacy: identifiers that start with an underscore (_) are visible only inside the library. Every Dart app is a library, even if it doesn’t use a library directive.
Source
Looks like Flutter for Web and Flutter for Mobile have to exist as separate projects due to the imports.
Example:
import 'package:flutter_web/material.dart
vs
import 'package:flutter/material.dart';
Is there anyway to build one flutter project with one code base that works for both web and mobile (ios/android)? If not, is this coming?
If so, can you provide an example app?
Would like to just make one code base for the web and mobile and not have to maintain separate projects/code repos.
The OP's question is a bit old and is no longer applicable at the time of posting(7/21/2020). Flutter now has consolidated web into the main flutter package, which prevents us from running into issues with imports like this. flutter_web is no longer a separate package.
However, you may have been able to accomplish this even at the time you posted your question with conditional imports. This answer provides an excellent method of doing this. The following are the essentials of that post:
The core idea is as follows.
Create an abstract class to define the methods you will need to use in general.
Create implementations specific to web and android dependencies which extends this abstract class.
Create a stub which exposes a method to return the instance of this abstract implementation. This is only to keep the dart analysis tool happy.
In the abstract class import this stub file along with the conditional imports specific for mobile and web. Then in its factory constructor return the instance of the specific implementation. This will be handled automatically by conditional import if written correctly.
This method allows for you to do these imports based on platform and applies to all packages that may not support every possible flutter platform(e.g. dart:html, dart:js, dart:js_util, dart:io).
I created a library that uses the native navigation controller to navigate through react and native screens. The library is written in Swift and contains some objective-c code to setup the React bridge etc. Currently I can distribute this library through CocoaPods by creating a podspec and defining the React dependency there. However, this forces the user to setup React in their project through CocoaPods as well (like so: https://facebook.github.io/react-native/docs/integration-with-existing-apps.html). I'd like them to use the react-native link or manually linking option as well (like so: https://medium.com/#joshyhargreaves/adding-react-native-to-existing-ios-project-without-cocoapods-6f1ee9106009).
If I understand correctly I can create a static library and distribute that. So far I created this static library, added my mixed swift and objective-c code and tried to manually link it into my main project. This however produces an error in one of my classes inside my static library where I import React like so import React. Error is "No such module 'React'.
I updated the Header Search Paths of my static library to contain:
$(SRCROOT)/../react-native/React
and
$(SRCROOT)/../React
(react-native, React and my own lib are all inside the node_modules folder)
both set to recursive. Unfortunately it still doesn't find the module React. Does anyone know how to create a static library that contains a dependency with React?
The end goal would be to import this static library in my main project like import MyStaticNaivationLib in one of my viewcontrollers and subclass from a class that's defined in my static library.
My main project also uses https://github.com/rebeccahughes/react-native-device-info. This looks exactly what I want to achieve. It's a static library that has a dependency with React ("import RCTBridgeModule.h") which I can manually link in my main project. Only difference is that this project doesn't contain Swift code.
I wrote a custom module for the company, and you can view my documentation. This custom module have inner framework and I link this framework to the main project. In your custom_modulem do you have package.json with this?
"peerDependencies": {
"react": "16.8.3",
"react-native": "0.59.4"
}
https://github.com/Hardy1207/RNOkay
We have an Eclipse IDE application on 3.x that uses various newWizards to allow the user to create different files. Although these files differ slightly contentwise, the structure of the wizards is quite similar.
Thus, a sound object-oriented approach would be to instantiate different wizards from the same class and initialize them with different data.
Problem:
To decide what wizard needs which data we need a way to distinguish the different already instantiated wizards (e.g during the call to the init method of the wizard).
Is there any way to do so? It would e.g. help if somebody knows a way to get the wizard's id defined in the extension point from within the instantiated wizard.
If your wizard implements IExecutableExtension, it will be passed the configuration element that represents the extension for which it is created.
You can also use extension factories in that you specify a type that implements IExecutableExtensionFactory.
The interface allows you to control how the instances provided to extension-points (wizards in your case) are created.
Extension example:
<extension point="org.eclipse.ui.wizards">
<newWizard
name="..."
class="com.example.WizardFactory">
</newWizard>
Note that the extension factory may also implement IExecutableExtension to gain access to extension attributes before creating the extension's executable class.
I have a Qt application containing a Webkit module and using Dart (compiled to JS). It's like a bare-bones browser written in Qt. The application basically replaces certain text on the webpage with different text. I want users to be able to make their own Dart files to replace their own text with their own different text.
Any recommendations for approaches to creating a plugin system?
I think that this question needs a little clarification: are you asking about using Dart for scripting Qt applications (where Dart plays the role of a scripting language), or are you asking about a plugin system for Dart application that is compiled to JS and used in a Qt application, probably via QtScript (in which case, the role of a scripting language is played by JavaScript)?
I presume that it is the latter variant (and I don't know enough about Qt to be able to answer about the former variant anyway).
Let's assume that all plugins for the Dart application are available at the build time of that Qt application, so that you don't need to compile Dart to JS dynamically. Then, if you compile a Dart script, resulting JS will include all necessary code from its #imports. All you need is to create a proper script that imports all plugins and calls them (importing isn't enough, as dead code will be eliminated).
Maybe an example will be more instructive. Let's say that you want to allow plugins to do some work on a web page. One way you might structure it is that every plugin will be a separate #library with a top-level function of a well known name (say doWork). Example of a plugin:
// my_awesome_plugin.dart
#library('My Awesome Plugin')
doWork(page) {
page.replaceAll('JavaScript is great', 'Dart is great');
}
You can have as many plugins of this nature as you wish. Then, you would (at the build time) generate a following simple main script in Dart:
// main.dart
// these lines are automatically generated -- for each plugin file,
// one #import with unique prefix
#import('my_awesome_plugin.dart', prefix: 'plugin1');
#import('another_plugin.dart', prefix: 'plugin2');
main() {
var page = ...; // provided externally, from your Qt app
// and these lines are automatically generated too -- for each plugin,
// call the doWork function (via the prefix)
plugin1.doWork(page);
plugin2.doWork(page);
}
Then, if you compile main.dart to JavaScript, it will include all those plugins.
There are other possibilities to structure the plugin system: each plugin could be a class implementing a specific interface (or inheriting from a specific base class), but the general approach would be the same. At least the approach that I would recommend -- making each plugin a separate library.
You probably don't like the step with generating the main script automatically, and I don't like it either. But currently, Dart only allows one way to dynamically load new code: spawning new isolates. I'm not sure how (or even if) that would work in QtScript, because isolates are implemented as web workers when compiled to JavaScript, so I won't discuss this here.
Things will get more complicated if you want to support compiling Dart scripts at the runtime of your Qt application, but I think that I'm already guessing too much about your project and I might be writing about something you don't really need. So I'll finish it like this for now.