Keeping track of View added to WindowManager (no f

2020-02-23 07:27发布

问题:

In my service I add a view to WindowManager with addView(). When I'm ready to hide the view, I call removeView() using the View reference. This works great -- most of the time.

I have occasional Force Close reports that say that the View is not attached to the WindowManager. This makes sense. The problem is that I think the service is getting killed by Android, and when it is time to hide the view, it attempts to removeView on the wrong View.

I have tried checking for the View to be null, but apparently it isn't at this point, it simply isn't the one attached to the WindowManager. It seems that if the View reference is lost, there is no way to gain access to it again.

How can I get the equivalent of findViewById() on the WindowManager itself? Is the View automatically removed from WindowManager if my service is stopped (killed)? Is there a way I can store the reference to the View so that if the service is stopped I can still remove the View later (I'm also trying to avoid leaking the View)?

回答1:

In my service I add a view to WindowManager with addView(). When I'm ready to hide the view, I call removeView() using the View reference. This works great--most of the time. I have occasional Force Close reports that say that the View is not attached to the WindowManager.

I am having the exact same problem. Hopefully an expert will chime in.

How can I get the equivalent of findViewById() on the WindowManager itself?

Keep a reference to the View that was added and simply use removeView(mView).

Currently in my Service, to add the view:

WindowManager.LayoutParams params = ...
mView = new View(this);
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);

Then to remove the view, I avoid occasional FC by catching the exception:

WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
try {
    wm.removeView(mView);
} catch (Exception e) {}

Is the View automatically removed from WindowManager if my service is stopped (killed)?

In my experience, they are removed when the service is killed. You can test this by stopping your service without removing the views. No idea why that works though.

My concern is that my second reference to the WM is different when I go to remove the view. If that is the case, is mView still being displayed when I catch the exception? I would try keeping a reference to the WM when I add the view, but I've had issues where references to System Services seem to go bad over time.

Let me know if you ever solved this problem.



回答2:

To check if view has been succesfully attached to Windows Manager, or is still attached, you can use view.isShown();.



回答3:

Check that the views parent != null before trying to remove it.

if(mView.getParent() != null){
   wm.removeView(mView);
}


回答4:

You can also use:

ViewCompat.isAttachedToWindow(mView);

According the docs:

Returns true if the provided view is currently attached to a window.