2016-10-13 4 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スレッドである、または私はいくつかの研究を持っているが、まだ答えを見つけていない何か

を欠場することをどこから読んで、助けてくださいので、あなたに感謝多くの人。

これは私が@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); 
      } 
     }); 

    } 
}); 
私にはとても混乱して発生したログ

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]

UPDATE 1

から得たものです

android.view.ViewRootImpl $ CalledFromWr ongThreadException:ビュー階層を作成した元のスレッドのみがそのビューに触れることができます。

+0

私はあなたのQUEを取得しておりません。 –

+0

no-argsコンストラクタ、または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); 
       } 
      }); 

     } 
    }); 

例外が発生します:たぶんViewRootImpl.checkThread()Activity.onCreate()

で呼び出されていない

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) 

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.がいる場合にのみスローされます

+0

このコードを試してみました。同じエラーですので、今混乱しています – kittenforcode

0

例外:非UIスレッド

  • コールから呼び出さ

    1. は、レイアウトの変更が必要です。例えばTextViewのサイズ(幅と高さ)があるため、あまりにも長い文字列

    だからあなたのUI操作は、レイアウト変更(作成または再作成)につながらない場合は、例外の、延長すべき場合投げられないかもしれない。

  • +0

    幅と高さの両方についてTextViewを 'wrap_content'に設定してOPと同じサンプルを実行します。この例ではテキストが変更されますが、最終的にレイアウトの変更を要求してはいけませんか? –

    +0

    はい固定サイズで試してみよう – dit

    +0

    私はあなたの意見を忘れてしまったと思う...レイアウト変更をトリガーするためにサイズ 'wrap_content'を作った。あなたが提案された答えが正しいならば、アプリケーションは 'CalledFromWrongThreadException'のためにクラッシュしますが、そうではありません。 –

    0

    Handlerオブジェクトは、自身が作成されたスレッドに自身を登録します。このスレッドにデータを送信するチャネルを提供します。たとえば、アクティビティのonCreate()メソッドで新しいHandlerインスタンスを作成した場合、それを使用してデータをメインスレッドにポストすることができます。 Handlerクラスを介して送信できるデータは、MessageクラスまたはRunnableクラスのインスタンスです。

    したがって、以下の行に基づいて、ハンドラはHandlerThreadに属している必要があります。

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

    私はOnCreate()がメインスレッドだと理解していますが、OnClick Listenerは別のクラスです。それは文脈の違いがあることを意味します。例えば

    // 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

    trueの場合は、onClickメソッドのコードを使用しているときにエラーがまだ発生します – kittenforcode

    +0

    HandlerThreadの作成インスタンスを移動し、ハンドラの部分をonClickメソッドに入れてもエラーが発生する:( – kittenforcode

    +0

    btw onClickが別のスレッドで実行されている場合UIビューに触れる方法 – kittenforcode

    関連する問題