子スレッドでハンドラを作成して使用する方法

私たちは、ソースコードの観点から分析前の記事ハンドラ我々はサブスレッドを作成する方法でハンドラを言ったこの記事の実現は、ハンドラは子スレッドでちょうど2つのステップを作成しました:

  1. )(Looper.prepare:ルーパーを作成します。
  2. スタートルーパー:Looper.loop()

外部電流スレッドを作成するハンドラは、現在のルーパーを取得する方法を提供し、

次のようにJavaコードは次のとおりです。

public class HandlerThread extends Thread {

    private Looper mLooper;

    @Override
    public void run() {
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
        }
        Looper.loop();
    }

    public Looper getLooper() throws Exception {
        if (!isAlive()) {
            throw new Exception("current thread is not alive");
        }
        if (mLooper == null) {
            throw new Exception("current thread is not start");
        }
        return mLooper;
    }
}

私たちは、次を使用して見てみましょう:

class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val handlerThread = com.example.handlerdemo.HandlerThread()
        handlerThread.start()
        val handler1 = object : Handler(handlerThread.getLooper()) {
            override fun handleMessage(msg: Message?) {
                super.handleMessage(msg)
                Log.d("aaa", "thread:${Thread.currentThread().name},handle message")
            }
        }

        handler1.sendMessage(Message.obtain())
    }
    
}

上記のコードは非常にシンプルでHandlerThreadスタートを作成し、次にHandlerThreadルーパーでハンドラを作成し、認証のためのメッセージを送信することです。
しかし、我々は直接クラッシュを実行していることがわかります、異常は、次のとおりです。
ここに画像を挿入説明
私たちは初期化されていないmLooperによって引き起こされることがわかっていることに対応するコードを見つけるために、我々は最初のルーパーのコードを起動することができ、それを初期化しない理由は、その後、得られますか?我々はHandlerThreadを開始し、ハンドラを作成しているため実際には、ここでは、その後どのように、メインスレッドで実行されている、とHandlerThreadのrunメソッドがサブスレッドを実行することで、すべてのHandlerThreadまだ初期化されていませんルーパールーパー取得につながるされているが、一般的なスレッド同期の問題ですこの問題を解決するには?

最も簡単な解決策:のnotifyAllと待ち時間によって

public class HandlerThread extends Thread {

    private Looper mLooper;

    @Override
    public void run() {
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Looper.loop();
    }

    public Looper getLooper() throws Exception {
        if (!isAlive()) {
            throw new Exception("current thread is not alive");
        }
        synchronized (this){
            if (null == mLooper){
                wait();
            }
        }
        return mLooper;
    }
}

次のように動作では、出力ログは次のようになります。
ここに画像を挿入説明
私たちは、ハンドラ・プロセスがプロセスではなく、子スレッドでメインスレッドで見つかりました。
実際には、そこなど無限ループ待ち、セマフォ(セマフォ)、など解決スレッド同期に多くの方法が、ありますが、上記の方法を使用することをお勧めします。

実際には、SDKがHandlerThreadを私たちに提供している、我々はいくつかの人々は、これはあなたの卵を傷つけるではないと言うかもしれないが、自分自身を達成する必要はありませんか?
私は、我々は彼らの思考を学ばなければならない、私はすべてのクラスおよびAPI SDKそれことをはっきり言うことができ、私たちだけでなく、SDKが提供されるAPIを使用する必要があることを言いたいですか?私は本当にHandlerThreadにこのクラスを知らない初めに、その後、プロジェクトのニーズがあり、このクラスを達成することができました、私は非常にはっきりと覚えて、このクラスは非常に単純なものの、唯一見つけるために、スレッドの同期の問題に注意を払うために時間の使用が開始されますそれは、このような動作原理ハンドラ、スレッド同期など、多くの知識を必要とします。
ここでは、HandlerThreadシステムを見てみましょう。
ここに画像を挿入説明
これらの2つのコンストラクタを通じて、私たちは、このスレッドとセットの優先順位の名前を見つけることができます。
ここに画像を挿入説明
よりonLooperPrepared方法と書き換えサブクラス化することで、当社のrunメソッドを、比較してください。
私たちは、getLooper方法を見て:
ここに画像を挿入説明
私は次のように除いて、同期コードブロックの主な違いを書きました:

  1. 私たちは、裁判官、裁判官のwhileループシステムにある場合。
  2. 我々はのisAlive、およびシステムの判断を決定する時間がありません。
  3. 例外がスローされることなく、しかし、直接返さヌル。

レッツは、最初の質問は、whileループかどうか、あなたが呼び出す場合を考えると思います

handlerThread.notifyAll();

その後、我々は、whileループは限りルーパーがnull待っているように、必要であるので、明らかにこれは、私たちが望むものではありません、NULLを返します。

第二の問題:再解釈の必要性を循環させながらすでに述べたように判断のisAlive()は、待ち時間が操作を保留していることをノートでは、ユーザーがスレッドを終了したときに保留中の場合は、スレッドがこの時点で終わっているので、裁判官する必要があります。

3番目の質問:例外またはリターンヌルを投げて、そして今、これらの2つの方法は非常に良いではないことを感じる個人的に来てほしい、最初のヌルケースを処理するために、ユーザが必要となるすべての戻りヌルの、例外をスローすると、使用中のあまり便利になりますされ、ユーザー:自分の例外を処理する必要性は、以下のように
ここに画像を挿入説明
しようとする...キャッチ、ユーザーが必要な
ものの2対1のリターンはnullを、そしてより良いと思うが、我々はいくつかの使用に注意を払う必要があるとき。
HandlerThreadソースを見て続行します。

ここに画像を挿入説明
このハンドラは、どのようにそれをすることのhandleMessageの道を上書きする場合はここでHandlerオブジェクトは、ありますか?一時的にどのように意味のこの方法を考えていませんでしたか?

外観に続行:
ここに画像を挿入説明
ここでは、出口への2つの方法があり、これらの2つの方法は、もはやここに説明するために、メソッドのルーパーのではありません。

結論:多くの側面が含まれ、このような単純な関数、ソースコードを見たときにすることはより重要であるが、自分の考えを学ぶことですが、あなたが考えることができたときに、ソースコードを見ると、私はこの関数を記述した場合、どのように私はできています書き込みに?ちょうどそれについて考えてはいけない、ない手は-にシステムを書き込み後、書き込みと比較するより多くの事を学びます。

公開された113元の記事 ウォン称賛66 ビュー30万+

おすすめ

転載: blog.csdn.net/mengks1987/article/details/87797941