教你对Android项目的需求进行封装抽象(下)

我们来实现Android端的弹框显示逻辑,由于需要显示的分享弹框业务种类有八种,所以必要的封装和抽象是必要的

1.封装前后台切换监听

点击参考这篇前后台切换管理类

在应用的主页的onCreate()中调用:

       //根据前后台切换监听检测是否有分享弹窗
        AppBackgroundManager.getInstance().initWatcher().setAppStateListener(new AppBackgroundManager.IAppStateChangeListener() {
            @Override
            public void onAppStateChanged(boolean isAppForceground) {

                if (isAppForceground) {
                   ShareCommandMgr.getInstance().startCheckShareCommand();
                }
            }
        });

考虑到项目中主页之前还有启动页,在前后台切换管理类的基础上,我加了一个方法,以便在第一次打开应用时,主页第一次走onCreate()时也能回调onAppStateChanged

    /**
     * 开始监听时调用,只允许调用一次
     */
    private boolean isInited = false;

    public AppBackgroundManager initWatcher() {
        if (!isInited) {
            isAppForeground = false;

            isInited = true;
        }
        return this;
    }


(因为注册的前后台监听是在主页,闪屏页启动之后,如果没有这个方法,第一次启动APP进入闪屏页,mListener == null,后续都在前台,主页就不会再走回调,而我希望第一次进入主页也会有回调。请细品代码哦)

    //App前后台切换
    private void onAppForegroundStateChange(boolean isAppForeground) {
        if (mListener == null) {
            return;
        }
        mListener.onAppStateChanged(isAppForeground);
    }

别忘了在应用的Application的onCreate中增加方法:

    /**
     * 注册监听应用全局activity生命周期的监听,判断应用前台后台切换
     */
    private void registerActivityLifeCycle() {
        getApplication().registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

            }

            @Override
            public void onActivityStarted(Activity activity) {
                AppBackgroundManager.getInstance().onActivityStarted(activity.getLocalClassName());
            }

            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {
                AppBackgroundManager.getInstance().onActivityStopped();
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

            }

            @Override
            public void onActivityDestroyed(Activity activity) {

            }
        });
    }

2.获取口令,获取分享数据

刚刚在前后台回调中做了如下调用,看看内部是如何封装的

ShareCommandMgr.getInstance().startCheckShareCommand();
/**
 * 分享弹窗管理类
 */
public class ShareCommandMgr {

    public static ShareCommandMgr uHelper;

    public static ShareCommandMgr getInstance() {
        if (uHelper == null) {
            synchronized (ShareCommandMgr.class) {
                if (uHelper == null) {
                    uHelper = new ShareCommandMgr();
                }
            }
        }
        return uHelper;
    }


    /**
     * 粘贴板是否含自己的口令
     * <p>
     * #LZ100_200000#
     * #LZabcdefg890123456#
     * 客户端判断 #LZ开头 和#结尾中间的内容code,
     * 若code的长度>16 或等于0则不处理;
     *
     * @return
     */
    public boolean isLzShareCommand() {

        if (StringUtils.isEmpty(ClipboardUtils.getText())) {
            return false;
        }
        String command = ClipboardUtils.getText().toString();

        if (StringUtils.isTrimEmpty(command)) {
            return false;
        }

        if (command.length() <= 4) {
            return false;
        }

        if (command.startsWith("#LZ") && command.endsWith("#")) {
            return true;
        }
        return false;
    }

    /**
     * 开始解析并显示口令
     */
    public void startCheckShareCommand() {

        //如果不是自己的口令直接退出
        if (!isLzShareCommand()) {
            return;
        }

        //获取粘贴板文本口令
        String commandFull = ClipboardUtils.getText().toString();

        //根据口令调接口
        getShareDataByCommand(commandFull);

    }

    public void getShareDataByCommand(String shareCode) {
        RetrofitFactory.composeAndAutoDispose(RetrofitFactory.getAPI().share_detail(shareCode), (AppCompatActivity) ActivityUtils.getTopActivity())
                .subscribe(new SmartObserver<ShareCommandData>(ActivityUtils.getTopActivity()) {
                    @Override
                    public void onSuccess(BaseBean<ShareCommandData> bean) {
                        if (bean.getData() == null) {
                            return;
                        }
                        //根据类型显示不同的口令弹窗
                        if (bean.getData().equipment != null) {
                            //显示设备弹窗
                            ShareCommandFactory.getInstance()
                                    .newShareCommandViewScene(ShareCommandFactory.TYPE_MACHINE)
                                    .setData(bean.getData(), bean.getData().equipment)
                                    .show();
                        } else if (bean.getData().equipmentdemand != null) {
                            //显示求租弹窗
                            ShareCommandFactory.getInstance()
                                    .newShareCommandViewScene(ShareCommandFactory.TYPE_RENT_OUT)
                                    .setData(bean.getData(), bean.getData().equipmentdemand)
                                    .show();
                        } else if (bean.getData().goods != null) {
                            //显示商品弹窗
                            ShareCommandFactory.getInstance()
                                    .newShareCommandViewScene(ShareCommandFactory.TYPE_PRODUCT)
                                    .setData(bean.getData(), bean.getData().goods)
                                    .show();
                        } else if (bean.getData().demand != null) {
                            //显示采购单弹窗
                            ShareCommandFactory.getInstance()
                                    .newShareCommandViewScene(ShareCommandFactory.TYPE_PURCHASE)
                                    .setData(bean.getData(), bean.getData().demand)
                                    .show();
                        } else if (bean.getData().recruit != null) {
                            //显示招聘弹窗
                            ShareCommandFactory.getInstance()
                                    .newShareCommandViewScene(ShareCommandFactory.TYPE_RECRUIT)
                                    .setData(bean.getData(), bean.getData().recruit)
                                    .show();
                        } else if (bean.getData().resume != null) {
                            //显示人才简历弹窗
                            ShareCommandFactory.getInstance()
                                    .newShareCommandViewScene(ShareCommandFactory.TYPE_TALENT)
                                    .setData(bean.getData(), bean.getData().resume)
                                    .show();
                        } else if (bean.getData().userinfo != null) {
                            //显示个人主页弹窗
                            ShareCommandFactory.getInstance()
                                    .newShareCommandViewScene(ShareCommandFactory.TYPE_PERSONAL)
                                    .setData(bean.getData(), bean.getData().userinfo)
                                    .show();

                        }else{
                            Log.i("LZ", "不支持的弹窗类型");
                        }

                        //清除粘贴板口令信息,防止重复进入应用重复显示弹窗
                        ClipboardUtils.copyText("");

                    }

                    @Override
                    public void onFailure(int code, String errorMsg) {
                        super.onFailure(code, errorMsg);
                    }
                });


    }

3.抽象弹窗显示

ShareCommandMgr 中显示弹窗的代码如下:

      //显示设备弹窗
                            ShareCommandFactory.getInstance()
                                    .newShareCommandViewScene(ShareCommandFactory.TYPE_MACHINE)
                                    .setData(bean.getData(), bean.getData().equipment)
                                    .show();

我们来看看内部实现,这里用了工厂模式,以较为优雅的方式创建不同风格的弹框,毕竟弹框种类不少:

/**
 * 分享弹窗工厂
 */
public class ShareCommandFactory {

    public static final int TYPE_MACHINE = 0;//机械设备
    public static final int TYPE_PURCHASE = 1;//采购单
    public static final int TYPE_RENT_OUT = 2;//求租
    public static final int TYPE_RECRUIT = 3;//招聘
    public static final int TYPE_TALENT = 4;//人才
    public static final int TYPE_PERSONAL = 5;//主页
    public static final int TYPE_PRODUCT = 6;//商品

    public static ShareCommandFactory uHelper;

    public static ShareCommandFactory getInstance() {
        if (uHelper == null) {
            synchronized (ShareCommandFactory.class) {
                if (uHelper == null) {
                    uHelper = new ShareCommandFactory();
                }
            }
        }
        return uHelper;
    }


    private IShareCommand iShareCommand = null;

    /**
     * 创建分享弹窗场景实例
     *
     * @param type
     * @return
     */
    public ShareCommandFactory newShareCommandViewScene(int type) {
        switch (type) {
            case TYPE_MACHINE:
                iShareCommand = new MachineSence();
                break;

            case TYPE_PURCHASE:
                iShareCommand = new PurchaseSence();
                break;

            case TYPE_RENT_OUT:
                iShareCommand = new RentOutSence();
                break;

            case TYPE_RECRUIT:
                iShareCommand = new RecruitSence();
                break;

            case TYPE_TALENT:
                iShareCommand = new TalentSence();
                break;

            case TYPE_PERSONAL:
                iShareCommand = new PersonalSence();
                break;

            case TYPE_PRODUCT:
                iShareCommand = new ProductSence();
                break;

            default:
                iShareCommand = new MachineSence();
                break;

        }
        return this;

    }

    /**
     * 设置弹窗中的数据
     * @param bean
     * @param data
     * @param <T>
     */
    public <T> ShareCommandFactory setData(ShareCommandData bean, T data){
        if (iShareCommand != null) {
            iShareCommand.setData(bean,data);
        }
        return this;
    }

    /**
     * 显示弹窗
     *
     */
    public void show() {
        if (iShareCommand != null) {
            iShareCommand.showShareSceneView();
        }

    }
}

对于弹窗的显示,我做了小小的抽象,写了个基类:

/**
 * 分享弹窗抽象类
 * @param <T>
 */
public abstract class IShareCommand<T> {

    /**
     * 数据
     */
    protected T mData;
    protected ShareCommandData mDataParent;
    /**
     * view
     */
    protected View mView;

    /**
     * 弹窗资源layout
     * @return
     */
    public abstract int getLayoutResId();

    /**
     * 绑定数据到界面
     */
    public abstract void bindDataToView();

    /**
     * 界面上点击查看详情按钮
     */
    public abstract void navigationTo();


    /**
     * 设置数据
     * @param mDataParent
     * @param data
     * @return
     */
    public IShareCommand setData(ShareCommandData mDataParent,T data) {
        this.mDataParent = mDataParent;
        mData = data;
        return this;
    }


    /**
     * 显示弹窗
     * @return
     */
    public IShareCommand showShareSceneView(){
        CustomDialog.show(ActivityUtils.getTopActivity(), getLayoutResId(), new CustomDialog.BindView() {
            @Override
            public void onBind(final CustomDialog dialog, View v) {

                mView = v;

                //弹窗界面相似逻辑基类统一处理start
                v.findViewById(R.id.ll_cancel).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        dialog.doDismiss();
                    }
                });
                v.findViewById(R.id.tv_navigation).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //跳转
                        navigationTo();
                        dialog.doDismiss();
                    }
                });


                GlideImageView avatar = mView.findViewById(R.id.iv_avatar);
                TextView username = mView.findViewById(R.id.tv_user_name);
                LinearLayout ll_share_user_top = mView.findViewById(R.id.ll_share_user_top);
                if (mDataParent.frominfo == null) {
                    ll_share_user_top.setVisibility(View.GONE);
                } else {
                    avatar.setImageUrl(mDataParent.frominfo.fromavatar);
                    username.setText(mDataParent.frominfo.nickname);
                }

                //弹窗界面相似逻辑基类统一处理end
                
                //绑定数据到界面
                bindDataToView();
            }
        });
        return this;
    }

}

然后每个业务场景的弹窗只需要继承这个抽象类,实现不同的弹窗风格,设置不同类型的数据,跳转到自己的详情页即可:
比如,其中一个弹窗示例:

/**
 * 机械设备分享弹窗
 */
public class MachineSence extends IShareCommand<ShareCommandData.Equipment> {
    /**
     * 弹窗界面
     * @return
     */
    @Override
    public int getLayoutResId() {
        return R.layout.share_command_machine_dialog;
    }

    /**
     * 绑定数据到界面
     */
    @Override
    public void bindDataToView() {
        GlideImageView ivTop = mView.findViewById(R.id.iv_top);
        if (!BosUtil.isRealUrl(mData.pic)) {
            ivTop.setImageUrl(BosUtil.getRealUrlByShort(mData.pic));
        } else {
            ivTop.setImageUrl(mData.pic);
        }

        TextView title = mView.findViewById(R.id.tv_title);
        title.setText(mData.title);

        TextView tv_name_price = mView.findViewById(R.id.tv_name_price);
        if (StringUtils.isEmpty(mData.rentpricelist) || mData.rentpricelist.equals("面议")) {
            tv_name_price.setText("面议");
        } else {
            tv_name_price.setText(mData.rentpricelist);
        }
    }

    /**
     * 跳转
     */
    @Override
    public void navigationTo() {
        ARouter.getInstance().build(RoutingTable.DeviceDetail)
                .withString("id", mData.id)
                .navigation();
    }

}

最后重新看下分享弹窗管理类调用代码显示弹窗逻辑:

    //显示设备弹窗
      ShareCommandFactory.getInstance()
             .newShareCommandViewScene(ShareCommandFactory.TYPE_MACHINE)
             .setData(bean.getData(), bean.getData().equipment)
             .show();

是不是很优雅的实现了弹窗的显示,这就是Java封装与抽象的魅力,这也和平时封装BaseActivity或者BaseFragment相似,只是这里多了个工厂模式,很简单,请客观细品。

欢迎关注公众号,给你更多技术干货:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值