Android進級:六、サブスレッドで直接Toastとその原理を使用する

3080 ワード

最近个人的な原因のため、长い间更に文章がなくて、関心の小さい仲间に感谢して、理解してください!
一般的にToastはUIコントロールとしてメインスレッドに表示されます.ただし、サブスレッドにToastを表示したくない場合は、Handlerを使用してメインスレッド表示に切り替えます.
しかし、サブスレッドには本当にToastが直接表示されないのでしょうか.
答えは:もちろんです.
どうすればいいですか?現在のスレッドでLooperを1つ初期化すればいい!
Looper.prepare();
Toast.makeText(getBaseContext(), "text", Toast.LENGTH_LONG).show();
Looper.loop();

なぜサブスレッドでToastを使用するには最初のLooperが必要なのでしょうか.ソースコードを見てみましょう.
    public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
        return makeText(context, null, text, duration);
    }


public static Toast makeText(@NonNull Context context, @Nullable Looper looper,
            @NonNull CharSequence text, @Duration int duration) {
        Toast result = new Toast(context, looper);
        ...
        return result;
    }

以上はToastで呼び出された静的メソッドであり,2番目のメソッドにはパラメータLooperが見られるが,我々が普段使っているときにnullが伝わっているが,このLooperはいったい何の役に立つのだろうか.Toastのコンストラクション関数を見てみましょう.
  public Toast(@NonNull Context context, @Nullable Looper looper) {
        mContext = context;
        mTN = new TN(context.getPackageName(), looper);
    }

このLooperはTNで使われていることがわかります.構造関数を見てみましょう.
        TN(String packageName, @Nullable Looper looper) {
            if (looper == null) {
                // Use Looper.myLooper() if looper is not specified.
                looper = Looper.myLooper();
                if (looper == null) {
                    throw new RuntimeException(
                            "Can't toast on a thread that has not called Looper.prepare()");
                }
            }

        }

以上のコードは簡略化されています.Looperがnullの場合、現在のLooperがLooper.myLooperによって取得されることがわかります.メインスレッドではシステムがmainLooperを初期化していることを知っていますので、一般的には管理しません.しかし、サブスレッドでLooperが初期化されていない場合、ここでLooper.myLooperを呼び出すとLooperが1つも取得されず、例外が放出されます.したがって、サブスレッドでToastを使用し、Looper.prepare()メソッドを使用してLooperを初期化し、Looper.loop()を使用して起動すればよい.
任意のスレッドで使用できるToastをカプセル化することができます
  private static Toast toast = null;
    public static void showToast(Context context, String text) {
        Looper myLooper = Looper.myLooper();
        if (myLooper == null) {
            Looper.prepare();
            myLooper = Looper.myLooper();
        }

        if (toast == null) {
            toast = Toast.makeText(context, text, Toast.LENGTH_LONG);
            toast.setGravity(Gravity.CENTER, 0, 0);
        }
        toast.show();
        if ( myLooper != null) {
            Looper.loop();
            myLooper.quit();
        }
    }

Toastを初期化する前に、現在のスレッドのlooperが空であるかどうかを判断し、空であれば新しいmyLooperを初期化し、Toastのshowメソッドを呼び出した後にlooperを起動すればよい.Looperのloop()メソッドは無限ループであるため,Looperがスレッドをブロックすることを防止するためにメモリ漏洩の原因となる場合は直ちにLooperを終了すべきである.
最後に書く
多くの人がこの業界に接触したばかりの時やボトルネック期に遭遇した時、いつもいくつかの問題に直面して、例えばしばらく勉強して方向感がなくて、そこから学ぶべきか分からないで、これに対して私はいくつかの資料を整理して、必要なのは無料でみんなに分かち合うことができます
もし私の文章が好きで、ベテランの開発者と一緒に交流して勉強したいならば、もっと関連する大工場の面接コンサルティングと指導を得て、私の協力グループAndroid Senior Engineer技術交流グループに参加することを歓迎します:925019412