Hello does someone successfully added Bluetooth CPCL on your Flutter project? - android-studio
I tried to print in a ZEBRA ez320 Bluetooth printer I found out that it only works using cpcl code, the good news is I have the sample code for cpcl but I don't know how to integrate it on my Flutter project.
Can someone help me out?
This github https://github.com/devinim/flutter-zsdk has Zebra SDK Kit Flutter Integration
code snippet
devices = await FlutterZsdk.discoverBluetoothDevices();
devices.forEach((d) {
print('Device: ${d.friendlyName} [${d.mac}]');
});
...
d.sendZplOverBluetooth(FLUTTER_LOGO_ZPL),
full example code https://github.com/devinim/flutter-zsdk/blob/master/example/lib/main.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter_zsdk/flutter_zsdk.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
static const String FLUTTER_LOGO_ZPL = "^XA^CI28^PON^PW560^MNN^LL460^LH0,0^LT60" +
"^GFA,6150,6150,25,,gP01XFCgP03XF8gP07XF,gP0XFE,gO01XFC,gO03XF8,gO07XF,gO0XFE,gN01XFC,gN03XF8,gN0YF,gN0XFE,gM01XFC,gM03XF8,gM0YF,gL01XFE"
",gL01XFC,gL07XF8,gL0YF,gK01XFE,gK03XFC,gK07XF8,gK0YF,gJ01XFE,gJ03XFC,gJ07XF8,gJ0YF,gI01XFE,gI03XFC,gI07XF8,gI0YF,gH01XFE,gH03XFC,gH07XF8"
",gH0YF,gG01XFE,gG03XFC,gG07XF8,gG0YF,g01XFE,g03XFC,g07XF8,g0YF,Y01XFE,Y03XFC,Y07XF8,Y0YF,X01XFE,X03XFC,X07XF8,X0YF,W01XFE,W03XFC,W07XF8"
",W0YF,V01XFE,V03XFC,V07XF8,V0YF,U01XFE,U03XFC,U07XF8,U0YF,T01XFE,T03XFC,T07XF8,T0YF,S01XFE,S03XFC,S07XF8,S0YF,R01XFE,R03XFC,R07XF8"
",R0YF,Q01XFE,Q03XFC,Q07XF8,Q0YF,P01XFE,P03XFC,P07XF8,P0YF,O01XFE,O03XFC,O07XF8,O0YF,N01XFE,N03XFC,N07XF8,N0YF,M01XFE,M03XFC,M07XF8"
",M0YF,L01XFE,L03XFC,L07XF8,L0YF,K01XFE,K03XFC,K07XF8,K0YF,J01XFE,J03XFC,J07XF8,J0YF,I01XFE,I03XFC,I07XF8,I0XFE,001XFE,003XFCN03XF"
",007XF8N07XF,00XFEO0XFE,01XFCN01XFC,03XFCN03XF8,07XF8N07XF,0XFEO0XFE,1XFCN01XFC,3XF8N03XF8,7XF8N07XF,3WFEO0XFE,1WFCN01XFC,0WF8N03XF8"
",07VFO07XF,03UFEO0XFE,01UFCN01XFC,00UF8N03XF8,007TFO07XF,003SFEO0XFE,001SFCN01XFC,I0SF8N03XF8,I07RFO07XF,I03QFEO0XFE,I01QFCN01XFC,J0QF8N03XF8"
",J07PFO07XF,J03OFEO0XFE,J01OFCN01XFC,K0OF8N03XF8,K07NFO07XF,K03MFEO0XFE,K01MFCN01XFC,L0MF8N03XF8,L07LFO07XF,L03KFEO0XFE,L01KFCN01XFC,M0KF8N03XF8"
",M07JFO07XF,M03IFEO0XFE,M01IFCN01XFC,N0IF8N03XF8,N07FFO07XF,N03FEO0XFE,N01FCN01XFC,O0F8N03XF8,O07O07XF,O02O0XFE,X01XFC,X03XF8,X07XF,X0XFE,W01XFC"
",W03XF8,W07XF,W0XFE,V01XFC,V03XF8,V07XF,V0XFE,U01XFC,U03XF8,U07XF,U0XFE,T01XFC,T07XF8,T07XF,T03XF8,T01XFC,U0XFE,U07XF,U03XF8,U01XFC,V0XFE,V07XF"
",V03XF8,V01XFC,W0XFE,W07XF,W07XF8,W03XFC,X0XFE,X07XF,X07XF8,X03XFC,X01XFE,Y07XF,Y07XF8,Y03XFC,Y01XFE,g0YF,g07XF8,g03XFC,g01XFE,gG0YF,gG07XF8,gG03XFC"
",gG01XFE,gH0YF,gH07XF8,gH03XFC,gH01XFE,gI0YF,gI07XF8,gI03XFC,gI01XFC,gJ0XFE,gJ07XF,gJ03XF8,gJ01XFC,gK0XFE,gK07XF,gK03XF8,gK01XFC,gL0XFE,gL07XF,gL03XF8"
",gL01XFC,gM0XFE,gM07XF,gM03XF8,gM01XFC,gN0XFE,gN07XF,gN03XF8,gN01XFC,gO0XFE,gO07XF,gO03XF8,gO01XFC,gP0XFE,gP07XF,gR01VF8"
",^FS ^XZ";
List<ZebraBluetoothDevice> _devices = List();
#override
void initState() {
super.initState();
__init();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> __init() async {
List<ZebraBluetoothDevice> devices = List();
try {
devices = await FlutterZsdk.discoverBluetoothDevices();
devices.forEach((d) {
print('Device: ${d.friendlyName} [${d.mac}]');
});
} catch (e) {
showDialog(context: context, child: Text(e));
//throw e;
print('Error' + e);
}
if (!mounted) return;
setState(() {
_devices = devices;
});
}
String levelText = "Querying...";
_level(ZebraBluetoothDevice d) {
d.batteryLevel().then((t) {
setState(() {
levelText = t;
});
});
}
Widget _listPrinters() {
List<Widget> items = List();
if (_devices.length < 1) {
items.add(ListTile(
title: Text("Not found any or still searching"),
));
} else {
items.addAll([
ListTile(
title: Text("Found ${_devices.length} device(s)"),
),
SizedBox(height: 50),
]);
_devices.forEach((d) {
_level(d);
items.add(
ListTile(
title: Text(d.friendlyName),
subtitle: Text(d.mac + "[%${levelText}]"),
leading: IconButton(icon: Icon(Icons.list), onPressed: () => d.properties()),
trailing: IconButton(
icon: Icon(Icons.print),
onPressed: () => d.sendZplOverBluetooth(FLUTTER_LOGO_ZPL),
),
),
);
});
}
return ListView(
padding: EdgeInsets.all(24),
children: items,
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Zebra Plugin Example App'),
),
body: _listPrinters(),
),
);
}
}
Related
save string and associated icon with shared prefs
I'm currently using the shared preferences to save a string list. Every time the page is opened, for every string entry from the list I create a list tile inside a list view. But now I don't want to only save the string, I even want to save an icon with it. But I have absolutely no idea on how to solve this Here is my current code: import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:trainings_app/widgets/alertbox_widget.dart'; import 'package:trainings_app/widgets/team_widget.dart'; class TeamScreen extends StatefulWidget { #override _TeamScreenState createState() => _TeamScreenState(); } class _TeamScreenState extends State<TeamScreen> { late SharedPreferences sharedPreferences; List<String> teams = []; IconData? currentIcon; #override void initState() { tryFetchData(); super.initState(); } void tryFetchData() async { sharedPreferences = await SharedPreferences.getInstance(); if (!sharedPreferences.containsKey('teams')) { sharedPreferences.setStringList('teams', []); return; } teams = sharedPreferences.getStringList('teams') as List<String>; } #override Widget build(BuildContext context) { return Scaffold( body: ListView.builder( itemCount: teams.length, itemBuilder: (context, index) { return Team( teams[index], Icon(currentIcon), () => removeTeam(teams[index]), ); }, ), floatingActionButton: FloatingActionButton( onPressed: () { newTeam(); }, child: Icon( CupertinoIcons.add, ), ), ); } void newTeam() { showDialog<Alertbox>( context: context, builder: (BuildContext context) { return Alertbox('Namen auswählen:', addTeam); }, ); } void addTeam(String name, IconData? icon) { if (name.isNotEmpty) { setState(() { currentIcon = icon; teams.add(name); }); } Navigator.pop(context); sharedPreferences.setStringList('teams', teams); } void removeTeam(String name) { setState(() { teams.remove(name); }); sharedPreferences.setStringList('teams', teams); } } class Team extends StatelessWidget { final String name; final Icon icon; final Function remove; const Team(this.name, this.icon, this.remove); #override Widget build(BuildContext context) { return Container( padding: EdgeInsets.symmetric(horizontal: 22), child: ListTile( leading: Icon(icon.icon), contentPadding: EdgeInsets.symmetric(vertical: 8.0), title: Text( name, style: TextStyle( fontSize: 18.0, fontWeight: FontWeight.w600, ), ), trailing: IconButton( icon: Icon(CupertinoIcons.delete), onPressed: () => remove(), ), onTap: () { Navigator.push(context, MaterialPageRoute(builder: (context) => TeamWidget(name, icon))); }, ), ); } }
you can use each Icon specific id instead of IconData and store it as a List of Json: Json.encode({title:"test", icon:61668} and then save it in sharedPref. after that you can recall it as follows: Icon(IconData(**YOUR SELECTED ID**, fontFamily: 'MaterialIcons')); check the id of each icon here: link The other solution can be using images instead of icons! or using this site to convert image to font icon and use it as follows: Icon(IconData(int.parse('0x${e90a}', fontFamily: 'family name given in the link above'));
Failed Assertion 'url != null': is not true Error
I am still new to flutter and am learning building apps. I have been trying to run this code for but every time I run it I get a red screen on the android emulator and an error which goes "Failed Assertion: Line 22 pos 14 'url != null': is not true". This is my main file which runs the app import "package:flutter/material.dart"; import "src/app.dart"; voidmain() { runApp(MyApp()); } My App file has this code import 'package:flutter/material.dart'; import 'package:http/http.dart' show get; import 'models/image_models.dart'; import 'dart:convert'; import 'widgets/image_list.dart'; class MyApp extends StatefulWidget { createState() { return AppState(); } } class AppState extends State<MyApp> { int counter = 0; List<ImageModels> images = []; void fetchImage() async { counter++; var response = await get('http://jsonplaceholder.typicode.com/photos/$counter'); var imagemodel = ImageModels.fromjson(json.decode(response.body)); setState(() { images.add(imagemodel); }); } Widget build(context) { return MaterialApp( home: Scaffold( body: ImageList(images), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () { fetchImage(); }), appBar: AppBar(title: Text("Ola Amigo!")), )); } } Heres the ImageModel Class class ImageModels { int id; String url; String title; ImageModels(this.id, this.url, this.title); ImageModels.fromjson(Map<String, dynamic> parsedjson) { id = parsedjson[id]; title = parsedjson[title]; url = parsedjson[url]; } } and lastly the ImageList import 'package:flutter/material.dart'; import '../models/image_models.dart'; class ImageList extends StatelessWidget { final List<ImageModels> image; ImageList(this.image); Widget build(context) { return ListView.builder( itemCount: image.length, itemBuilder: (context, int index) { return buildImage(image[index]); }); } Widget buildImage(ImageModels image) { return Container( decoration: BoxDecoration( border: Border.all(color: Colors.grey) ), padding: EdgeInsets.all(20.0), margin: EdgeInsets.all(20.0), child: Image.network(image.url), ); } } Can someone please take a look at it and tell me what am I doing wrong and how can I resolve this issue. Thank you
You can copy paste run full code below You have error in ImageModels, please revise to code snippet factory ImageModels.fromjson(Map<String, dynamic> parsedjson) => ImageModels( parsedjson["id"], parsedjson["url"], parsedjson["title"], ); working demo full code import 'dart:convert'; import 'package:http/http.dart'; import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { createState() { return AppState(); } } class AppState extends State<MyApp> { int counter = 0; List<ImageModels> images = []; void fetchImage() async { counter++; var response = await get('https://jsonplaceholder.typicode.com/photos/$counter'); print(response.body); var imagemodel = ImageModels.fromjson(json.decode(response.body)); print(imagemodel.url); setState(() { images.add(imagemodel); print(images[0].url); }); } Widget build(context) { return MaterialApp( home: Scaffold( body: ImageList(images), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () { fetchImage(); }), appBar: AppBar(title: Text("Ola Amigo!")), )); } } class ImageModels { int id; String url; String title; ImageModels(this.id, this.url, this.title); factory ImageModels.fromjson(Map<String, dynamic> parsedjson) => ImageModels( parsedjson["id"], parsedjson["url"], parsedjson["title"], ); } class ImageList extends StatelessWidget { final List<ImageModels> image; ImageList(this.image); Widget build(context) { return ListView.builder( itemCount: image.length, itemBuilder: (context, int index) { print(image[index].url); return buildImage(image[index]); }); } Widget buildImage(ImageModels image) { return Container( decoration: BoxDecoration(border: Border.all(color: Colors.grey)), padding: EdgeInsets.all(20.0), margin: EdgeInsets.all(20.0), child: Image.network(image.url), ); } }
Flutter JSON data issue
I'm facing issue to fetch json data from Flutter mobile app. Code as follow: import 'package:flutter/material.dart'; import 'package:flutter_app/pages/main_page.dart'; class App extends StatelessWidget { #override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: "Flutter NodeJS", home: MainPage(), ); } } void main(){ runApp(App()); } main_page.dart import 'package:flutter/material.dart'; import 'package:flutter_app/modules/http.dart'; import 'package:flutter_app/pages/add_user_page.dart'; class MainPage extends StatefulWidget { #override State<StatefulWidget> createState() { return MainPageState(); } } class User { String id; String first_name,email; User(this.id, this.first_name,this.email); } class MainPageState extends State<MainPage> { List<User> users = []; Future<void> refreshUsers()async{ var result = await http_get('users'); if(result.ok) { setState(() { users.clear(); var in_users = result.data as List<dynamic>; in_users.forEach((in_user){ users.add(User( in_user['id'].toString(), in_user['first_name'], in_user['email'] )); }); }); } } #override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Users"), //email: Text("Email"), actions: <Widget>[ IconButton( icon: Icon(Icons.add), onPressed: (){ Navigator.of(context).push(MaterialPageRoute( builder: (context){ return AddUserPage(); } )); }, ) ], ), body: RefreshIndicator( onRefresh: refreshUsers, child: ListView.separated( itemCount: users.length, itemBuilder: (context, i) => ListTile( leading: Icon(Icons.person), title: Text(users[i].first_name+"\n" + users[i].email), //email: Text(users[i].email), ), separatorBuilder: (context, i) => Divider(), ), ), ); } } http.dart import 'dart:convert'; import "package:http/http.dart" as http; class RequestResult { bool ok; dynamic data; RequestResult(this.ok, this.data); } //'https://jsonplaceholder.typicode.com/users/1 //http://192.168.183.179:8081/api/users/ const PROTOCOL = "http"; const DOMAIN = "https://jsonplaceholder.typicode.com/users/1"; Future<RequestResult> http_get(String route, [dynamic data]) async { var dataStr = jsonEncode(data); var url = "$PROTOCOL://$DOMAIN/$route?data=$dataStr"; var result = await http.get(url); return RequestResult(true, jsonDecode(result.body)); } Future<RequestResult> http_post(String route, [dynamic data]) async { var url = "$PROTOCOL://$DOMAIN/$route"; var dataStr = jsonEncode(data); var result = await http.post(url, body: dataStr, headers:{"Content-Type":"application/json"}); return RequestResult(true, jsonDecode(result.body)); } When I'm fetch json data from "https://jsonplaceholder.typicode.com/users/1". Its working fine. enter image description here When I try to fetch json data from "https://192.168.183.179:8081/api/users". Its give error: at Object.createErrorWithStack (http://localhost:15340/dart_sdk.js:4348:12) at Object._rethrow (http://localhost:15340/dart_sdk.js:37892:16) at async._AsyncCallbackEntry.new.callback (http://localhost:15340/dart_sdk.js:37886:13) at Object._microtaskLoop (http://localhost:15340/dart_sdk.js:37718:13) at _startMicrotaskLoop (http://localhost:15340/dart_sdk.js:37724:13) at http://localhost:15340/dart_sdk.js:33243:9 What I'm doing wrong Regards, SAO
Check in Postman whether the ip address is returning data. Another case would be the data obtained, could not be transffered correctly to the app. Check the variables and types where the data is stored.
How to fix WillPopScope() not working for me
I created two pages one is login and main page but i want close app from main page i am using Willpopscope but it is not working for me i have tried all things but the onwillpop method is not calling please help me thank you. class main_page extends StatelessWidget { #override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData(primarySwatch: Colors.amber), home: my_page(), ); } } class my_page extends StatefulWidget { #override _my_pageState createState() => _my_pageState(); } class _my_pageState extends State<my_page> { #override void initState() { check_login(); super.initState(); } Future check_login() async { SharedPreferences preferences = await SharedPreferences.getInstance(); if (preferences.getBool("islogin") == false) setState(() { Navigator.of(context).push(MaterialPageRoute( builder: (context) => MyApp(), )); }); } #override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async=>false, child: Scaffold( appBar: new AppBar( title: Text( "Home", style: new TextStyle(color: Colors.white), ), actions: <Widget>[ FlatButton( onPressed: () async { SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); setState(() { sharedPreferences.setBool("islogin", false); Navigator.of(context).push(MaterialPageRoute( builder: (context) => main_page(), )); }); }, child: Text( "Logout", style: TextStyle(color: Colors.white, fontSize: 16.0), )) ], ), ), ); } } I am also using Shredprefrences but i think it does not matter i want close app from my main_page please help me for this Thank you.
Just check out this answer and let me know if it works: import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter/services.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { #override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData(primarySwatch: Colors.amber), home: SecondPage(), ); } } class LoginPage extends StatelessWidget { #override Widget build(BuildContext context) { return Scaffold( body: Container( child: Center( child: RaisedButton( child: Text('Move to second page after Login'), onPressed: () async { SharedPreferences preferences = await SharedPreferences.getInstance(); preferences.setBool("islogin", true); // this will remove the login page after routing to the second page and then the stack will have only one page that is second page. // so later you can use the willpopscape Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (context) => SecondPage()), ModalRoute.withName("/Home")); }, )), ), ); } } class SecondPage extends StatefulWidget { #override _SecondPageState createState() => _SecondPageState(); } class _SecondPageState extends State<SecondPage> { #override void initState() { check_login(); super.initState(); } Future check_login() async { SharedPreferences preferences = await SharedPreferences.getInstance(); if (preferences.getBool("islogin") == null) //This above if statement will check if the parameter islogin is null then redirect to the login screeen // else if the value is not null then i will not enter the if statement setState(() { Navigator.of(context).push(MaterialPageRoute( builder: (context) => LoginPage(), )); }); } Future<bool> _onWillPop() async { // This dialog will exit your app on saying yes return (await showDialog( context: context, builder: (context) => new AlertDialog( title: new Text('Are you sure?'), content: new Text('Do you want to exit an App'), actions: <Widget>[ new FlatButton( onPressed: () => Navigator.of(context).pop(false), child: new Text('No'), ), new FlatButton( onPressed: () => Navigator.of(context).pop(true), child: new Text('Yes'), ), ], ), )) ?? false; } #override Widget build(BuildContext context) { return WillPopScope( onWillPop: _onWillPop, child: Scaffold( appBar: new AppBar( title: Text( "Home", style: new TextStyle(color: Colors.white), ), actions: <Widget>[ FlatButton( onPressed: () async { SystemNavigator.pop(); }, child: Text( "Logout", style: TextStyle(color: Colors.white, fontSize: 16.0), )) ], ), ), ); } }
Here is answer example_page code class exmp extends StatefulWidget { #override _exmpState createState() => _exmpState(); } class _exmpState extends State<exmp> { #override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("example"), ), body: Column( children: <Widget>[ Center( child: RaisedButton(onPressed: () { Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute( builder: (context) => my_example(), ), (route) => false); }), ) ], ), ); } } And this is my second page my_example class my_example extends StatelessWidget { #override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData(primarySwatch: Colors.amber), home: my_examp(), ); } } class my_examp extends StatefulWidget { #override _my_exampState createState() => _my_exampState(); } class _my_exampState extends State<my_examp> { Future<bool> onbackpress() async{ return true; } #override Widget build(BuildContext context) { return WillPopScope( onWillPop: onbackpress, child: Scaffold( appBar: AppBar( title: Text("my_eaxmple"), ), ), ); } } The problem was i am pushing another page from my main page but i forget to remove first page for that i used the Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (context) => my_example()(route) => false); to remove the main page before navigate to another page
I was struggling with this problem, none of answers helped but finally I found the correct answer in BackButton widget source code. When we use WillPopScope on top of our widget, we should use maybePop instead of pop method that forces the Navigator to pop the last pushed page in order to let the WillPopScope widget decides the next action. Navigator.maybePop(context);
This is how you should use Future<bool> _willPopCallback() async { // await Show dialog of exit or what you want // then return true; // } //then use in the build like WillPopScope(child: new Scaffold(), onWillPop: _willPopCallback)
I resolved this error as in my case I have a parent screen and in that, I have PageView. I was trying to call WillPopScope in one of my PageView and then I realized my parent have WillPopScope too. That is why it is not calling WillPopScope of PageView
don't use on Scaffold(), wrap your MaterialApp as in the example bool allowed = false; return WillPopScope( onWillPop: () async { print('MJD POP TRYING TO GET BACK from login Page'); return Future.value(allowed); }, child: MaterialApp( title: 'Your App Title', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyLoginPage(title: 'Login Page'), ), );
Is there a way to send a request after the user has stopped typing?
I am looking for a way to send an API request after the user has stopped typing for X amount of seconds. The way I am sending the request is through the onTextChanged callback, however, that sends a request on every key press I have seen ways to do this with a timeout in React, however, I am relatively new to flutter so any help would be appreciated
you can use the below code to do this: import 'package:flutter/material.dart'; import 'dart:async'; class Test extends StatefulWidget { #override State<StatefulWidget> createState() { return _TestState(); } } class _TestState extends State<StatefulWidget> { Timer searchOnStoppedTyping; _onChangeHandler(value ) { const duration = Duration(milliseconds:800); // set the duration that you want call search() after that. if (searchOnStoppedTyping != null) { setState(() => searchOnStoppedTyping.cancel()); // clear timer } setState(() => searchOnStoppedTyping = new Timer(duration, () => search(value))); } search(value) { print('hello world from search . the value is $value'); } #override Widget build(BuildContext context) { return TextField( onChanged: _onChangeHandler, decoration: InputDecoration( hintText: 'Search ....' ), ); } }
The usual way to do this in Flutter is using RxDart and its debounce() method. It allows to wait a small period before launching a specific call. In the following full example you see it in action with a time of 1 second. In the example, a message is shown where the call to the server should be dispatched. import 'package:flutter/material.dart'; import 'package:rxdart/rxdart.dart'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { #override Widget build(BuildContext context) { return new MaterialApp( home: new MyHomePage(), ); } } class MyHomePage extends StatefulWidget { #override _MyHomePageState createState() => new _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { final subject = new PublishSubject<String>(); bool isLoading = false; GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey(); void _textChanged(String text) { if (text.isEmpty) { setState(() { isLoading = false; }); return; } setState(() { isLoading = true; }); scaffoldKey.currentState.showSnackBar(new SnackBar( content: new Text("Search for ${text}"), )); } #override void initState() { super.initState(); subject.stream.debounce(new Duration(milliseconds: 1000)).listen(_textChanged); } #override void dispose() { subject.close(); super.dispose(); } #override Widget build(BuildContext context) { return new Scaffold( key: scaffoldKey, appBar: new AppBar( title: new Text("Debounce demo"), ), body: new Container( padding: new EdgeInsets.all(8.0), child: new Column( mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ new TextField( decoration: new InputDecoration( hintText: 'Type text to search', ), onChanged: (string) => (subject.add(string)), ), isLoading ? Padding( padding: const EdgeInsets.all(20.0), child: new CircularProgressIndicator(), ) : new Container(), ], ), ), ); } } You can see this code in action in the following article and code by Norbert Kozsir