2011-03-12 83 views
2

我在非UI線程中創建一組webview對象,並在webview的頁面加載完成後繼續將其添加到隊列中。 UI線程最終將查詢webview,並且如果維護隊列中有元素,它將從隊列中挑選出來。此非UI線程將保持永久運行,並在需要時填充隊列&。不幸的是,當UI線程呈現webview時,雖然它被正確渲染,但非UI線程突然失敗並出現「CalledFromWrongThreadException」錯誤。我不確定這種行爲是否預期。我創建了一個示例程序來演示相同。有人能幫我在這裏找出問題嗎?在非UI線程中構造視圖並在UI線程中使用

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

回答

2

如果我記得從我遇到這個異常時正確的,Android不喜歡另一個線程嘗試更改UI。你需要做的是讓你的其他線程發送一些消息給主UI線程(使用Handler)來執行這些改變。另請參見:http://developer.android.com/guide/appendix/faq/commontasks.html#threading

+1

您也可以使用'runOnUiThread()',它執行相同的操作,但沒有處理程序。 – bigstones 2011-03-12 19:00:45

+0

是必須在他們將顯示的線程上構建視圖。 – hackbod 2011-03-12 19:47:28

+0

@anothem謝謝指出。是的,我知道這個限制。這就是我從UI線程中完成以下幾行的確切原因。 mLL.addView(mWv,new LinearLayout.LayoutParams(200,200)); mWv.requestFocus(); (2/3) (1/2) – 2011-03-14 05:59:36