🎸 Basic Flutter stuff.
For people who already know Android:
UI - Android needs XML integration whereas everything is a Widget in Flutter and can be made in a single file
Listeners No more listeners for onclicks, call the methods, change the state and enjoy the view
findView - No more findViewById() - just do everything inside the Widget(){} and leave the finding to Android
Gradle - No more gradle issues - add dependencies in the pubspec.yaml file and refresh the application to use the new libraries
Assets - Have to be managed separately in Flutter, you have to declare everything you use - For eg: images, fonts. In android, you can simply add it in the file section and use them.
Animations are much much easier and well supported in Flutter - Basic Uses - Eg: Splash activity, Swiping tabs, results, analytics page, navigation
Running the app - Hot reloading in Flutter - just hit 'r' for a reload and 'R' for a restart of the application. Android studio can take upto 20-30 seconds for each reload, and even more if there are gradle issues, which popup every once a while
API - Android APIs can be done with different libraries like Retrofit using GSON whereas fetching in Flutter can be done without any pain. The common Fetch function can be used in Flutter and have async await methods to call the APIs.
Recycler/List view - Recycler View is used in Android to create different lists on a screen. We need an adapter for that which has an interface and we need to know all sorts of different functions to completely implement it. Flutter just has a widget for a ListView where we can define different ListTiles or just add stuff dynamically. Much easier, looks simpler.
Learning Curve - Working in Flutter is easier once you know dart, which is similar to javascript, and understand the basic concepts about Widgets. Android allows you to make layouts with the help of the designer, which can be used to make constraint layouts. Making basic applications are definitely easier to learn in Android but as we go deeper in fragments and other stuff, it starts to get complicated
Fragments vs Components(widgets) - we can simply use the widget component wherever we want unlike the fragments we make in Android, which require some knowledge before hand on how to use Bundle, adapters, xml layouts, and different methods like onCreateView and layoutInflator
SQl database - It's pretty similar in both the technologies. The only difference is that state management can come into place if you're trying to add something consecutively, you would have to store the key in the state and change it using setState(){_key+=1} -> just a use case. The room library in Android is pretty wide used and easy to implement as well
Architecture patterns - Everything boils down to MVP/ MVVM/ MVC in Android, whereas we have BloC and Providers in Flutter, which do something similar to MVC, separating out the business logic by creating sinks and streams
Code Editor - VSCode/Android studio - Flutter and Android studio for android
Getting started guide - Pretty straighforward for Android, download the studio and get started, whereas you have to do a bunch of things for Flutter - can be annoying
Firebase - Resources for Flutter Firebase: -
https://flutter.dev/docs/development/data-and-backend/firebase
https://www.youtube.com/channel/UCFTM1FGjZSkoSPDZgtbp7hA/search?query=firebase
https://codelabs.developers.google.com/codelabs/flutter-firebase/#0
Firebase connection - Definitely easier to implement for Flutter, you can do it in 20 lines of code depending on the list view you make. The basics are the same, you need the .json files and have to add it to the firebase console. Coding in Flutter helps you understand it in a much better way. Overall it's similar.
Lists + Firebase - Android has crazy recycler views which make everything so hard, and integrating firebase + recycler view has about 200 articles, and you just cannot master it. There was no way I could've implemented something in Android without a tutorial, but in Flutter, you can always try
Fetching, Pushing Data - Pushing data is also easier in Flutter Firebase, there's literally an onTap() method which allows you to send a snapshot of the data
Machine Learning - Integrating machine learning
UI - Flutter and RN have a one file system, where you define the rules and UI. I personally like the interface for Flutter apps as it's much more defined. It's also maintained by Google which owns Android and can have a much better integration with Google.
Classes - Flutter uses Widgets for literally everything, from TextViews to TabViews - they're called 'Widgets'. Flutter uses dart, whereas React native uses Typescript or javascript.
Components - RN has components and we have to import them from 'react-native' to use them. Flutter has widgets which can be used in a similar space. Both of them are similar except the styling and the rendering part.
Styling Flutter - inside widgets - so if you want padding => you wrap the widget in Padding() widget with some padding, React Native: you define const style: Stylesheet and add your styles there - similar to the web style where you have css. So react native has css styling whereas Flutter has the 'widget' styling
Animations - Flutter is much easier to grasb, whereas react native has a wider aspect to it
Learning Curve - Similar in React native and Flutter.
Libraries - npm helps in react native whereas for flutter we just add them to the pubspec.yaml file
APIs - Both of them have a clear vision on using APIs. A good article for RN - https://medium.com/better-programming/handling-api-like-a-boss-in-react-native-364abd92dc3d
Code Editor - VS code is popular for both
Getting started - Personally, it's been really really hard to work with react native on windows. It's much better if you use a mac, but overall that red screen annoys you a lot. Flutter doesn't have the easiest getting started guide, but there is support out there to help you.
Overall - Both can make cross native apps and I'll choose Flutter anyday - hackathons/quick projects/learn android as well, and React native - web/ learn react.js/ -> if you want to stress yourself :P
fetch() async {
var url = "API-HERE";
var res = await http.get(url);
var body = jsonDecode(res.body);
// body is your API body
}
content description
to a button, textView etc in Android for voice oversclass App extends StatelessWidget{
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
home: Home(),
theme: ThemeData(primaryColor: PrimaryColor),//add-your-color here || or remove this
debugShowCheckedModeBanner: false,
);
}
}
class Home extends StatefulWidget{
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new _HomeState();
}
}
class _HomeState extends State<Home>{
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column()
);
}
child: users.length <= 0
? Center(
child: EmptyState(
title: 'Oops',
message: 'Add form by tapping add button below',
),
)
: ListView.builder(
addAutomaticKeepAlives: true,
itemCount: users.length,
itemBuilder: (_, i) => users[i],
),
)
fetch() async {
var url = "API-HERE";
var res = await http.get(url);
var body = jsonDecode(res.body);
// body is your API body
}
for(int i=0;i<body[0]['staggered_tiles'].length;i++){
_staggeredTiles.add(new StaggeredTile.count(
body[0]['staggered_tiles'][i]['cross_axis'],// body is what we get from the API
body[0]['staggered_tiles'][i]['main_axis']// body is what we get from the API
));
}
if (body[i][0]['type'] == 'donut') {
List<LabelPieSales> _d = [];
for (int j = 0; j < body[i][0]['data'].length; j++) {
_d.add(new LabelPieSales(
body[i][0]['data'][j]['year'], body[i][0]['data'][j]['sales']));// body is what we get from the API
}
_wid_top.add(new Container(
height: 200,
width: 200,
child: DonutChartWidget.withSampleData(_d),
));
}
else if (body[i][0]['type'] == 'label-pie') {
List<LabelPieSales> _d = [];
for (int j = 0; j < body[i][0]['data'].length; j++) {
_d.add(new LabelPieSales(
body[i][0]['data'][j]['year'], body[i][0]['data'][j]['sales']));// body is what we get from the API
}
_wid_top.add(new Container(
height: 200,
width: 200,
child: SimpleBarChart.withSampleData(_d),
));
}
return Container(
padding: const EdgeInsets.all(4.0),
child: appState.isFetching
? CircularProgressIndicator()
: appState.getResponseJson() != null
? ListView.builder(
primary: false,
shrinkWrap: true,
itemCount: appState.getResponseJson().length,
itemBuilder: (context, index) {
return Container(
height: 100,
width: 100,
child: graph(appState.getResponseJson()),
);
},
)
: Text("Press Button above to fetch data"),
);
initDB() async {
return await openDatabase(
join(await getDatabasesPath(), 'graphs_database.db'),
onCreate: (db, version) {
return db.execute(
"CREATE TABLE graphs(id INTEGER PRIMARY KEY, type TEXT)",
);
},
version: 1,
);
}
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () async {
Dog dog = new Dog(id: _id, name: "name",age: 22);
await insertDog(dog);
setState(() {
_id += 1;
});
},
),
List<Graph> graphs_sql = await graphs();
List<String> graphs_sql_types = [];
for(int i=0;i<graphs_sql.length;i++){
graphs_sql_types.add(graphs_sql[i].type);
}
if (graphs_sql.length != _types.length) {
for (int i = 0; i < _types.length; i++) {
if(!graphs_sql_types.contains(_types[i])){ // add only if a new type
await insertGraph(new Graph(id: i, type: _types[i]));
}
}
}
launchUrl() {
setState(() {
urlString = controller.text;
flutterWebviewPlugin.reloadUrl(urlString);
});
}
class News{
String dateAdded;
String title;
String body;
String level;
String category;
News(this.dateAdded, this.title, this.body, this.level, this.category);
}
class Record {
final String name;
final int votes;
final DocumentReference reference;
Record.fromMap(Map<String, dynamic> map, {this.reference})
: assert(map['name'] != null),
assert(map['votes'] != null),
name = map['name'],
votes = map['votes'];
Record.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data, reference: snapshot.reference);
@override
String toString() => "Record<$name:$votes>";
}
double _height = MediaQuery.of(context).size.height;
double _width = MediaQuery.of(context).size.width;
@override
void initState() {
// TODO: implement initState
super.initState();
_image = {url};
localList1 = globalList1;
localList1 = globalList2;
}
export const sendToTopic = functions.firestore
.document('recipes/{recipyId}')
.onCreate(async snapshot => {
// const recipe = snapshot.data();
const payload : admin.messaging.MessagingPayload = {
notification: {
title: 'new recipe added, check it out',
body: 'Make it and eat it'
}
};
return fcm.sendToTopic('recipes', payload);
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Recipes for you')),
body: _buildBody(context),
);
}
Widget _buildBody(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('recipes').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return LinearProgressIndicator();
return _buildList(context, snapshot.data.documents);
},
);
}
List<Recipe> recipe_list = [];
// snapshot.map((data) => recipeList(context, data).toList());
for(int i=0;i<snapshot.length;i++){
Recipe recipe = Recipe.fromSnapshot(snapshot[i]);
recipe_list.add(recipe);
}
return AsymmetricView(products: recipe_list,);