如何操作从Android的另一个线程主线程UI元素?线程、主线、元素、操作

2023-09-07 10:02:17 作者:夏—尛—媣

我的应用程序结合了一堆主应用程序线程上运行的常规视图对自己的线程运行的SurfaceView。在大多数情况下,这工作正常。然而,当我尝试对SurfaceView的线程触发的改变在主应用程序线程的UI元素的一个东西,我得android.View.ViewRoot $ CalledFromWrongThreadException。

有没有解决这个正确的方式?我应该使用AsyncTask的? Runonuithread()?抑或是混合在自己的线程与主线程只是一个天生的坏事情在其他UI元素的SurfaceView?

如果我的问题没有意义,这里是伪code,可能会更清晰。

  //活动的主应用程序线程中运行公共类MainActivity延伸活动{    RelativeLayout的布局;    TextView中弹出;    MySurfaceView mysurfaceview;    保护无效的onCreate(捆绑savedInstanceState){        ...        的setContentView(布局);        layout.addView(mysurfaceview); //显示表面观        popup.setText(你赢了); //创建,但尚未显示    }    公共无效showPopup(){        layout.addView(弹出式);    }}//表面观运行在自己的独立线程公共类MySurfaceView扩展SurfaceView实现SurfaceHolder.Callback,OnTouchListener {    私人ViewThread mThread;    公共布尔onTouch(视图V,MotionEvent事件){        ...        如果(someCondition ==真){            mainactivity.showPopup();            //这工作,因为onTouch()是由主应用程序线程调用        }    }    公共无效抽奖(帆布油画){        ...        如果(someCondition ==真){            mainactivity.showPopup();            //这与崩溃$的ViewRoot CalledFromWrongThreadException            //因为绘制由mThread称为            //这是可以解决的?        }    }} 

解决方案   

我应该使用AsyncTask的? Runonuithread()?

无论这些应该罚款。我通常使用的AsyncTask 对于需要做一个后台进程更新 UI 最多的事。但无论哪种应该工作。

一个java类,他有一个方法计算1 2并返回结果 用主线程创建一个新线程调用上面类的方法 并打印结果

AsyncTask的文档

runOnUiThread例如和文档

My app combines a SurfaceView running on its own thread with a bunch of regular Views running on the main application thread. For the most part, this works fine. However, when I try to have something on the SurfaceView's thread trigger a change to one of the UI elements in the main application thread, I get android.View.ViewRoot$CalledFromWrongThreadException.

Is there a right way around this? Should I use an asynctask? Runonuithread()? Or is mixing a SurfaceView on its own thread with other UI elements on the main thread just an inherently bad thing to do?

If my question doesn't make sense, here's pseudocode that may be clearer.

// Activity runs on main application thread
public class MainActivity extends Activity {
    RelativeLayout layout;
    TextView popup;
    MySurfaceView mysurfaceview;

    protected void onCreate(Bundle savedInstanceState) {
        ...
        setContentView(layout);
        layout.addView(mysurfaceview);  // Surface View is displayed
        popup.setText("You won");       // created but not displayed yet
    }
    public void showPopup() {
        layout.addView(popup);
    }
}

// Surface View runs on its own separate thread
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener {
    private ViewThread mThread;

    public boolean onTouch(View v, MotionEvent event) { 
        ...
        if (someCondition == true) {
            mainactivity.showPopup();
            // This works because onTouch() is called by main app thread
        }
    }
    public void Draw(Canvas canvas) { 
        ...
        if (someCondition == true) {
            mainactivity.showPopup();
            // This crashes with ViewRoot$CalledFromWrongThreadException
            // because Draw is called by mThread
            // Is this fixable?
        }
    }
}

解决方案

Should I use an asynctask? Runonuithread()?

Either of these should be fine. I typically use AsyncTask for most things that need to update the UI after doing a background process. But either should work.

AsyncTask Docs

runOnUiThread example and Docs