edufolly / flutter_bluetooth_serial

A basic Flutter Bluetooth Serial
MIT License
479 stars 465 forks source link

A question about "connection.input.listen". #112

Open piggy-w opened 3 years ago

piggy-w commented 3 years ago

Problem

Hello! I'm working on a project which is using blue-tooth for data transmission. Your work has been very helpful to me.

Recently, I had a problem on "listen" (a method of connection.input). My app has a main page A, in page A, there are many sub-pages(B, C and D). When I run this app ,it starts page A, then I go to page B, I connect my other blue-tooth device with my phone in this page, it works well. Then I return to page A and enter to page C, in page C, I start method "connection.input.listen" , it also works well, it can receive data from other blue-tooth device correctly. But when I return to page A(from page C) and enter page D, I find it can not start connection.input.listen-method, the information tells me that I have already start it in page C.

But I find that if I finish the connection when exits page C, it works, but it seems a bit troublesome reconnecting to the original device. So, my question is how can I just shutdown the connection.input.listen-method in page C when I return to page A, but keeps connecting to the original device, so that I can start this method in page D?

Looking forward to your reply, thank you very much!

AgainPsychoX commented 3 years ago

You should have shared model/object between all the pages, which encapsulates communication with the device you are connected to. Please take a look at example app code. There is BackgroundCollectingTask, which is started at MainPage and used in other page and also in the background. The class manages whole connection, after it was started. It have single connection.input.listen. In your object you could have broadcast stream, or allow to register some call back function for incoming data - so you register it on C/D page start and unregister at their dispose,

https://github.com/edufolly/flutter_bluetooth_serial/blob/a79eb251c4ace655e2db849ab061e5ada11c2baa/example/lib/BackgroundCollectingTask.dart#L41-L69

The object itself is stored at MainPage too, and passed to other pages as they come up, in the example using neat ScopeModel which ease such passing: https://github.com/edufolly/flutter_bluetooth_serial/blob/a79eb251c4ace655e2db849ab061e5ada11c2baa/example/lib/MainPage.dart#L301-L304 https://github.com/edufolly/flutter_bluetooth_serial/blob/a79eb251c4ace655e2db849ab061e5ada11c2baa/example/lib/BackgroundCollectedPage.dart#L7-L11

I suggest creating similar class for you application. For example, let's say you have some DIY 3D printer. So you could have My3DPrinter which can be constructed from already created bare connection, and then this class would be shared to everywhere it would be needed. The same time, this class would have all the bare methods that operate your device, instead packing implementation of those methods in multiple pages, i.e. setTemperature, moveX, moveY, moveZ, pushMaterial, etc, or larger methods i.e print3DModelFromBinary.

Such encapsulation is good practice. Imagine opposite - you have your connection code shattered around multiple pages:

Imagine user starting the print which could take a while, as your app sends next printing layers data. In meanwhile, user goes back to main page. What would happen? Data living in A page object could get disposed, any futures/processes could stop, and your printer would end up in bad state (imagine heating up 3D printer for no reason, or being stuck on pushing material...).

With proper encapsulation, both A and B pages would just ask your My3DPrinter shared object to print3DModelFromBinary, which could result in error if there already is ongoing process at the printer. What's more, you could add some field to the class indicating whenever there is such ongoing process, so you could lock the button and show message "Something else is already being printed".

By the way, the 3D printer controller application is bad idea for mobile phone app, but it was first I got in my mind.

Also, you asked for listening: it's very similar thing. Imagine some scanner, which also take some time to do the scan. If there is code to start scan and listen for data in the A page and user exits the page, scanner could still sending the data. If user re-enters and click scan again, app could receive data from already ongoing scanning.

piggy-w commented 3 years ago

Thank you for your detailed reply, your example is very apposite! Wish you have a good day at work.