Flutter async executing on main thread - dart

I have a CameraPreview that fills the whole screen, with a FloatingActionButton at the bottom to take a picture.
On the onPress method of the button, I'm making a network call for which I do not care (yet) about the result. So I would like everything made inside that method to be done asynchronously, so it does not block my main thread.
That means (if I get it right) that I sould not use the await keyword.
This is the code in my onPressed
// Attempt to take a picture and log where it's been saved
await controller.takePicture(path);
print("Done taking picture");
sendBase64ToAPI(path);
This is my sendBase64ToApi method
Future<String> sendBase64ToAPI(String path) async {
File(path).readAsBytes().then(thenMethod);
return null;
}
void thenMethod(List bytes){
print("Start reading file");
Image image = decodeImage(bytes);
int x = ((screenWidth/2) + (overlayWidth/2)).toInt();
int y = ((screenHeight/2) + (overlayHeight/2)).toInt();
print("Start cropping image");
image = copyCrop(image, x, y, overlayWidth, overlayHeight);
var base64Str = base64.encode(image.getBytes());
print("Done");
print(base64Str.substring(0,30));
print(base64Str.substring(base64Str.length-30,base64Str.length-1));
}
My UI is completely frozen between 'Start reading file' and 'Start cropping image' although, those are async methods, called without await so that shouldn't happen.
Why are those methods not executing asynchronously ?

Okay, this seems to be a known issue from the library I'm using.
The documentation recommends to use the decodeImage function in an Isolate.
Will keep the question open for a few days, if someone spots what is synchronous in my code.

Related

Callback function if Vaadin Image src changes and update on client is complete

I'm using Vaadin 23 and I build an application which shows different images which are changed and loaded on runtime. I need the exact display size of the image to update other information based on the size. The server from which I get the image is quite slow, therefore it can last up to 10 seconds until the new image is downloaded by the client.
Image doesn't have a function like:
myImage.addSrcChangedAndClientUpdatedListener(...);
Is there any other solution to get a callback function in Java when the src Attribut changes and the new image is downloaded from the client?
My workaround is to wait 10 seconds and then get the image size by an async Javascript call.
But sometimes the image is ready after 2 seconds -> my implementation waits 8 seconds unnecessaryly which leads to bad customer experience.
Sometime the image download even takes 20 seconds -> my implementation doesn't work.
I don't see a proper solution. Any ideas? Can a implement a custom Java callback function based on custom Javascript code? How would such a solution look like?
Using Flow's Element API you can create a listener for the load DOM event that an img element fires after it has finished loading the image data. Using the element API you can also add several details to the event data that should be sent to the server. Here is a simple example that allows switching images, and then logs the image's size from the server:
public class ImageView extends Div {
private static final String IMAGE_1 = "https://imgs.search.brave.com/bjAqtSxNjNFNHm384o53EB6Zrv85eGtWpmspBqc98Yk/rs:fit:592:225:1/g:ce/aHR0cHM6Ly90c2Uy/Lm1tLmJpbmcubmV0/L3RoP2lkPU9JUC5X/ZzNXajk1SDl6VTNw/SzNMY2dwT2xRSGFG/NyZwaWQ9QXBp";
private static final String IMAGE_2 = "https://imgs.search.brave.com/v5uhvAoiVtMDM8UPI8vk8XMELrIRKW1fVLkRsiuqnU0/rs:fit:844:225:1/g:ce/aHR0cHM6Ly90c2Ux/Lm1tLmJpbmcubmV0/L3RoP2lkPU9JUC5O/OEV3U1psZlNZNmph/cmR1cm4xckZBSGFF/SyZwaWQ9QXBp";
public ImageView() {
Image image = new Image();
Button setImage1 = new Button("Set image 1", e -> image.setSrc(IMAGE_1));
Button setImage2 = new Button("Set image 2", e -> image.setSrc(IMAGE_2));
Span imageData = new Span();
image.getElement().addEventListener("load", loadEvent -> {
JsonObject eventData = loadEvent.getEventData();
Number width = eventData.getNumber("element.clientWidth");
Number height = eventData.getNumber("element.clientHeight");
imageData.setText(String.format("Width: %s | Height: %s", width, height));
})
.addEventData("element.clientWidth")
.addEventData("element.clientHeight");
add(image);
add(new Div(imageData));
add(new Div(setImage1, setImage2));
}
}
Reference:
Flow Element API - Listening to User Events
Window: load event

Why is this task await leaving the UI context in Xamarin iOS?

The following has somewhat shaken my async/await-based belief system. Under Xamarin/iOS the following fails, saying that UI-related things are being done in a non-UI thread. Adding check points shows that the context does in fact switch after the async file write.
My understanding is that lacking a ConfigureAwait, the following should be completely safe. I'm assuming this is a Xamarin nuance of which I'm unaware but it's difficult to understand what that could be.
This same code works fine on Android and UWP.
private async void ShareButton_OnClicked(object sender, EventArgs e)
{
if (!(BindingContext is PhotoViewModel photoViewModel))
{
return;
}
// in UI context
var name = photoViewModel.Name ?? "temp.jpg";
var file = Path.Combine(FileSystem.CacheDirectory, name);
using (var stream = new FileStream(file, FileMode.Create, FileAccess.Write))
{
await stream.WriteAsync(photoViewModel.Data, 0, photoViewModel.Data.Length);
}
// not in UI context!
// calling this causes SIGABRT: UIKit Consistency error
await Share.RequestAsync(new ShareFileRequest(new ShareFile(file)));
}
calling this causes SIGABRT: UIKit Consistency error
await Share.RequestAsync(new ShareFileRequest(new ShareFile(file)));
Although there is no problem in Android and UWP, it may not be compatible with such writing in iOS. Above line code needs UI thread to invoke , however it is in async method ShareButton_OnClicked. Maybe need to invoke it from Main thread specially, have a try with the follow code to invoke it.
await Device.InvokeOnMainThreadAsync(() =>
{
// inkoke your code .
Share.RequestAsync(new ShareFileRequest(new ShareFile(file)));
});
This turned out to be a bug in mono
https://github.com/mono/mono/issues/16759

Getting a Future from an ImageElement load

THis is a followup from Use of futures for async loading
My WebGL/Dart program needs to create lots of opengl data while initializing. It all gets loaded asynchronously and uses futures to process data when it is loaded and to know when all the required data is loaded.
I'm having trouble loading textures though. I have this code -
ImageElement img = new ImageElement();
img.onLoad.listen((e) {
baseTexture = gl.createTexture();
gl.bindTexture(TEXTURE_2D, baseTexture);
gl.texImage2DImage(TEXTURE_2D, 0, RGBA, RGBA, UNSIGNED_BYTE, img);
gl.texParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, LINEAR);
gl.texParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, LINEAR);
});
img.src = "base.png";
This works fine. It loads the image and makes a texture from it when it arrives.
However I need my main program to know when all my textures have arrived. Based on the previous question, I should use a future for each one and the use Future.wait to wait for them all to be ready.
However loading images as above doesn't use futures, it uses a StreamSubscription so I get no future back from this function to wait for.
How can I get a future object that will let me know when my texture is creater?
Can I create my own Future object and "signal" it in the callback? If I can do that it's not at all clear to me from the documentation how I do that.
You can indeed "signal" that a future is complete manually.
Future<Results> costlyQuery() {
var completer = new Completer();
database.query("SELECT * FROM giant_table", (results) {
// when complete
completer.complete(results);
});
// this returns essentially immediately,
// before query is finished
return completer.future;
}
The future completes when completer.complete(results); is executed.
From here: http://blog.sethladd.com/2012/03/using-futures-in-dart-for-better-async.html
You can use the property Future<T> first of the Stream class.
https://api.dartlang.org/docs/channels/stable/latest/dart_async/Stream.html#first
ImageElement img = new ImageElement();
Future future = img.onLoad.first.then((e) {
...
});
img.src = "base.png";

Is it possible to take photos programmatically without bringing the default camera application into foreground in blackberry.....?

I am developing an application which makes use of camera...and my app's requirement is :
I have to take photos from my "already running" background application ; but I have to keep camera application into background......means I want to capture picture without disturbing the current foreground applications.
and in addition without making any camera shutter sound....???
Is this possible If we call camera app - through Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA, new CameraArguments())...........
thanks to all of u...specially to #donturner
.....sorry to come back on this post very late.
after some attempts I hv found that without bringing the camera screen into foreground we cant capture the snap.
1) If we put the camera screen into background OR
2) change the visibility of VideoControl's class object as false...
_videoControl.setVisible(false);
then no bytes (null value) will be received by...
byte[] imageBytes = _videoControl.getSnapshot( encoding );
So whats the use of this function....while we r using the video control class for capture snap or video???
_videoControl.setVisible(true);
I hv tried a different trick......
I call a thread just before bring the camera screen into foreground to off the back-light of the device.
then soon after that I bring the camera screen into foreground and capture the snap.
I hv tested the above trick on BB Flip (4.6) and Storm (5.0) devices and it takes snapshots successfully even when device back light is OFF.
But now I become stuck on some other problem....and that is the camera SHUTTER sound. I hv tried a lot but couldn't get success to mute it....
as #Michael Donohue suggested, I hv tried..
private void muteThread() {
Thread t = new Thread(new Runnable() {
public void run() {
try {
int i = 0;
while (i < 50) {
Audio.setVolume(0);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
i++;
}
System.out.println("\n\n >>>>> End of Mute Thread. <<<< \n\n");
} catch (Exception e) {
}
}
});
t.start();
}
but it is not working... If this cant be done then how these application r providing this facility...and wht kind of functionality they hv used.
http://appworld.blackberry.com/webstore/content/97648/?lang=en
http://appworld.blackberry.com/webstore/content/79083/?lang=en
You cannot take a photo programmatically without displaying the camera preview feed to the user so at the very minimum you need to bring the camera preview surface into the UI foreground.

BlackBerry Please Wait Screen with Time out

Hello I am trying to create a please wait screen.This screen will appear when my program requests data from web service and will hide when the process is finished.Also I want to add a time out if request process lasts longer than 90 seconds.
can anyone help or show me a guiding example about that matter.
public static void showBusyDialog() {
try
{
if (busyDialog == null) {
busyDialog = new Dialog("Please Wait", null, null, 0, Bitmap.getPredefinedBitmap(Bitmap.HOURGLASS));
busyDialog.setEscapeEnabled(false);
}
synchronized (Application.getEventLock()) {
busyDialog.show();
}
}
catch(Exception e)
{
}
}
and my hiding code is
public static void hideBusyDialog() {
try
{
if (busyDialog == null) {
// busyDialog = new Dialog("Please wait...", null, null, 0, Bitmap.getPredefinedBitmap(Bitmap.HOURGLASS));
busyDialog.setEscapeEnabled(false);
}
synchronized (Application.getEventLock()) {
busyDialog.close();
}
}catch(Exception e)
{
}
}
Many BlackBerry® smartphone applications need to wait for some network activity (or another blocking operation, which must process in the background), while still holding up the User Interface (UI) and displaying a progress indicator.
You can follow through this links
Links
Sample "Please Wait" screen - part 1
Sample "Please Wait" screen - part 2
Sample "Please Wait" screen - part 4
you can download simple examples for Please wait screen
PleaseWait1.zip 25 KB
PleaseWait2.zip 25 KB
PleaseWait3.zip 25 KB
Note :in case above Links not working then just follow following contents
There seem to be two common issues when programming this:
1) As applications are not allowed to block the Event Thread, how do they get the UI processing to wait?
2)How can the background Thread update the UI?
This article is intended to help with these issues and provide a fully functioning "Please Wait" sample Popup Screen. However, as there is quite a lot to explain, in this first article, we will just create a popup screen that will show itself, hold up the UI, and then remove itself once the background processing has finished. This does not give us any progress indication, nor does it let the user cancel the wait. These points will be covered in a followup article. But the code supplied with this article will be useful anyway, especially when the duration of the background processing is not known and the user may not cancel the processing.
First, we start with the background processing we need to run. While this could be anything, typically this will be network processing, like the following:
httpConn = (HttpConnection)Connector.open(_url + ";deviceside=true");
responseCode = httpConn.getResponseCode();
responseMessage = "Response Code: " + Integer.toString(responseCode);
To initiate this network processing, we have a MainScreen that contains
1) A BasicEditField that allows the entry of a URL
2) A RichTextField that should display the response code (or error message). Here are the important parts of that screen:
BasicEditField _requestedURLField = new BasicEditField("http://", "www.blackberry.com", 255, BasicEditField.FILTER_URL);
RichTextField _responseField = new RichTextField("<response code>", RichTextField.NON_FOCUSABLE);
We would like the MainScreen to be updated with the result. As noted above, background processing can't directly update the UI; UI updating code must be on the Event Thread. There are several ways to get a background process onto the Event Thread, see the related article for more. In this case, we will use the following code:
// Make things final so we can use them in the inner class
final String textString = responseMessage;
final RichTextField rtf = _resultField;
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
rtf.setText(textString);
}
});
Now we must define the PleaseWaitPopupScreen to be displayed while waiting.
To give the user something to look at while they are waiting, we have an animated .gif, which is diplayed using the code in the AnimatedGIFField (see related link). And, so the user knows what they are waiting for, the PleaseWaitPopupScreen is supplied with a String to display, as the following constructor shows:
private PleaseWaitPopupScreen(String text) {
super(new VerticalFieldManager(VerticalFieldManager.VERTICAL_SCROLL | VerticalFieldManager.VERTICAL_SCROLLBAR));
GIFEncodedImage ourAnimation = (GIFEncodedImage) GIFEncodedImage.getEncodedImageResource("cycle.agif");
_ourAnimation = new AnimatedGIFField(ourAnimation, Field.FIELD_HCENTER);
this.add(_ourAnimation);
_ourLabelField = new LabelField(text, Field.FIELD_HCENTER);
this.add(_ourLabelField);
}
PleaseWaitPopupScreen provides a method – showScreenAndWait(..) – which will create and display the Popup screen, run the Background processing, and then dismiss the Popup screen.
The final piece of the puzzle involves supplying showScreenAndWait(..) with the processing to run.
Java has the concept of a Runnable, which is an Object that contains a public void run() method that should be executed. In this case, we have the Connection code and screen update code, given above, that should be executed. So, this code is packaged up into a new Runnable Object, which is supplied to showScreenAndWait(..). And here is that method. Note how a new Thread is created and run.
public static void showScreenAndWait(final Runnable runThis, String text) {
final PleaseWaitPopupScreen thisScreen = new PleaseWaitPopupScreen(text);
Thread threadToRun = new Thread() {
public void run() {
// First, display this screen
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(thisScreen);
}
});
// Now run the code that must be executed in the Background
try {
runThis.run();
} catch (Throwable t) {
t.printStackTrace();
throw new RuntimeException("Exception detected while waiting: " + t.toString());
}
// Now dismiss this screen
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().popScreen(thisScreen);
}
});
}
};
threadToRun.start();
}
And this is the key part of the PleaseWaitPopupScreen. Note how this code will create and display a Popup screen to the user, including an animated icon, while it is running the background processing. Input from the user is blocked by the Popup screen until the processing completes. The originating screen is updated as a result of the background processing.
Download the associated .zip archive, which contains the source included in this article.
In the next article, we will extend this code to be able to handle:
a) Status updates from the Background Thread
b) "Time to go" indication
c) Being cancelled by the BlackBerry smartphone user
Just put timer after you show busy dialog.
showBusyDialog();
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
hideBusyDialog();
}
};
timer.schedule(task, 9000);
this is for time out. If the process finishes less than 90 seconds you should call
timer.cancel();
timer = null;
task = null;

Resources