如何在Android中更新自定义视图

时间:2016-03-12 15:10:08

标签: java android multithreading android-custom-view

我正在开发一个简单的自定义视图来显示由背景图像组成的仪表,在该背景图像上方打印数字(rpm)并绘制指针。
为了实现它,我定义了一个扩展ImageView类的类(MyGauge)。在onDraw()成员中,我将drawLine()和drawText()一个由活动发送并由SetRpm()成员收集的数字;然后我强制使用invalidate()调用 该活动运行一个Thread(一个Runnable实例),每秒生成一个不同的数字;线程将一条消息发送给活动;处理程序接收消息并通过SetRpm()函数设置数字。

我收到的错误是:

03-12 09:39:33.280 1796-1827/com.stemmo.termi_up W/dalvikvm: threadid=16: thread exiting with uncaught exception (group=0xb178e678)
03-12 09:39:33.280 1796-1827/com.stemmo.termi_up E/AndroidRuntime: FATAL EXCEPTION: Thread-78
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5908)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:869)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:4253)
at android.view.View.invalidate(View.java:10539)
at android.view.View.invalidate(View.java:10494)
at com.stemmo.termi_up.CustomViews.MyGauge.SetRpm(MyGauge.java:61)
at com.stemmo.termi_up.GaugeActivity$2.handleMessage(GaugeActivity.java:54)
at android.os.Handler.dispatchMessage(Handler.java:99)
at com.stemmo.termi_up.GaugeActivity$3.run(GaugeActivity.java:83)
at java.lang.Thread.run(Thread.java:841)

所以,处理程序在线程的上下文中? 我怎么解决呢? 我需要AsyncTask对象而不是Runnable对象吗?

3 个答案:

答案 0 :(得分:0)

Android中的视图只能从UI线程更新。您始终可以将Runnable发布到此类视图

    MyGauge gauge = ... // your custom view
    gauge.post(new Runnable() {
        view.SetRPM();
    });

答案 1 :(得分:0)

我回答因为我最好写下代码..
这是Activity的onCreate()上的代码:

       final Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            Bundle data = msg.getData();
            String v = data.getString("value");
            myGauge.SetRpm(v);
        }
    };

    // Simul thread
    nValue = 0;
    bUpDown = true;
    Runnable thread = new Runnable() {
        @Override
        public void run() {
            while(true) {
                if (bUpDown)    // Up
                   ...
                }

                Bundle data = new Bundle();
                data.putString("value", String.valueOf(nValue));
                Message msg = new Message();
                msg.setData(data);
                myHandler.dispatchMessage(msg);

                // Delay
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };
    new Thread(thread).start();

MyGauge中的SetRpm()成员是:

 public void SetRpm(String newRpm)
{
    m_strRpm = newRpm;
    invalidate();
}

答案 2 :(得分:0)

我发现您的代码存在问题。请替换您的代码行

myHandler.dispatchMessage(MSG); with myHandler.sendMessage(msg);

它将修复异常“只有创建视图层次结构的原始线程才能触及其视图。”