【问题标题】:System.Threading: Running into Java.Lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()System.Threading:遇到 Java.Lang.RuntimeException:无法在未调用 Looper.prepare() 的线程内创建处理程序
【发布时间】:2019-06-04 09:22:37
【问题描述】:

在我的 Xamarin.Android-App 中,当打开一个特殊页面(活动)时,创建时会显示一个表格。 ListAdapter 定义该表中的某些字段。我有一个函数可以让我获得一个外部 int。 int 是该表中显示的其他数据之一。但是这个函数只被调用一次(在创建时)。我想在运行时动态检测接收到的 int 是否发生了变化,如果发生了变化,还要更改表中 int 的显示。

请看我下面的代码:

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";
            }
        });
    }
}

不幸的是,我在var a = new Activity(); 行中遇到运行时错误,说

Java.Lang.RuntimeException:无法在线程内创建处理程序 没有调用 Looper.prepare()

谁能告诉我问题出在哪里/如何解决?

最好的问候

编辑:Get_Number() 方法如下所示:

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);
            }
        }
    }
}

【问题讨论】:

    标签: c# android xamarin.android refresh android-runonuithread


    【解决方案1】:

    照它说的做,打电话给Looper.prepare()

    void MethodToRun() {
        Looper.prepare();
    
        //...
    }
    

    但是,您还有其他问题。您不能自己创建 Activity 的新实例。如果你想在主线程上运行一些东西,创建一个新的 Handler:

    var handler = new Handler(Looper.GetMainLooper());
    

    然后你就可以用它发帖了:

    handler.Post(() => {
        int number = Get_Number();
    
        //...
    }
    

    但是,如果您想在主线程上运行重复操作,您所做的正是创建 Handlers 来避免的。

    试试这样的:

    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);
    }
    

    这样,您只需调用一次PostAction() 即可让事情顺利进行,然后它会继续循环您的逻辑。

    如果你想停止循环:

    handler.RemoveCallbacks(actions);
    

    【讨论】:

    • 感谢您的回答@TheWanderer。我按照建议尝试了所有方法,但现在我的应用程序挂了 xD 这个处理程序是否启动了多个线程?因为正如开头所写的那样,为了给出一个概览,我有一张表。我正在尝试对该表中的每一行执行此刷新过程,但不刷新活动/表本身。所以基本上我尝试只更新/刷新显示数字的字段,并且只有当它发生变化时。
    • Get_Number() 是做什么的?
    • 从外部获取一个数字并返回。我用它的详细代码更新了这个问题。
    • 好吧,即使让您的代码工作,那也会挂起。该部分需要从主线程运行。我将编辑我的答案。
    • 嗯现在应用程序不再挂起,但不幸的是您的代码没有任何效果我很抱歉文本没有显示在表格中:(通过代码使用调试器运行使它看起来像代码被跳过了,至少他没有跳到Runnable actions = new Runnable()之后的代码,并且局部变量handleractions既没有定义也没有赋值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    相关资源
    最近更新 更多