2016-10-13 51 views
3

這段代碼爲什麼有效?爲什麼設置HandlerThread的循環的Handler可以與UI對象交互?

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    Log.i("onCreate", Thread.currentThread().toString()); 
    textView = (TextView) findViewById(R.id.textView); 
    imageView = (ImageView) findViewById(R.id.imageView); 

    HandlerThread thread = new HandlerThread("myHandlerThread"); 
    thread.start(); 
    mUiHandler = new Handler(thread.getLooper()); 
    mUiHandler.post(new Runnable() { 
     @Override 
     public void run() { 
      Log.i("Thread: ", Thread.currentThread().toString()); 
      Toast.makeText(getApplicationContext(), "Hello Cats!", Toast.LENGTH_SHORT).show(); 
      textView.setText("Hello Cats"); 
      imageView.setImageResource(R.mipmap.ic_launcher); 
     } 
    }); 

} 

我從某處讀取,可以與UI對象溝通的唯一線程是UI線程,或者我錯過的東西

我有一些研究,但沒有找到答案,請大家幫幫忙,非常感謝你很多人。

這是我從日誌中得到

10-13 18:47:42.888 23841-23841/th.co.me.sampleapp I/onCreate: Thread[main,5,main] 10-13 18:47:42.891 23841-24041/th.co.me.sampleapp I/Thread:: Thread[myHandlerThread,5,main]

更新1

我試圖從@nshmura此代碼,發生錯誤是如此混亂我現在

textView.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     HandlerThread thread = new HandlerThread("myHandlerThread"); 
     thread.start(); 
     mUiHandler = new Handler(thread.getLooper()); 
     mUiHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       Log.i("Thread: ", Thread.currentThread().toString()); 
       Toast.makeText(getApplicationContext(), "Hello Cats!", Toast.LENGTH_SHORT).show(); 
       textView.setText("Hello Cats"); 
       imageView.setImageResource(R.mipmap.ic_launcher); 
      } 
     }); 

    } 
}); 

android.view.ViewRootImpl $ CalledFromWr ongThreadException:只有創建視圖層次結構的原始線程可以觸及其視圖。

+0

我沒有得到你的闕。 –

+0

使用無參數構造函數或Handler(Looper.getMainLooper())初始化您的處理程序...這樣您的處理程序將在主線程上運行,並且您可以從中更新您的視圖 –

回答

-2

試試這個代碼

mHandler = new Handler(); 

new Thread(new Runnable() { 
    @Override 
    public void run() { 
     // Perform long-running task here 
     // (like audio buffering). 
     // you may want to update some progress 
     // bar every second, so use handler: 
     mHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       // make operation on UI - on example 
       // on progress bar. 
      } 
     }); 
    } 
}).start(); 
-1

檢查這樣的:

textView.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      HandlerThread thread = new HandlerThread("myHandlerThread"); 
      thread.start(); 
      mUiHandler = new Handler(thread.getLooper()); 
      mUiHandler.post(new Runnable() { 
       @Override 
       public void run() { 
        Log.i("Thread: ", Thread.currentThread().toString()); 
        Toast.makeText(getApplicationContext(), "Hello Cats!", Toast.LENGTH_SHORT).show(); 
        textView.setText("Hello Cats"); 
        imageView.setImageResource(R.mipmap.ic_launcher); 
       } 
      }); 

     } 
    }); 

異常會發生:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
     at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6556) 
     at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:942) 
     at android.view.ViewGroup.invalidateChild(ViewGroup.java:5081) 
     at android.view.View.invalidateInternal(View.java:12719) 
     at android.view.View.invalidate(View.java:12683) 
     at android.view.View.invalidate(View.java:12667) 
     at android.widget.TextView.checkForRelayout(TextView.java:7156) 
     at android.widget.TextView.setText(TextView.java:4347) 
     at android.widget.TextView.setText(TextView.java:4204) 
     at android.widget.TextView.setText(TextView.java:4179) 

也許ViewRootImpl.checkThread()不是在Activity.onCreate()

稱爲
+0

我試過這段代碼,同樣的錯誤它現在是如此混亂 – kittenforcode

0

異常android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.會拋出異常,只有當:

  1. 從非UI線程
  2. 電話叫需要佈局的變化。例如,如果一個TextView的大小(寬度和高度)應適當延長,因爲過長的字符串

所以如果你的UI操作不會導致佈局更改(創建或重建),異常的,可能不會被拋出。

+0

我運行同樣的例子作爲OP與TextView設置爲'wrap_content'的寬度和高度。這個例子改變了文本,不是它最終也要求更改佈局嗎? –

+0

是用固定尺寸試一下 – dit

+0

我想你錯過了我的觀點......我做了'wrap_content'的大小來觸發佈局改變。如果您提出的答案是正確的,則應用程序將因'CalledFromWrongThreadException'而崩潰 - 但事實並非如此。 –

0

Handler對象將自己註冊到創建它的線程中。它提供了一個將數據發送到該線程的通道。例如,如果您在活動的onCreate()方法中創建新的Handler實例,則可以使用它將數據發佈到主線程。可以通過Handler類發佈的數據可以是Message或Runnable類的實例。

因此,根據下面的行,你的處理程序應該屬於HandlerThread。

mUiHandler = new Handler(thread.getLooper()); 

有一件事我明白的OnCreate()是主線程,但onClick的監聽器單獨的類。這意味着存在上下文差異。

例如:

// onCreate() we are writing like this 
Toast.makeText(this, "Hello Cats!", Toast.LENGTH_SHORT).show(); 
// but in Onclick method we are writing like this 
Toast.makeText(MainActivity.this, "Hello Cats!", Toast.LENGTH_SHORT).show(); 
+0

如果它是真的爲什麼在onClick方法上使用代碼時仍然出現錯誤 – kittenforcode

+0

我移動了HandlerThread的創建實例和處理程序部分到onClick方法,但錯誤仍然發生:( – kittenforcode

+0

btw如果onClick運行在不同的老鼠,它如何觸摸UI視圖 – kittenforcode

相關問題