Continue code when awaited PushModalAsync Page is closed Xamarin.Forms - asynchronous

I have a method like this:
public async Task BtnLoad_OnClick()
{
MediaPage galleryPage = new MediaPage();
await Application.Current.MainPage.Navigation.PushModalAsync(galleryPage);
try
{
//some logic here;
}
catch (Exception ex)
{
//
}
}
My intention was to open MediaPage() and wait until it is closed before the try{}catch{} follows.
As of now, as soon as the MediaPage opens, the try{}catch{} is executed straight away, and this is not what I intend.
How can I wait until the PushModalAsync(galleryPage) is closed?

OK.
I found the solution:
galleryPage.Disappearing += (sender2, e2) => {//after closing logic here.}

Related

How to know the popped state of a NavigationPage in Xamarin

I want it to popup or not to popup by receiving the On and Off events.
I received the On event and popped it up. Off event has [await Navigation.PopAllPopupAsync(false); ] to clear the popup.
There are cases where the off event comes in twice. If there is no currently popped page, await Navigation.PopAllPopupAsync(false); will throw an exception. So I want to know if there is a flag to know if there is currently popped screen.
How to know which page is currently popped up
Fix #1:
You could make the exception harmless:
try
{
await Navigation.PopAllPopupAsync(false);
}
catch (Exception ex)
{
}
Fix #2:
You could keep track of it yourself:
public static bool PopupIsShowing;
// In On event, Just before (or just after) you show it.
PopupIsShowing = true;
// In Off event,
if (PopupIsShowing) {
PopupIsShowing = false;
await Navigation.PopAllPopupAsync(false);
}

Catch Socket Exception [duplicate]

This is probably a noob question, but how do I make my response throw an exception if the user does not have an internet connection or if it takes too long to fetch the data?
Future<TransactionModel> getDetailedTransaction(String crypto) async {
//TODO Make it return an error if there is no internet or takes too long!
http.Response response = await http.get(crypto);
return parsedJson(response);
}
You should surround it with try catch block, like so:
import 'package:http/http.dart' as http;
int timeout = 5;
try {
http.Response response = await http.get('someUrl').
timeout(Duration(seconds: timeout));
if (response.statusCode == 200) {
// do something
} else {
// handle it
}
} on TimeoutException catch (e) {
print('Timeout Error: $e');
} on SocketException catch (e) {
print('Socket Error: $e');
} on Error catch (e) {
print('General Error: $e');
}
Socket exception will be raised immediately if the phone is aware that there is no connectivity (like both WiFi and Data connection are turned off).
Timeout exception will be raised after the given timeout, like if the server takes too long to reply or users connection is very poor etc.
Also don't forget to handle the situation if the response code isn't = 200.
You don't need to use http to check the connectivity yourself, simply use connectivity library
You can use this plugin https://pub.dev/packages/data_connection_checker
So you can check prior if you have the connection, if not give a alert to the user that no internet connection. And if you have the internet connection then just proceed to your fetching part.
I will just link some resources below where it has been explained perfectly:
https://www.youtube.com/watch?v=u_Xyqo6lhFE
This is all things will be done prior to making an http call, but what if while making an http call the internet goes off then you can use the try catch block which #uros has mentioned.
Let me know if it works.
This is my approach to check internet connection to check internet connection throughout full app
i create a common class called "connectivity" & use it everywhere in app to check connectivity.i use connectivity package by flutter.
My connectivity class
Future<bool> check() async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
return true;
} else if (connectivityResult == ConnectivityResult.wifi) {
return true;
}
return false;
}
then i use this class like this:
#override
void initState() {
super.initState();
checkInternetConnection().then((internet) {
if (internet != null && internet) {
// Internet Present Case
// do your task;
} else {
// No-Internet Case
showAlertDialog(context);
}
});
}

Plugin BLE (v1.3.0) delay after characteristic.ReadAsync()

I’m developing an app and I want to read some characteristics one after one.
My issue is that after a read is done I must do a delay otherwise I get an error.
Why does it need a delay ? is there a way to write correctly read tasks one after other ?
I'm using Xamarin.forms and Ble v1.3.0 plugin.
I've tried "await Task.Delay(200)" between two consecutive ReadAsync() functions and it works fine but if I remove the delay, the second ReadAsync gets exception.
private async Task ReadChr(ICharacteristic LocalCharacteristic)
{
byte[] localData = { };
if (LocalCharacteristic.CanRead)
{
try
{
return localData = await LocalCharacteristic.ReadAsync();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
return null;
}
}
}
if (firstCharacteristic.CanRead)
{
var ccc = await ReadChr(firstCharacteristic);
}
await Task.Delay(200);
if (secondCharacteristic.CanRead)
{
var ddd = await ReadChr(secondCharacteristic);
}
I'm searching something like polling the read process status of the characteristic. Delay after ReadAsync does not seem a good practice coding.
Any idea ?

Unable to Access SQLite Data in MvvmCross ViewModel

Hello StackOverflow community,
I know there's a lot of code in this post, but I wanted to give you guys, the community as good of a picture as possible as to what is going on here so that maybe someone can help me figure out what my issue is.
Recently for a project I'm working on we've decided to upgrade from MvvmCross 5.7.0 to 6.2.2. I've managed to get our UWP app to successfully complete the initialization and setup process. The first viewmodel for which we register the app start also starts initializing. However, I'm finding that my vm initialization hangs at a particular line of code (shown in the code below). The weirdest part though is similar methods called in the app initialization code run perfectly fine without hanging/deadlock, so I'm not sure what's different Here's a simplified version of my viewmodel code to illustrate:
public class MyViewModel : BaseAuthenticatedTabBarViewModel, IMvxViewModel<int>
{
private int? _settingValue;
public override async Task Initialize()
{
//Some irrelevant initialization code
Exception e = null;
try
{
//This line of code never returns
_settingValue = _settingValue ?? await AppSettingService.GetSettingValue();
}
catch (Exception ex)
{
e = ex;
}
if (e != null)
{
await HandleCatastrophicError(e);
}
}
}
The AppSettingService.GetSettingValue() method looks like this:
public async Task<int?> GetCurrentEventId()
{
return await GetNullableIntSetting("SettingValue");
}
private static async Task<int?> GetNullableIntSetting(string key)
{
try
{
var setting = await SettingDataService.SettingByName(key);
if (setting != null)
{
return string.IsNullOrEmpty(setting.Value) ? (int?)null : Convert.ToInt32(setting.Value);
}
}
catch (Exception ex)
{
//Handle the exception
}
return null;
}
All the code for SettingDataService:
public class SettingDataService : DataService<SettingDataModel>, ISettingDataService
{
public async Task<SettingDataModel> SettingByName(string name)
{
try
{
var values = (await WhereAsync(e => e.Name == name));
return values.FirstOrDefault();
}
catch(Exception ex)
{
//Handle the exception
}
return null;
}
}
Finally, the implementation for WhereAsync() is in a class called DataService and is as follows:
public virtual async Task<IEnumerable<T>> WhereAsync(System.Linq.Expressions.Expression<Func<T, bool>> condition, SQLiteAsyncConnection connection = null)
{
return await (connection ?? await GetConnectionAsync())
.Table<T>()
.Where(condition)
.ToListAsync();
}
Thank you very much for your help in advance
Edit: Forgot to also add this crucial bit of code to help you guys even further:
protected async Task<SQLiteAsyncConnection> GetConnectionAsync()
{
SQLiteAsyncConnection connection = null;
while (true)
{
try
{
connection = Factory.Create(App.DatabaseName);
// This line of code is the culprit. For some reason this hangs and I can't figure out why.
await connection.CreateTableAsync<T>();
break;
}
catch (SQLiteException ex)
{
if (ex.Result != Result.CannotOpen && ex.Result != Result.Busy && ex.Result != Result.Locked)
{
throw;
}
}
await Task.Delay(20);
}
return connection;
}
I'm suspecting that you are calling Task.Wait or Task<T>.Result somewhere further up your call stack. Or if you're not doing it, MvvmCross is probably doing it for you. This will cause a deadlock when called from a UI context.
Personally, I prefer the approach that ViewModels should always be constructed synchronously, and cannot have an asynchronous "initialization". That is, they must construct themselves (synchronously) into a "loading" state, and this construction can kick off an asynchronous operation that will later update them into a "loaded" state. The synchronous-initialization pattern means there's never an unnecessary delay when changing views; your users may only see a spinner or a loading message, but at least they'll see something. See my article on async MVVM data binding for a pattern that helps with this, and note that there's a newer version of the helper types in that article.

SignalR Start()'s task is continuing even if connection is not possible

I have a C# SignalR client and I want to do some actions upon success/failure of the connection to my server. Here is my code :
this.connection.Start().ContinueWith(task =>
{
if (task.IsFaulted)
{
this.OnRaiseServerConnectionClosedEvent();
}
else
{
this.JoinGroup();
this.StopTimer();
this.OnRaiseServerConnectionOpenedEvent();
}
});
}
The else block is always executed, not caring if a server is here or not...
I have also tried with await or with Wait() but same scenario.
I understand .net tasks correctly I think but here I am stuck.
Right now my code looks like
try
{
this.connection.Start().Wait();
if (this.connection.State == ConnectionState.Connected)
{
this.JoinGroup();
this.StopTimer();
this.OnRaiseServerConnectionOpenedEvent();
}
}
catch (AggregateException)
{
this.OnRaiseServerConnectionClosedEvent();
}
catch (InvalidOperationException)
{
this.OnRaiseServerConnectionClosedEvent();
}
When no server is present, the task created by the Start() method returns without fault and with status connecting. You have to check the state of the connection if you want to follow with some actions or retry connecting.
The task you are receiving from Connection.Start is likely cancelled due to a timeout instead of being faulted. This should be an easy fix:
this.connection.Start().ContinueWith(task =>
{
if (task.IsFaulted || task.IsCanceled)
{
this.OnRaiseServerConnectionClosedEvent();
}
else
{
this.JoinGroup();
this.StopTimer();
this.OnRaiseServerConnectionOpenedEvent();
}
});
If you use Wait() instead of ContinueWith, an AggregateException containing an OperationCanceledException in its InnerExceptions collection will be thrown when the task is canceled.

Resources