WindowInspector(ウィンドウインスペクター)は2年間出ていますが、まだわかりませんか?!!

この記事はHaowenSummoningOrderアクティビティに参加しています。クリックして表示します。バックエンドとフロントエンドのデュアルトラックの提出物で、20,000元の賞金プールがあなたの挑戦を待っています!

序文

この知識のポイントは2年間出ていましたが、今はインターネットで検索していますが、関連する共有は見られません。フローティングウィンドウの問題点を解決するためにAndroid10でのみ追加された非常に使いやすいApi。私の経験を皆さんと共有させてください。それがお役に立てば幸いです。

フローティングウィンドウの問題点(ビューは添付)

なぜ「ビューの判断はアタッチである」と言うのは、フローティングウィンドウの問題点です。

Android10より前

WinodwManagerは、addViewおよびremoveView操作を提供します。クエリインターフェイスはありません。ビューが追加されているかどうかを判断する方法は、ビューをアタッチすることだけです。「ウィンドウマネージャに接続されていないビュー」のソースコードログを追加すると、開発者は、View.isAttachedToWindowで判断することにより、使用中のリスクを調査することなく、ビューがウィンドウ上にあるかどうかを判断できると確信できます。

残念ながら、他の優れたAPIがなければ、View.isAttachedToWindowを使用することがほとんど唯一のオプションになりました。

Android 10は新しいAPIをプッシュし、開発者により良い選択肢を提供します。

ケースを使用してこのAPIを説明し、この問題点を解決してください。

ケースレビュー

フローティングウィンドウの使用

windowManager.addView(view, layoutParams);//新增窗口
windowManager.removeView(view);移除窗口
复制代码

ただし、追加または削除するとクラッシュが発生しやすくなります。ログは次のとおりです。

例:同じビューが2回追加されます

05-21 03:19:13.285 3463 3463 W System.err: java.lang.IllegalStateException: View XXX{7afdd92 V.E...... ......I. 0,0-56,290} has already been added to the window manager.

05-21 03:19:13.285 3463 3463 W System.err:  at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:359)

05-21 03:19:13.285 3463 3463 W System.err:  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:96)
复制代码

アタッチせずにウィンドウを削除する

W System.err: java.lang.IllegalArgumentException: View=XXXX{25626d6 V.E...... ........ 0,0-56,229} not attached to window manager

08-19 07:08:08.832 25836 25836 W System.err:   at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:517)

08-19 07:08:08.832 25836 25836 W System.err:   at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:426)

08-19 07:08:08.832 25836 25836 W System.err:   at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:123)
复制代码

通常の解決策:ログプロンプトが添付されていない-> View.isAttachedToWindowを使用して、コードを次のように判断します。

if(view.isAttachedToWindow()){
    try {
        windowManager.removeView(textView);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
if(!view.isAttachedToWindow()){
    try {
        windowManager.addView(view,layoutParams);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
复制代码

発生した問題

上記のコードを使用しますが、プロジェクトでクラッシュする可能性はまだ非常に低いです。

つまり、isAttachedToWindow≠ビューはウィンドウの追加です

問題を解く

  • オプション1:

    应用中给View标志位,表示view 是否被add。但是总觉得本地标识,没有系统api准确,该方案不算太好。偶现的问题,必然有必现的过程,后面进行了深入的分析。

    项目中遇到的问题是:同一个view,windowManager.addView 被连续执行了两次,也不是异步造成的。

    最后发现,两次调用时间间隔极短,isAttachedToWindow 还没有来得及改变。

    经详细调查有了方案二。

  • 方案二:

    使用 WindowInspector,此类在Android 10 framework 才增加,且只有getGlobalWindowViews 这一个静态方法

    view.isAttachedToWindow() 改为 WindowInspector.getGlobalWindowViews().contains(view)
    复制代码

源码分析

getGlobalWindowViews

看下主要类的调用关系,以及主要的方法

RmzUoV.png

/**
* addView 与 removeView 都会调用此方法
* addView  required:false 如果 index !=0  同一个View重复add,抛异常
* removeView required:true  index < 0 ,没有找到View,抛异常
*/
private int findViewLocked(View view, boolean required) {
    final int index = mViews.indexOf(view);
    if (required && index < 0) {
        throw new IllegalArgumentException("View=" + view + " not attached to window manager");
    }
    return index;
}
复制代码

通过以上分析:WindowManagerGlobal 中 mView 是问题的关键,管理着所属应用的所有View。

Android 10,提供了 WindowInspector.getGlobalWindowViews()。可以获取mViews。修改代码如下

if(WindowInspector.getGlobalWindowViews().contains(view)){
    windowManager.removeView(view);
}
if(!WindowInspector.getGlobalWindowViews().contains(view)){
    windowManager.addView(view,layoutParams);
}
复制代码

分析到这里,问题就解决了。那isAttachedToWindow 怎么就不行呢?

isAttachedToWindow

以下时序图看出:

当刷新线程走完后,才认为是attach。

在这里插入图片描述

两者区别是:attach 当view 被add ,且被刷新了。

总结

经过上文分析,从view add -> attach , 区别是view 是否被刷新。

分析了下:为什么要重新用WindowInspector,而不是用WIndowManager WindowManager:是对Window 的管理,查询觉得不合适吧,所以用了WindowInspector类

下面说明下可能出现的一些误区

1、getGlobalWindowViews 获取的View列表 ,其实是WindowManagerGlobal.mViews 的浅拷贝,所以增删改,都不会应该WindowManagerGlobal 中mViews的结构。

2、强调下,不要被Global迷惑,Global的范围是应用级别的,获取不到其他应用的窗口。

おすすめ

転載: juejin.im/post/6981476971394007054