Android MVP-编程思想6(依赖注入多个P层方式优化---注解,反射)

前言

通过一个小的登录功能模块案例,帮助大家了解MVP。最终实现一个结合Rxjava2,Retrofit 的MVP通用框架。代码放到github上。(如有错误之处,请在评论区指出,谢谢。如果感觉写的不错,请点赞,关注,谢谢。)

目录:

Android MVP-编程思想1(什么是MVC-MVP-MVVM模式?)
Android MVP-编程思想2(代码实现初级版)
Android MVP-编程思想3(内存泄露问题处理,基类封装,有没有必要再使用软引用?)
Android MVP-编程思想4(AOP思想-动态代理运用,反射创建M层实例对象)
Android MVP-编程思想5(如何处理多个P层的问题?)
Android MVP-编程思想6(依赖注入多个P层优化—注解,反射)
Android MVP-编程思想7(为什么使用代理类抽取通用方法而不是工具类?,基类BaseMvpFragment)

未完待续--------
Android MVP-编程思想8(集成Rxjava2,Retrofit)

上一小节就是讲解多个P的处理思想。非常简单,使用容器存储就Ok了。这一小节,讲解使用如何使用注解和反射形式创建P的实例对象。目的有两个(1)是减少基类(父类)和子类的直接依赖。基类不需要通过createPresenter方式 注入P的引用,(2)减少代码,去掉繁琐的创建操作。

每次都要实现createPresenter()方法,这种依赖注入的方式能否优化?

解决思路一句话:注解扫描,反射创建实例化对象
看代码

创建注解类 InjectPresenter
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InjectPresenter {
}
在LoginActivity 使用InjectPresenter
    @InjectPresenter
    private LoginPresenter loginPresenter;
改动BaseMvpActivity 扫描注解,反射创建P对象
 private void initPresenterByScanAnnotation() {
        mPresenters = new ArrayList<>();
        //获得已经申明的变量,包括私有的
        Field[] fields = this.getClass().getDeclaredFields();
        for (Field field : fields) {
            //获取变量上面的注解类型
            InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class);
            if (injectPresenter != null) {
                try {
                    Class<? extends BasePresenter> type = (Class<? extends BasePresenter>) field.getType();
                    BasePresenter mInjectPresenter = type.newInstance();
                    mInjectPresenter.attachView(this);
                    field.setAccessible(true);
                    field.set(this, mInjectPresenter);
                    mPresenters.add(mInjectPresenter);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (ClassCastException e) {
                    e.printStackTrace();
                    throw new RuntimeException("SubClass must extends Class:BasePresenter");
                }
            }
        }
    }
BaseMvpActivity 修改之后的代码
public abstract class BaseMvpActivity extends AppCompatActivity {
    protected List<BasePresenter> mPresenters;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View rootView;
        final Object layout = getLayout();
        if (layout instanceof Integer) {
            rootView = View.inflate(this, (int) getLayout(), null);
        } else if (layout instanceof View) {
            rootView = (View) getLayout();
        } else {
            throw new ClassCastException("type of setLayout() must be int or View!");
        }
        setContentView(rootView);
        initPresenterByScanAnnotation();
        afterCreate();
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        for (BasePresenter p : mPresenters) {
            p.detachView();
        }
        mPresenters.clear();
        mPresenters = null;
    }

    private void initPresenterByScanAnnotation() {
        mPresenters = new ArrayList<>();
        //获得已经申明的变量,包括私有的
        Field[] fields = this.getClass().getDeclaredFields();
        for (Field field : fields) {
            //获取变量上面的注解类型
            InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class);
            if (injectPresenter != null) {
                try {
                    Class<? extends BasePresenter> type = (Class<? extends BasePresenter>) field.getType();
                    BasePresenter mInjectPresenter = type.newInstance();
                    mInjectPresenter.attachView(this);
                    field.setAccessible(true);
                    field.set(this, mInjectPresenter);
                    mPresenters.add(mInjectPresenter);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (ClassCastException e) {
                    e.printStackTrace();
                    throw new RuntimeException("SubClass must extends Class:BasePresenter");
                }
            }
        }
    }

    @SuppressWarnings("ConstantConditions")
    protected <T extends View> T $(@IdRes int viewId) {
        return findViewById(viewId);
    }

    public void showProgress(boolean isShow) {
        if (isShow) {
            Log.i("mvp_", "显示等待框");
        } else {
            Log.i("mvp_", "隐藏等待框");
        }
    }

    public void showToast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }

    protected abstract Object getLayout();

    protected abstract void afterCreate();
}
LoginActivity 修改之后的代码
public class LoginActivity extends BaseMvpActivity implements LoginContract.IView {
    @InjectPresenter
    private LoginPresenter loginPresenter;

    @Override
    protected Object getLayout() {
        return R.layout.activity_main;
    }


    @Override
    protected void afterCreate() {
        $(R.id.btn_login).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                loginPresenter.onClickLogin("xxx", "xxx");
            }
        });
    }

    @Override
    public void goToMainActivity() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //todo 登录成功跳转到主界面
                Log.i("mvp_", "登录成功跳转到主界面");
            }
        });

    }

    @Override
    public void showProgress(boolean isShow) {
        if (isShow) {
            Log.i("mvp_", "显示等待框");
        } else {
            Log.i("mvp_", "隐藏等待框");
        }
    }

    @Override
    public void showToast(String str) {
        Toast.makeText(this, str, Toast.LENGTH_LONG).show();
    }
}

很明显优化之后的依赖注入方式使得代码更精简,同时也减少基类(父类)和子类的依赖。
下一节实现BaseMvpFragment基类。同时使用代理类的方式抽离通用方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基本功能 2016/10/31 添加抽奖功能,修复已知Bug(点击删除购物,出现闪退bug) 2016/10/28 添加微信分享功能 2016/10/28 添加忘记密码功能、完善用户评价系统、以及完善订单页面按钮功能及显示 2016/10/27 添加自动更新功能,修复已知的登陆闪退Bug 2016/10/26 添加订单查询(全部订单、待付款、待发货、待收货、待评价、退款和售后等查询)以及显示功能,收藏宝贝查询、及显示功能 2016/10/25 添加加入购物车功能、移除购物车中的商品和下单之后更新购物车等功能 2016/10/24 添加评论功能的显示、登陆用户的收藏和取消收藏功能、下单页面的显示、以及下单功能的实现 2016/10/23 添加商品的类别显示、分类查询展示、固定数据的搜索(暂时数据固定) 2016/10/22 添加用户注销功能、头像的上传以及更新用户个人资料功能 2016/10/20 添加注册、登陆、加载默认头像等功能、解决ViewPager Fragment 中Fragment被预加载问 2016/10/19 进行主页、微淘、问大家、购物车、我的淘宝等页面的设计、添加轮播图、资讯滚动条功能 2016/10/18 构建基本MVP框架 开发过程中遇到的问题(可能导致程序无法运行的bug)及解决方案 当用户未登录时,点击购物车,登陆之后,程序闪退 出现问题 :NullPointerException 解决方案: 使用Fragment的延时加载(懒加载)实现对数据的加载 拍照时无法进行图片的裁剪(不断加载) 解决步骤如下: Activity跳转时图库时的Intent如下 Intent takePhotoIntent = new Intent( “android.media.action.IMAGE_CAPTURE”); takePhotoIntent.putExtra( MediaStore.EXTRA_OUTPUT, imageUri); 在onActivityResult()方法中调用P进行处理,相关代码如下 String uri = Environment.getExternalStorageDirectory() “/icoImage.jpg”; if(!allSelectedPicture.contains(uri)){ allSelectedPicture.add(uri); } ViewPager和Fragment结合使用,Fragment出现被预计载的情况 解决方案 项目中使用的主要技术及框架 框架 ButterKnife 注解绑定获取控件功能 Picasso 网络和本地图片的加载功能 okhttp 网络连接功能

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值