user2235253 user2235253 - 2 months ago 20
Android Question

How to make an async button click update a TextView dynamically with Xamarin Android

In Xamarin Native Android app I am calling methodOne() and getting some details. After this I want to updated the details to text view and then calls the methodTwo(). After executing MethodTwo I have to clear the text details from text view. I tried with
RunOnUiThread(() => tColorDetail.SetText("text", TextView.BufferType.Normal));
The details are displaying after finishing all the methods it is not showing immediately after executing MethodOne().
What is missing here?
.....................................................

public class MainActivity : Activity
{
int count = 1;
ticket Ticket;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);

// Get our button from the layout resource,
// and attach an event to it
Button bClick= FindViewById<Button>(Resource.Id.bSub);
try {
bClick.Click += delegate {

Job Job;
Action act = new Action();
EditText Address = (EditText)FindViewById(Resource.Id.Address);
act.Address = Address.Text.ToString();

if (!ValidateIPv4(act.Address))
{
ShowMessage("Invalid IP");
}
else
{//TextView Mode = (TextView)FindViewById(Resource.Id.Mode);
string httpUrl = act.iPAddress ;
Ticket = act.ExecuteTicket(httpUrl, "Ticket");
//RunOnUiThread(() => tColorMode.SetText("text", TextView.BufferType.Normal));
// this.RunOnUiThread(() => setTicket(true));
setStatus(" Ticket : Success", true);
setTicket(true);
//tColorMode.SetText("text",TextView.BufferType.Normal);
//tColorMode.Invalidate();
Job = act.executeJob(httpUrl, Ticket);
setStatus(" Job : Success", true);
act.File(httpUrl, Ticket, Job);
setStatus("File Retrieval : Success", true);
setTicket(false);
setStatus("File Retrieval : Success", false);
}
};
}
catch (Exception ex)
{

ShowMessage(ex.Message.ToString());
}
}
public bool ValidateIPv4(string ipString)
{
if (String.IsNullOrWhiteSpace(ipString))
{
return false;
}

string[] splitValues = ipString.Split('.');
if (splitValues.Length != 4)
{
return false;
}
return true;
}

public void setTicket(bool b)
{
//TextView tMode = (TextView)FindViewById(Resource.Id.tMode);
// tMode.SetText("text",TextView.BufferType.Normal);
RunOnUiThread(() => {
TextView tMode = (TextView)FindViewById(Resource.Id.Mode);
tColorMode.SetText("text",TextView.BufferType.Normal);// b==true?Ticket.getProcessing():"";
((TextView)this.FindViewById(Resource.Id.tRes)).Text = b == true ? Ticket.getHeight().ToString() : "";
((TextView)this.FindViewById(Resource.Id.tFormat)).Text = b == true ? Ticket.getFormat().ToString() : "";
((TextView)this.FindViewById(Resource.Id.tOrode)).Text = b == true ? Ticket.getType().ToString() : "";
((TextView)this.FindViewById(Resource.Id.tRot)).Text = b == true ? Ticket.getValue().ToString() : "";
((TextView)this.FindViewById(Resource.Id.tSource)).Text = b == true ? Ticket.getSource().ToString() : "";
((TextView)this.FindViewById(Resource.Id.tSize)).Text = b == true ? Ticket.getAutoDetect().ToString() : "";
((TextView)this.FindViewById(Resource.Id.tExpo)).Text = b == true ? Ticket.getAuto().ToString() : "";
((TextView)this.FindViewById(Resource.Id.tSharp)).Text = b == true ? Ticket.getSharp().ToString() : "";
((TextView)this.FindViewById(Resource.Id.tComp)).Text = b == true ? Ticket.getComp().ToString() : "";
//tColorMode.Invalidate();
}); }
private void ShowMessage(string msg)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog dialog = builder.Create();

dialog.SetMessage(msg);
dialog.SetButton("OK", (s, ev) =>
{
dialog.Cancel();
});
dialog.Show();
}
private void setStatus(string status,bool b)
{
((TextView)this.FindViewById(Resource.Id.tStatus)).Text = b == true ? status : " ";
}
}

Answer

Without access to the full code it is tricky to give you an answer but

Ticket = act.ExecuteTicket(httpUrl, "Ticket");

this line has the potential to take a while to complete if it performs network operations and probably runs in a background thread not to freeze the UI.

Presumably when you get to

    // this.RunOnUiThread(() => setTicket(true));setStatus(" Ticket : Success", true);
 setTicket(true);

the act.ExecuteTicket call might not have finished

also if there are async operations taking place in

Job = act.executeJob(httpUrl, Ticket);

it could take a while to complete

All taken into consideration, you could probably be getting to

setTicket(false);
setStatus("File Retrieval : Success", false);

before the first calls finish

It could be worth checking

ANSWER UPDATE after discussion in comments:

Since your problem is that your asynchronous calls are taking a long time and you are experiencing "race conditions" because of it (your UI thread is proceeding with the updates on the TextViews before it should), you can solve the situation by changing your button click delegate to an async delegate, and forcing an await on the long operations' result before proceeding.

bClick.Click += async delegate {

               //...
               Job = await act.executeJob(httpUrl, Ticket);
               //...
    }