【Andorid】 回调监听 - 结合单例模式,接口实现异步的资源加载监听(结合Glide和Okhttp的图片资源加载功能)

需求提出

跟进项目时候Leader给了我一个需求:提供一个广告位给每个app复用

构建思路

这个广告位是跟后台进行交互,获取后台提供的json,json中会带有图片资源url和点击之后跳转的href。
这是一个模块化的东西,整个lib包供所有的项目的使用。

  • 实现glide调用网络图片的代码
 private void glideLoad() {
        try {
            Glide.with(getContext())
                    .load(GoLoginManager.getInstance().adImageJsonObject.getImageUrl())
                    .listener(new RequestListener<Drawable>() {
                        @Override
                        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                            return false;
                        }

                        @Override
                        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                            if (adImageDisplayCompletionCallback != null) {
                                adImageDisplayCompletionCallback.onSuccess();
                            }
                            return false;
                        }
                    })
                    .into(GoAdImageView.this);
        } catch (Exception e) {
            if (adImageDisplayCompletionCallback != null) {
                adImageDisplayCompletionCallback.onFailure(ERROR_FAIL_GLIDE_LOAD);
            }
        }

        //实现跳转到一个WebView
        setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                GoWebViewActivity.jumpActivity(getContext(), GoLoginManager.getInstance().adImageJsonObject.getHref(), "网页标题");
            }
        });
    }

深入优化

之前我写的代码,实现了这个广告位的功能即“展示广告”,点击跳转。
但是毕竟我是菜鸟,思维没那么严谨。
没有考虑到应用层调用广告位的调用方法的时候

要是网络资源晚点到,那应用层调用后是不会有展示的;而后资源到了,该调用就已经激发过了,这样资源就不会被使用到,存在浪费。

  • 这个广告位是当以一个ImageView来使用的,通过应用层来调用加载方法和一个监听实现是否成功。
    在应用层上的调用方法。
 //初始化广告位
        advertiseImageView.startImageLoad(new GoAdImageView.IGoAdImageDisplayCompletionCallback() {
            @Override
            public void onSuccess() {
                Log.d("MainSettingActivity_ad","onSuccess");
                advertiseImageView.setVisibility(View.VISIBLE);
            }

            @Override
            public void onFailure(int errorCode) {
                Log.d("MainSettingActivity_ad","onFailure:"+errorCode);
            }
        });
  • 还有网络交互的okhttp,这一点就是上面👆所提及过的特殊情况。只有有网络交互就极大可能存在异步问题。所需要网络资源就得走网络。在本需求中使用使用到网络资源。

示意草图
理想情况和实际情况

主要是理解如何创建和设置监听?在哪里设置监听?监听回调什么?

如何创建监听?

首先肯定得构建一个接口专门用来实现方法来达到监听的目的。
如下的代码是:网络资源申请的接口。
因为是整个lib项目,作为一个大模块供上层使用所以提供一个单例模式下的对象进行操作。这接口就是放在这些对象中才是比较合适的。唯一嘛~

 // 广告位资源监听
    // 监听广告位的资源加载
    public interface IGoReqAdImageInfoCallback {
        void onSuccess();
        void onFailure();
    }
    public IGoReqAdImageInfoCallback reqAdImageInfoCallback;

哪里设置监听?

回到需求优化的点,主要是针对后台给的网络数据的延迟进行处理所以设置这个监听肯定得在进行网络数据申请时候进行监听,如果得到了资源就执行成功方法,反之就执行失败方法。

 // 预加载广告
        if (GoLoginManager.getInstance().adImageJsonObject == null){
            //加载广告位资源
            BizAPI.getAdvertiseInfo(new IAdImageListener<AdImageJsonObject>() {
                @Override
                public void onAdImageInfoLoaded(int errorCode, AdImageJsonObject adImageJsonObject) {
                    if(adImageJsonObject != null){
                        GoLoginManager.getInstance().adImageJsonObject = adImageJsonObject;
                        //这里是才是设置回调的关键
                        if(GoLoginManager.getInstance().reqAdImageInfoCallback != null){
                            GoLoginManager.getInstance().reqAdImageInfoCallback.onSuccess();
                        }
                    }else{
                        if(GoLoginManager.getInstance().reqAdImageInfoCallback != null){
                            GoLoginManager.getInstance().reqAdImageInfoCallback.onFailure();
                        }
                    }
                }
            });
        }

以上的代码就可以确定你根据实际的反馈进行监听。但是到这一步会不会在想,这时候reqAdImageInfoCallback不还没给new出来过吗?那么就是空的呀?就算到了也不会执行呀!!!别急,这不是还有嘛?

监听回调什么?

书接上文,根据需求是需要在应用层来调用这个广告位模块的。所以最好得在这个模块内实现这个上面设置监听的部分所要给的回调Callback,也就是说要new一个出来!!!
在AdImageView这个广告位对象中就new出来一个新的回调,看到里面的
`glideLoad``方法了吗?回到文章最开头post的代码,这一块就是实现和glide进行交互加载图片的方法。
逻辑上讲,这时候,资源加载完毕后进行glide操作是合情合理的。

   private GoLoginManager.IGoReqAdImageInfoCallback loadAdImageInfoCallback = new GoLoginManager.IGoReqAdImageInfoCallback() {
        @Override
        public void onSuccess() {
            glideLoad();
        }

        @Override
        public void onFailure() {

        }
    };

但是,对象是new出来了,还没赋值给之前单例模式下的回调呢??

如何设置监听?

那么就得在合适的环节进行赋值,相当于一个开关告诉它我准备要进行监听了,你给我守好,一来资源你就给我调用——而不是简单的if-else只是单一的操作只会一次激发判断,错过就不再触发。
所以就得再AdImageView对象中正式启动该需求功能的方法下进行设计:

//进行广告位展示
    public void startImageLoad(IGoAdImageDisplayCompletionCallback IGoAdImageDisplayCompletionCallback){
        this.adImageDisplayCompletionCallback = IGoAdImageDisplayCompletionCallback;
        /**
         *资源没到就等到
         */
        if (GoLoginManager.getInstance().adImageJsonObject != null) {
            glideLoad();
        } else {
            GoLoginManager.getInstance().reqAdImageInfoCallback = loadAdImageInfoCallback;//就在这里赋值回去进行监听。
        }
    }

逻辑还是如此,资源到了就干活,资源没到就等到它到了再干活。这个监听就是这一等待的过程!
谢谢你看到最后,如果有学到东西或者有意义? 不妨给我个赞👍 吧!这也是我这个菜鸡学习的动力之一哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值