ハンドラの基本的な使い方

要約: Handlerハンドラを介して通信するための非同期メッセージ、メインスレッドと子スレッドを処理するために、コアクラスのAndroid SDK、メッセージを主に処理、サブスレッドがハンドラによってメインスレッドのUIの更新を通知することができます。

セクション

使用ハンドラは達成异步更新UI
1.ハンドラを作成します。

Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg){
       super.handleMessage(msg);
         //收到消息后,将会调用此方法
         //可以在这里进行UI更新操作
       }
   };

2.それからちょうどに子スレッドに空のメッセージを送信

new Thread(new Runnable(){
        @Override
        public void run(){
           handler.sendEmptyMessage(1);
        }
   }).start();

ハッハッハ、その後、非同期更新UIを実現し、そのシンプルなああではありません!しかし、まだUIを更新するために、メインスレッド、および役割ハンドラーは、メインスレッドに通知するために本質的である
ため、UIを更新するAndroid是单线程模式ので、我々は、不能在子线程更新UI唯一のハンドラによって、UIを更新するために、メインスレッドに通知することができます。

だから我々は、複数の場所でメッセージを送信した場合の質問は、あり、そしてすべての場所が異なるUIの更新操作でなければならないので、我々はそれを区別する方法にありますか?実際ハンドラに長い我々は考慮に入れると、私たちは見ても、バックステッピング、信じていないので、ハハハ...実際に、私たちは、このことを心配することは何もありません!

ここから、私たちはここにも、パラメータを運ぶ「1」と、これがあることがわかります1。この記事のメッセージである标识、それは我々がニュースを区別することができるようになりますそれによって、このメッセージID、として理解することができます!

handler.sendEmptyMessage(1);

その後...ハンドラを作成しますのでなりました

Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg){
       super.handleMessage(msg);
          switch(msg.what){
             case 1:
              {
                 //收到标识为1的消息后,将会调用这里
                 //可以在这里进行UI更新操作
              }
          }
       }
   };

拡張:あなたが唯一の空白のメッセージハンドラを送信すると思うなら、あなたは間違っている、なぜならHandler还支持发送一个Message对象それはしかし、!コードを見る前に、またはこれを見てみましょう!

パラメータ 解決
arg1に パラメータはint型であり、int型は、メッセージを渡すことができ
ARG2 引数1と同様に
OBJ 比較的強く、パラメータは、オブジェクトタイプ、オブジェクトタイプは、メッセージを渡すことができています。
メッセージ識別子は、主にメッセージを区別するために使用されるメッセージID、として理解することができます。

Messageオブジェクトを送信し
Message对象是可以带参数的、パラメータが解析されてきた、とここハッハッハ、説明していません...

Message message =new Message();
message.arg1=1;
message.arg2=2;
message.what=3;
message.obj="测试";
handler.sendMessage(message);

ハッハッハ、どのようにそれについて!その背の高い瞬間の多くを感じていない、何も感じああはありませんか?ハハハ...その後ハンドラのコードはそうなります。

Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg)
    {
       super.handleMessage(msg);
          switch (msg.what){
             case 1:
              {
                 //收到标识为1的消息后,将会调用这里
                 //可以在这里进行UI更新操作	
              }
             break;
             case 3:
              {
             //收到标识为3的消息后,将会调用这里
                Log.d("arg1", msg.arg1 + "");
                Log.d("arg2", msg.arg2 + "");
                Log.d("obj", msg.obj + "");
              }
          }
       }
   };

実行します。

メッセージ最適化:官方建议私たちは、意志

Message msg =new Message();

変更

Message msg = handler.obtainMessage();

若しくは

Message msg = Message.obtain();

長所:この場合、オブジェクトのメッセージを作成し、破壊するシステムのために責任があるかもしれません

さらなる研究

セクションII

慎重な友人がHandlerオブジェクトが持つ気付くかもしれpostRunnableオブジェクトを送信するための方法を、私たちはこのRunnableオブジェクトを必要とし、run()メソッドをオーバーライドします。

これは、ここで注意しなければならないですポストを使用してRunnableオブジェクトを送って 虽然看起来像是在子线程中执行,但其实它是在主线程中执行的!、我々は子スレッドを扱うたびにとの接触をRunnableをしますので、Runnableを、子スレッドで勘違いするのは簡単です、が、実際には子スレッドを作成することができる唯一の一つであり、そしてそれはスレッドですこの場合、あなたはポイントを取得する必要があります!これは、ログの出力電流のスレッドが完全に可能である、検証、あなたが試すことができます信じていません。

使用しているためpost发送的消息不会被Handler对象接收、ノートを取るためにそこに必要があるので、彼らは2、混ざっすべての操作だけでRunnableオブジェクトに書き込むことが困難であるとしようとしている入れていません。

一般的な使用方法:

new Thread(new Runnable(){
     @Override
     public void run()
     {
        handler.post(new Runnable()
        {
          @Override
           public void run()
            {
               //UI更新操作
               //这里的所有操作都会在主线程中执行
            }
        });
      }
   }).start();

もちろん、あなたも書くことができます

private class myRunnable implements Runnable{
    @Override
    public void run()
    {
       // UI更新操作
       // 这里的所有操作都会在主线程中执行
    }
 }

そして、...

myRunnable myRunnable=new myRunnable();
handler.post(myRunnable);

もちろん、あなたもハンドラを作成するとき、あなたはちょうどあなたが呼び出したい場所にメッセージを送る良い仕事関連の操作を行うことができます。

これらのHadler博士の基本的な使い方...ナ、そして今それを試して急いああ!ハッハッハ...

さらなる研究

セクションIII:

HandlerThread

我々はより多くの時間のかかる操作Handlerオブジェクトの一部を実行したい場合、我々は通常、実行するためのサブスレッドでスローされ、それを考えるので、新しい直接の子スレッドを直接ハンドラはそれで離れて取得していませんか?私は、ほとんどの人は右、次のように反応するだろうと思います!

Handler Handler=new Handler(){
    @Override
    public void handleMessage(Message msg){
       super.handleMessage(msg);
       new Thread(new Runnable(){
          @Override
          public void run(){
             //在这里执行耗时操作
          }
       }).start();
    }
 };

ああNAので、非同期実行を実装していますが、このHandlerオブジェクトは、メッセージそれの多くを受信した場合?だから何が起こるのだろうか?

効果がより明確にするために、私は現在のスレッドの出力の出力データ内のログHandlerオブジェクトに書いた、そしてそれに3つのメッセージを送信し、次のように、結果は以下のとおりです。

また、私は次のような結果があり、同じ操作ルーパ糸をしました:

分析:

現象 結論
3つのスレッドを作成するために、通常のオブジェクトをハンドラ それぞれがメッセージを受信し、それが新しいスレッドを作成し、この方法は、偉大なスレッドのオーバーヘッドである、それは推奨されません。
一つのスレッドだけルーパ糸 どんなに受信されているどのように多くのメッセージが、それだけでスレッドを作成しません

だから今、あなたはそれの役割ルーパ糸を知っている必要があります!

注意:これは主にルーパー糸、ない書き込みを行くための呼び出しで何を伝えたいです。当局は、この...私たちの背後に再訪HandlerThreadと呼ばれる良いパッケージルーパ糸を、持っています。

しかし、ルーパー糸を学習し、またはそれで、この最初の見ている前に!

単語の意味 説明
ルーパー スレッドが唯一のルーパーを持つことができ、ルーパーだけメッセージキューを持つことができ、メッセージを循環させるための責任ルーパー、それは内側からメッセージキューのメッセージを取り出し、および処理のための適切なハンドラに引き渡されていたであろう。
メッセージキュー ハンドラによって送信されたメッセージを格納するためのメッセージキュー
メッセージ メッセージ本体は、オブジェクトをロードするためのメッセージキューに格納され、送信される必要があります
ハンドラ ...私は、これはそれを導入していません...と思います!

ルーパー糸

私たちは子スレッドでハンドラを使用したい場合は、我々はまた、内部のルーパーのスレッドオブジェクトを作成する必要があり、それはメッセージを循環させることを可能にします。

Looper线程其实就是一个拥有Looper的子线程

質問は、なぜ我々はメインスレッドでハンドラを使用しないされるように、オブジェクトは、ルーパーを作成しませんか?そのため主线程默认是创建Looper对象的、私たちが作成行く必要はありません。

ルーパースレッドを作成

具体的なコードは次のよう:

private class myThread extends Thread{
    public Handler Handler;
    @Override
    public void run()
    {
       Looper.prepare();
       Handler = new Handler(){
          @Override
          public void handleMessage(Message msg)				{
             super.handleMessage(msg);
             Log.d("测试2", Thread.currentThread() + "");
             //异步任务
             //可执行一些比较耗时的操作
             //不能执行UI更新操作
             }
          };
          Looper.loop();
       }	
   }

上記の方法と異なる使用のいくつかの
具体的な表情コード:

例示:サブスレッドにメッセージを送ります

myThread myThread=new myThread();
myThread.start();
try
{
myThread.sleep(500);
}
catch (InterruptedException e)
myThread.Handler.sendEmptyMessage(0);

実行します。

これとは対照的に、我々は明らかにそれを見ることができます它是在子线程里面执行的,所以不能执行UI更新操作,可用于一些比较耗时的操作

テスト1は、私はいくつかの比較を行うために、出力は現在のスレッドで、Handlerオブジェクトのメインスレッドの内側に書いています。

Handler handler=new Handler(){
   @Override
   public void handleMessage(Message msg)
   {
      super.handleMessage(msg);
      Log.d("测试1", Thread.currentThread() + "");
      //UI更新操作
      }
   };
handler.sendEmptyMessage(0);

ルーパー糸を学ぶために続行

上記のことを理解した後。私たちは、Handlerオブジェクトを作成するために、メインスレッドになりました、そしてオブジェクトがルーパー、それを指定することで、それはそれのターゲットルーパールーパー糸として指定入れて!

次のように具体的な実施手順は次のとおりです。

private class myThread extends Thread{
    public Looper looper;
    @Override
    public void run()
    {
       looper.prepare();
       looper=looper.myLooper();
       looper.loop();
      }
   }

ここでは上記を説明するために
Looper.myLooper();
、現在のスレッドルーパーオブジェクトを取得するには

onDestroyの活動に書くことを忘れないでください
myThread.looper.quit();
スレッドの終了ルーパールーパーサイクルを

メインスレッドは、ハンドラオブジェクトを作成する際ルーパーは、オブジェクトを指定します

myThread myThread=new myThread();
myThread.start();
Handler handler=new Handler(myThread.looper){
    @Override
    public void handleMessage(Message msg)
    {
       super.handleMessage(msg);
       Log.d("嘿嘿",Thread.currentThread()+"");
       //异步任务
       //可执行一些比较耗时的操作
       //不能执行UI更新操作
   }
 };
 handler.sendEmptyMessage(1);

その後。

程序崩溃了

これはなぜでしょうか?
ログを実行することにより、我々は見ることができます
myThread.looper

我々はプログラムHandlerオブジェクトを作成するときにプログラムの崩壊につながっていること、そして、我々はそれを解決する方法に行く必要がありますので、ルーパーターゲットの子スレッドは、作成する時間がなかったので、ここでNULL値の問題が、ありましたか?

ソリューション:

ルーパー糸を開始した後、メインスレッドは、500ミリ秒を寝Handlerオブジェクトを作成行くことにしましょう。これは、NULL値の問題を解決するだろう。

myThread myThread=new myThread();
myThread.start();
try
{
Thread.sleep(500);
}catch (InterruptedException e){}
Handler handler=new Handler(myThread.looper){
    @Override
    public void handleMessage(Message msg){
       super.handleMessage(msg);
       //异步任务
       //可执行一些比较耗时的操作
       //不能执行UI更新操作
    }
 };
 Message msg= Message.obtain();
 handler.sendMessage(msg);

若しくは

myThread myThread=new myThread();
myThread.start();
try{
myThread.sleep(500);
}
catch (InterruptedException e){}
Handler handler=new Handler(myThread.looper){
    @Override
    public void handleMessage(Message msg){
       super.handleMessage(msg);
       //异步任务
       //可执行一些比较耗时的操作
       //不能执行UI更新操作
    }
 };
 Message msg= Message.obtain();
 handler.sendMessage(msg);

この時点で、我々の出力ログHandlerオブジェクトは、現在のスレッドの内容を、我々は表示されます它输出的是子线程,而不是主线程

だから、我々はまた、正常非同期実行を達成したメインスレッドハンドラに書き込み、その後可以在里面执行一些比较耗时的操作、それはサブスレッドで実行されているので、私たちはあります不能执行UI更新操作

実際には、ここに書き込む前に、子スレッドでHandlerオブジェクトは同じですが、何も別に書かないし。

Google官方我々はすでにパッケージ化ルーパ糸直接使用することをお勧めします、独自のカスタムルーパ糸を行くことをお勧めしませんHandlerThread、マルチスレッドの同時実行がなく、シンプルで使いやすい、私たちのために問題を解決することができます。

HandlerThread是什么?
私はあなたが今、UIの更新操作を実行することができない、そして最後に、我々はそれを使用する方法をHandlerThreadしたい、実際には、Google社員がHandlerThread公式パッケージルーパ糸は、より時間のかかる操作のいくつか、同じことを行うことができ、HandlerThreadが何であるかを知っておくべきと考えていますか?次のことを考えてみます。

HandlerThread使用:

HandlerThread HandlerThread=new HandlerThread("这个随便写");
HandlerThread.start();
Handler handler=new Handler(HandlerThread.getLooper()){
   @Override
   public void handleMessage(Message msg){
      super.handleMessage(msg);
      Log.d("嘿嘿",Thread.currentThread()+"");
      //异步任务
      //可执行一些比较耗时的操作
      //不能执行UI更新操作
      }
 };
 handler.sendEmptyMessage(1);

それを実行します。

どうでしょうか?あなたはそれを学びますか?使用HandlerThreadは非常に簡単です。

書き込みブログは本当に簡単です!それは心のレイヤです!しかし、また、ハンドラの私の理解、その損失なし...ハッハッハを深めました。

この記事では、ここで終わりにします

私はあなたがそれをお楽しみください。

おすすめ

転載: blog.csdn.net/weixin_45263548/article/details/92783103