View编程(8): 自定义 View 如何注册广播

想象这样一种情景:自定义 View 需要在外界条件改变的时候,改变自己的状态,并且这个条件改变的同时会发送一条广播,那麽如何做呢?


在  android opensource: Settings 研究_android 组件如何响应语言变化 博客中,说过我会跟大家交流一下如何在自己定义的 View 中注册以及接收广播。


在贴代码之前,先看看 View 的两个回调方法 onAttachedToWindow、onDetachedFromWindow.


从 api 不难看出,onAttachedToWindow、onDetachedFromWindow 分别在 view 依附到 window、脱离 window 时回调。源码如下:

 /**
     * This is called when the view is attached to a window.  At this point it
     * has a Surface and will start drawing.  Note that this function is
     * guaranteed to be called before {@link #onDraw}, however it may be called
     * any time before the first onDraw -- including before or after
     * {@link #onMeasure}.
     *
     * @see #onDetachedFromWindow()
     */
    protected void onAttachedToWindow() {
        if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
            mParent.requestTransparentRegion(this);
        }
    }

    /**
     * This is called when the view is detached from a window.  At this point it
     * no longer has a surface for drawing.
     *
     * @see #onAttachedToWindow()
     */
    protected void onDetachedFromWindow() {
        if (mPendingCheckForLongPress != null) {
            removeCallbacks(mPendingCheckForLongPress);
        }
        destroyDrawingCache();
    }

还需要搞明白一个问题,onDraw 方法与这两个回调方法的调用顺序。

D/mark-   (  316): onAttachedToWindow()
D/mark-   (  316): onDraw()
D/mark-   (  316): onDetachedFromWindow()

当我们运行 App,然后退出 App(点击Back,或者kill,不是点击Home),调用顺序如上所示。

看一个 android 源码的例子:

@Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        if (!mAttached) {
            mAttached = true;
            IntentFilter filter = new IntentFilter();
            filter.addAction(Telephony.Intents.SPN_STRINGS_UPDATED_ACTION);
            getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mAttached) {
            getContext().unregisterReceiver(mIntentReceiver);
            mAttached = false;
        }
    }

可以看出,注册和取消注册广播的操作是在两个回调方法中完成的。

其中,mAttached 是定义的一个 boolean 值。这个地方值得借鉴学习!

private boolean mAttached;

接收并处理广播的逻辑在这里:

private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (Telephony.Intents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
                updateNetworkName(intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_SPN, false),
                        intent.getStringExtra(Telephony.Intents.EXTRA_SPN),
                        intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_PLMN, false),
                        intent.getStringExtra(Telephony.Intents.EXTRA_PLMN));
            }
        }
    };

完整的源码,可以自行看

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/CarrierLabel.java


其中,CarrierLabel.java 是一个自定义的 TextView.


再延伸一步考虑,我们可以在这两个回调方法里面还可以发送广播、启动一个 android 组件等,希望对你有用!




©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页