在非ui线程中构造视图并在ui线程中使用

时间:2011-03-12 18:27:52

标签: 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);
    }
} 

1 个答案:

答案 0 :(得分:2)

如果我从遇到此异常时正确记得,当其他线程尝试对UI进行更改时,Android不会喜欢。您需要做的是让其他线程将一些消息发送回主UI线程(使用Handler)来执行这些更改。也请看这个:http://developer.android.com/guide/appendix/faq/commontasks.html#threading