美文网首页
Android切面实践

Android切面实践

作者: sgfb | 来源:发表于2020-03-12 00:13 被阅读0次

开篇

首先这不是一篇教程,更像是开发过程中的随笔所以建议抱着讨论与批评的态度观看

切面编程的基础概念我这里不做介绍,请自行搜索学习。
在Android中比较少使用到切面编程相关,在自行摸索了一段时间之后整理了点概念和一些实用性的功能,
目前的感觉是在Android中切面编程主要职责并不是单纯为简化代码(当然部分功能可以简化代码),简化代码应该是方法封装去做的。而切面是简化逻辑,把技术相关的逻辑都封装了再配合方法简化缩短实际代码,这样剩下的都是真实的业务层逻辑和代码。

在这里抛出一个使用切面优化案例:拍照上传用户新头像且立即保存
这个需求至少看起来很简单,但是几个技术细节会增加实际代码的复杂度。

首先拍照就需要运行时权限,
然后调起照相机拍照,
再然后调用上传文件接口(返回得到图片地址),
最后调用修改用户头像接口。

以上是整条逻辑都是成功的情况,如果考虑到失败的情况可以有8种走向,而且这4个步骤都需要回调所以逻辑和代码必然有冗余。

一个简化版实现(使用第三方辅助,未处理错误等逻辑)

使用了3个第三方
1.权限请求(com.yanzhenjie:permission)
2.网络请求及异步辅助(retrofit+rx+okhttp)
3.照片请求(com.github.LuckSiege.PictureSelector:picture_library)

    /**
     * 请求权限
     */
    private void requestPermission(){
        Options permissionHelp=AndPermission.with(TakePictureDemoActivity.this);
        permissionHelp.runtime()
                .permission(Manifest.permission.CAMERA)
                .onGranted(data -> {
                    getImageFromCamera();
                })
                .onDenied(data -> {
                    //提示请求权限
                })
                .start();
    }

    /**
     * 调用照相机取得照片
     */
    private void getImageFromCamera(){
        PictureSelector.create(TakePictureDemoActivity.this)
                .openCamera(PictureMimeType.ofImage())
                .forResult(new OnResultCallbackListener() {
                    @Override
                    public void onResult(List<LocalMedia> result) {
                        uploadAvatarAndChangeAvatar(result.get(0).getPath());
                    }

                    @Override
                    public void onCancel() {

                    }
                });
    }

    /**
     * 上传头像并且得到返回的头像url后调用接口修改头像地址
     */
    private void uploadAvatarAndChangeAvatar(String avatarPath){
        RequestBody file=RequestBody.create(MediaType.parse("image/jpg"),new File(avatarPath));
        MultipartBody.Part part=MultipartBody.Part.createFormData("file","image.jpg",file);
        mInterface.uploadFile(part)
                .flatMap((Func1<Response<String>, Observable<Response<Boolean>>>) stringResponse -> mInterface.updateUserAvatar(stringResponse.data))
                .subscribe(new Action1<Response<Boolean>>() {
                    @Override
                    public void call(Response<Boolean> booleanResponse) {
                        if(booleanResponse.data)
                            System.out.println("头像修改成功");
                    }
                });
    }

首先是一屏高的长度显的略长,其次使用了3个方法意味着以后维护时需要跳转3次去读这些代码,并且每个方法中都使用了回调增加了阅读理解成本

使用切面后实现同样功能

private void changeAvatar(){
        //使用照相机拍照获取返回的照片
        String imagePath=mController.getImageFromCamera();
        //上传照片并得到返回的url
        String imageUrl=mController.uploadFile(new File(imagePath));
        //调用接口修改头像地址
        mController.changeAvatar(imageUrl);
    }

//////////Controller切面实现
    @GetImageFromCamera
    public String getImageFromCamera(){
        return "";
    }

    public String uploadFile(File file){
        return mInterface.uploadFile(file);
    }

    public boolean changeAvatar(String avatarUrl){
        return mInterface.changeAvatar(avatarUrl);
    }

首先代码量减少,且重点逻辑变成顺序执行而不是原先的套娃形式。抽出了高级抽象作为主执行,而实际进行具体处理的是小弟Controller这也的拆分设计也很比较合理。

新建位图图像.jpg

最后

在之后文章中我会解释如何具体实现本篇提及的切面功能。

相关文章

网友评论

      本文标题:Android切面实践

      本文链接:https://www.haomeiwen.com/subject/bwvkjhtx.html