android - 在非 ui 线程中构建 View 并在 ui 线程中消费

标签 android thread-safety

我在非 UI 线程中创建一组 webview 对象,并在 webview 的页面加载完成后继续将它们添加到队列中。 UI 线程最终会查询一个 webview,如果维护的队列中有元素,就会从队列中挑选出来。这个非 UI 线程将永远运行并在需要时填充队列。不幸的是,当 UI 线程呈现 webview 时,虽然它被正确呈现,但非 UI 线程突然失败并出现错误“CalledFromWrongThreadException”。我不确定这种行为是否符合预期。我已经创建了一个示例程序来演示相同的内容。有人可以帮我找出这里的问题吗?

public class MultiThreadTest extends Activity {

    private volatile WebView mWv;
    private LinearLayout mLL;
    private volatile Handler nonUiThreadHandler = null;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mLL = (LinearLayout) findViewById(R.id.linearLayout);
        Button creator = (Button) findViewById(R.id.creator);
        creator.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                createThread();
            }
        });

        Button consumer = (Button) findViewById(R.id.consumer);
        consumer.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                mLL.addView(mWv, new LinearLayout.LayoutParams(200, 200));
                mWv.requestFocus();
            }
        });
    }

    public void createThread() {

        Thread t = new Thread (new Runnable() {         
            @Override
            public void run() {
                Looper.prepare();
                nonUiThreadHandler = new Handler();
                Looper.loop();          
            }
        }, "Creator thread");

        t.start();

        while (!t.isAlive() || nonUiThreadHandler==null) {}

        nonUiThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                constructView();
            }
        });
    }

    public void constructView() {
        mWv = new WebView(MultiThreadTest.this);
        mWv.setWebChromeClient(new WebChromeClient());
        mWv.loadUrl("http://www.yahoo.com");
        mWv.setFocusable(true);
    }
} 

最佳答案

如果我没记错的话,当我遇到这个异常时,Android 不喜欢另一个线程试图对 UI 进行更改。您需要做的是让您的其他线程将一些消息发送回主 UI 线程(使用处理程序)以执行这些更改。另见:http://developer.android.com/guide/appendix/faq/commontasks.html#threading

关于android - 在非 ui 线程中构建 View 并在 ui 线程中消费,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5284513/

相关文章:

android - 以编程方式安装 Android apk 作为测试框架的一部分

multithreading - 这是双重检查锁定的安全版本吗?

multithreading - 使用静态和非静态方法从类中进行线程化

java - 在单独的线程中处理文件写入的正确方法

android - 用户单击时图像 GridView 显示大图像

即使设置了 configChanges,Android Activity 也会在方向更改时重新启动

android - 将 touchListener 添加到路径对象

android - RecyclerView 不显示来自 firebase 的数据(Kotlin)

rust - 在 Rust 中拥有线程安全的延迟初始化的可能可变值的正确方法是什么?

c# - 使用 Session.SyncRoot 锁定每个 session 有哪些危险?