I have an app, collects WiFi and Bluetooth signals and displays them onto a Label
in a RecycleView
. When a Start Scan
button is pressed, we collect the data from an Android device and update Label.text
. The scan is then next carried out on a 10 second interval, GUI freezes for a brief moment, new data is appended to the Label and it keeps going.
def start_scanning(self, instance):
self.scan_network()
self.scan_event = Clock.schedule_interval(self.scan_network, 10)
The self.scan_event
is there for us to be able to stop or .cancel
network scan.
The understanding of Kivy I posses is that GUI is on a MainThread
. Because our scan happens on a MainThread
that leads to GUI freeze correct? Therefore, we need our scans to be carried out on a Thread although when I do try to get scans to be on another Thread it doesn't seem to work.
I'm pretty sure the issue is the Clock.schedule_interval
. We could have the label being continously updated in another Thread but on a interval would be preferred for now. How could I possibly unfreeze GUI?
Possibly is there a threading.Timer
way to replace Clock.schedule_interval
?
Let me know, if more reproducible example is required.
Edit: A more reproducible example was provided.
# This here updates the text in a label after scan_wifi or scan_bluetooth call this function to feed found network information
@mainthread
def update_text(self, new_results):
self.scanned_results = new_results + self.scanned_results
self.results_area.data = [{'text':str(result)} for result in self.scanned_results]
def get_wifi(self, *args):
# some logic
def get_bluetooth(self, *args):
# some logic
def scan_network(self, *args):
self.get_bluetooth()
self.get_wifi()
def start_scanning(self, instance):
self.scan_network()
# This here runs the function again but on interval my guess is this is what is freezing it.
self.scan_event = Clock.schedule_once(self.scan_network, 10)
# This function is called when on_press in a button.
def toggle_scan(self, *args):
# [...]
# above here we have some stopping logic
self.start_scanning(*args)
# These kinda work but after the first interval wave only mainthread appears and thread-1 just seems to hang there.
# with concurrent.futures.ThreadPoolExecutor() as self.executor:
# self.executor.submit(self.get_bluetooth)
# self.executor.submit(self.get_wifi)
# t = threading.Thread(target=self.start_scanning, args=(args))
# t.daemon = True
# t.start()
# t.join()
As per @JohnAnderson suggestion, we've went along with Threading for our scan_network
however, individual Threads for individual scans don't appear to wokr at the moment.
We've also used @mainthread
decorator on the update_text
so that we can update the value from different Thread without slowing out the MainThread
.