Reputation: 185
In my Xamarin.Android-App, when opening a special page (activity), there is a table displayed on create. A ListAdapter defines the certain fields within that table. I have a function which gets me an external int. The int is amongst other data displayed in that table. But this function is only called once (on create). I want to detect dynamically during runtime if this received int changed, and if so change the display of the int in the table as well.
Please see my following code:
ListAdapter.cs:
var thread = new Thread(() => MethodToRun());
thread.Start();
[...]
void MethodToRun()
{
while (true)
{
Thread.Sleep(1000);
var a = new Activity();
a.RunOnUiThread(() => {
int number = Get_Number();
if (number == 1)
{
v.FindViewById<TextView>(Resource.Id.textView).Text = "1";
}
if (number != 1)
{
v.FindViewById<TextView>(Resource.Id.textView).Text = "Not 1 anymore";
}
});
}
}
Unfortunately, I am getting a runtime error in the line var a = new Activity();
saying
Java.Lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Can anyone maybe tell me whats the problem / how to fix this?
Best regards
Edit: the Get_Number()-method looks like the following:
private int Get_Number(Geraet geraet)
{
var request = HttpWebRequest.Create(string.Format(Constants.WebservicePath, Serverip, Constants.WebservicePort, geraet.Ip));
request.ContentType = "application/json";
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
var content = reader.ReadToEnd();
var result = System.Text.RegularExpressions.Regex.Replace(content, @"[^0-9]", "");
if (result == string.Empty)
{
return -2;
}
else
{
return Int32.Parse(result);
}
}
}
}
Upvotes: 0
Views: 527
Reputation: 17874
Do what it says and call Looper.prepare()
:
void MethodToRun() {
Looper.prepare();
//...
}
However, you have other problems. You can't create a new instance of Activity yourself. If you want something to run on the main Thread, create a new Handler:
var handler = new Handler(Looper.GetMainLooper());
And then you can post with it:
handler.Post(() => {
int number = Get_Number();
//...
}
However, if you want to run a repeating action on the main Thread, what you're doing is exactly what Handlers were created to avoid.
Try something like this instead:
var handler = new Handler(Looper.GetMainLooper());
Runnable actions = new Runnable() => {
int number = Get_Number(); //this needs to be async
handler.Post(() => {
TextView text = v.FindViewById(Resource.Id.textView);
text.Text = number == 1 ? "1" : "Not 1 anymore";
PostAction();
}
}; //the syntax for this might be wrong, since I don't know C#
void PostAction() {
handler.postDelayed(() => {
new Thread(actions).start();
}, 1000);
}
This way, you just have to call PostAction()
once to get things going and then it'll keep looping over your logic.
If you want to stop the loop:
handler.RemoveCallbacks(actions);
Upvotes: 0