美文网首页Android项目框架
Android项目框架之MVP+Dagger.Android+L

Android项目框架之MVP+Dagger.Android+L

作者: 海晨忆 | 来源:发表于2018-12-04 17:25 被阅读30次

    个人博客:haichenyi.com。感谢关注

      之前的那个系列从零开始搭建一个主流的项目框架(一 ~ 八),尽管把dagger2中inject activity 优化了一下,但是依然显得繁琐,每一个activity里面都要写一个inject方法。Dagger.Android只用在基类里面inject一次,子类里不用管,直接用。

      还有就是之前的MVP架构,每次更新页面的时候都要在每个页面对应的Contract——View里面写方法,在P层去实现然后在Activity里面也要实现一遍,这样太繁琐,现在用上LiveData,解决了这个问题,并且LiveData的优点:

    1. 能保证UI与数据保持一致。LiveData是观察者模式,与EventBus一样,一个地方注册observer,另一个地方去响应,调用setValue()方法通知页面更新。
    2. 与activity的生命周期同步,不会出现内存泄漏。LiveData的observer对象是与lifeCycle绑定的,当lifeCycle对象被onDestory的时候,observer对象也被clean up了
    3. 当activity处于stop activity状态时,不会崩溃。当observer处于inactive状态时,例如,activity被按了返回键,observer将不会响应来自LiveData的事件
    4. 不需要更多的手动管理生命周期。LiveData负责自动管理生命周期
    5. 保证数据是最新的。比如处于后台的activity,返回到前台是时,他会自动获取最新数据。
    6. 响应屏幕旋转等配置变化。
    7. 共享资源。新建一个专门的LiveData管理类,通过单例模式,在项目的任意位置都可以访问的到。

    官方介绍

    Dagger.Android

    依赖的库

        implementation 'com.google.dagger:dagger:2.17'
        implementation 'com.google.dagger:dagger-android:2.16'
        implementation 'com.google.dagger:dagger-android-support:2.16'
        annotationProcessor 'com.google.dagger:dagger-android-processor:2.16'
        annotationProcessor 'com.google.dagger:dagger-compiler:2.16'
    

    集成

    1. 集成到application中
    2. 集成到activity中
    3. 集成到fragment中

    Application

    新建Application
    package com.haichenyi.aloe.demo1.base;
    
    import android.app.Activity;
    import android.app.Application;
    import android.content.Context;
    import android.support.multidex.MultiDex;
    
    import com.haichenyi.aloe.demo1.di.component.DaggerAppComponent;
    import com.haichenyi.aloe.tools.LogUtils;
    import com.haichenyi.aloe.tools.ToastUtils;
    
    import javax.inject.Inject;
    
    import dagger.android.AndroidInjector;
    import dagger.android.DispatchingAndroidInjector;
    import dagger.android.HasActivityInjector;
    
    /**
     * @Title: BaseApp
     * @Des: Application
     * @Author: haichenyi
     * @Date: 2018/11/20 0020
     * @Email: haichenyi@yeah.net
     */
    public class BaseApp extends Application implements HasActivityInjector {
    
        @Inject
        DispatchingAndroidInjector<Activity> dispatchingActivityInjector;
    
        @Override
        public void onCreate() {
            super.onCreate();
            setInstance(this);
            DaggerAppComponent.create().inject(this);
        }
        
        @Override
        public AndroidInjector<Activity> activityInjector() {
            return dispatchingActivityInjector;
        }
    }
    
    

      实现HasActivityInjector接口,这部分可以直接复制过去就可以了

    新建AppComponent,AppModule
    @Singleton
    @Component(modules = {AndroidInjectionModule.class, AppModule.class})
    public interface AppComponent {
        void inject(BaseApp baseApp);
    }
    
    @Module
    public class AppModule {
    
    }
    

    这都没有什么要说的,看好注解就行了。

    Activity

    新建BaseActivity
    public class BaseActivity extends SupportActivity{
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            AndroidInjection.inject(this);
            super.onCreate(savedInstanceState);
        }
    }
    

      在super前面添加AndroidInjection.inject(this);

    新建ActComponent
    package com.haichenyi.aloe.demo1.di.component;
    
    import com.haichenyi.aloe.demo1.base.BaseActivity;
    
    import dagger.Subcomponent;
    import dagger.android.AndroidInjectionModule;
    import dagger.android.AndroidInjector;
    
    /**
     * @Title: ActComponent
     * @Des:
     * @Author: haichenyi
     * @Date: 2018/11/21 0021
     * @Email: haichenyi@yeah.net
     */
    @Subcomponent(modules = {AndroidInjectionModule.class})
    public interface ActComponent extends AndroidInjector<BaseActivity> {
        @Subcomponent.Builder
        abstract class Builder extends AndroidInjector.Builder<BaseActivity> {
    
        }
    }
    

      这里实现AndroidInjector<T>接口,这里的泛型传你的BaseActivity,然后添加抽象的Builder类

    新建AllActivitiesModule
    package com.haichenyi.aloe.demo1.di.module;
    
    import com.haichenyi.aloe.demo1.di.component.ActComponent;
    
    import dagger.Module;
    import dagger.android.ContributesAndroidInjector;
    
    /**
     * @Title: AllActivitiesModule
     * @Des:
     * @Author: haichenyi
     * @Date: 2018/11/21 0021
     * @Email: haichenyi@yeah.net
     */
    @Module(subcomponents = ActComponent.class)
    public abstract class AllActivitiesModule {
    
    }
    

      这里的module注解里面传你上面创建的ActivityComponent类

    重要的事情说三遍,不然报错都不知道为什么

    重要的事情说三遍,不然报错都不知道为什么

    重要的事情说三遍,不然报错都不知道为什么

      接下来,在你创建的AppComponent类里面,的注解@Component,添加AllActivitiesModule.class,如下:

    @Singleton
    @Component(modules = {AndroidInjectionModule.class, AppModule.class, AllActivitiesModule.class})
    public interface AppComponent {
        void inject(BaseApp baseApp);
    }
    

      然后,你新建Activity就直接继承你创建的BaseActivity,然后,在你上面创建的AllActivitiesModule里面添加如下代码即可:

    package com.haichenyi.aloe.demo1.di.module;
    
    import com.haichenyi.aloe.demo1.di.component.ActComponent;
    import com.haichenyi.aloe.demo1.ui.activity.FragmentActivity;
    import com.haichenyi.aloe.demo1.ui.activity.SwipeBackActivity;
    import com.haichenyi.aloe.demo1.ui.activity.WelcomeActivity;
    
    import dagger.Module;
    import dagger.android.ContributesAndroidInjector;
    
    /**
     * @Title: AllActivitiesModule
     * @Des:
     * @Author: haichenyi
     * @Date: 2018/11/21 0021
     * @Email: haichenyi@yeah.net
     */
    @Module(subcomponents = ActComponent.class)
    public abstract class AllActivitiesModule {
    
        @ContributesAndroidInjector
        abstract WelcomeActivity contributeWelcomeActivityInjector();
    
        @ContributesAndroidInjector
        abstract FragmentActivity contributeFragmentActivityInjector();
    
        @ContributesAndroidInjector
        abstract SwipeBackActivity contributeSwipeBackActivityInjector();
    
    }
    

      这里是我的demo里面创建的三个activity:WelcomeActivity,FragmentActivity,SwipeBackActivity,这样就可以用了。

    Fragment

    重要的事情说三遍,不然报错都不知道为什么

    重要的事情说三遍,不然报错都不知道为什么

    重要的事情说三遍,不然报错都不知道为什么

      官方文档上面介绍的是app包下面fragment的集成方式,实现的是HasFragmentInjector接口。

      我这里介绍的是v4包下面的fragment的集成方式,绝大多数情况下,我们用的都是v4包下面的fragment,实现的是HasSupportFragmentInjector接口。

      强调一遍,一个是HasSupportFragmentInjector,一个是HasFragmentInjector,带Support的是v4包下的,不带的是app包下的。

      进入正题,fragment依赖activity存在,我们这里,需要对包含fragment的activity做额外的操作。如下:

    新建fragment需要依赖的activity
    package com.haichenyi.aloe.demo1.ui.activity;
    
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentPagerAdapter;
    import android.support.v4.view.ViewPager;
    
    import com.haichenyi.aloe.demo1.R;
    import com.haichenyi.aloe.demo1.base.BaseActivity;
    import com.haichenyi.aloe.demo1.base.BaseFragment;
    import com.haichenyi.aloe.demo1.presenter.EmptyPresenter;
    import com.haichenyi.aloe.demo1.ui.frag.Fragment01;
    import com.haichenyi.aloe.demo1.ui.frag.Fragment02;
    import com.haichenyi.aloe.demo1.ui.frag.Fragment03;
    import com.haichenyi.aloe.demo1.ui.frag.Fragment04;
    import com.jaeger.library.StatusBarUtil;
    
    import java.util.ArrayList;
    
    import javax.inject.Inject;
    
    import dagger.android.AndroidInjector;
    import dagger.android.DispatchingAndroidInjector;
    import dagger.android.support.HasSupportFragmentInjector;
    
    /**
     * @Title: FragmentActivity
     * @Des:
     * @Author: haichenyi
     * @Date: 2018/11/29 0029
     * @Email: haichenyi@yeah.net
     */
    public class FragmentActivity extends BaseActivity<EmptyPresenter> implements HasSupportFragmentInjector {
        @Inject
        DispatchingAndroidInjector<Fragment> fragmentInjector;
    
        ArrayList<BaseFragment> list;
        ViewPager viewPager;
    
        @Override
        protected int layout(@Nullable Bundle savedInstanceState) {
            setAttachToolbar(false);
            setFullScreen(false);
            return R.layout.activity_fragment;
        }
    
        @Override
        protected void initView() {
            super.initView();
            viewPager = findViewById(R.id.viewPager);
        }
    
        @Override
        protected void initData() {
            super.initData();
            StatusBarUtil.setTranslucentForImageViewInFragment(this, null);
            StatusBarUtil.hideFakeStatusBarView(this);
    
            list = new ArrayList<>();
            list.add(new Fragment01());
            list.add(new Fragment02());
            list.add(new Fragment03());
            list.add(new Fragment04());
            viewPager.setOffscreenPageLimit(3);
            viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
                @Override
                public Fragment getItem(int position) {
                    return list.get(position);
                }
    
                @Override
                public int getCount() {
                    return list.size();
                }
            });
        }
    
        @Override
        public AndroidInjector<Fragment> supportFragmentInjector() {
            return fragmentInjector;
        }
    }
    

      如上,实现的是HasSupportFragmentInjector,然后实现supportFragmentInjector方法即可。

      记得,这里继承的是BaseActivity,要在前面创建的AllActivitiesModule中,把这个FragmentActivity添加进去。

    新建FragmentActivity,需要的Component
    package com.haichenyi.aloe.demo1.di.component;
    
    import com.haichenyi.aloe.demo1.ui.activity.FragmentActivity;
    
    import dagger.Subcomponent;
    import dagger.android.AndroidInjectionModule;
    import dagger.android.AndroidInjector;
    
    /**
     * @Title: FragActivityComponent
     * @Des:
     * @Author: haichenyi
     * @Date: 2018/11/29 0029
     * @Email: haichenyi@yeah.net
     */
    @Subcomponent(modules = {AndroidInjectionModule.class})
    public interface FragActivityComponent extends AndroidInjector<FragmentActivity> {
        @Subcomponent.Builder
        abstract class Builder extends AndroidInjector.Builder<FragmentActivity> {
    
        }
    }
    

      这里的泛型传你上面创建的FragmentActivity

    新建FragmentActivity,需要的Module
    package com.haichenyi.aloe.demo1.di.module;
    
    import android.app.Activity;
    
    import com.haichenyi.aloe.demo1.di.component.FragActivityComponent;
    import com.haichenyi.aloe.demo1.ui.activity.FragmentActivity;
    
    import dagger.Binds;
    import dagger.Module;
    import dagger.android.ActivityKey;
    import dagger.android.AndroidInjector;
    import dagger.multibindings.IntoMap;
    
    /**
     * @Title: FragActivityModule
     * @Des:
     * @Author: haichenyi
     * @Date: 2018/11/29 0029
     * @Email: haichenyi@yeah.net
     */
    @Module(subcomponents = FragActivityComponent.class)
    public abstract class FragActivityModule {
    
        @Binds
        @IntoMap
        @ActivityKey(FragmentActivity.class)
        abstract AndroidInjector.Factory<? extends Activity> bindDaggerFragmentActivityInjectorFactory(FragActivityComponent.Builder builder);
    
    }
    
    新建BaseFragment
    public class BaseFragment extends Fragment{
    
        @Override
        public void onAttach(Context context) {
            AndroidSupportInjection.inject(this);
            super.onAttach(context);
        }
    
    }
    

      在super前面添加AndroidSupportInjection.inject(this);

    新建BaseFragment需要的Component
    package com.haichenyi.aloe.demo1.di.component;
    
    import com.haichenyi.aloe.demo1.base.BaseFragment;
    
    import dagger.Subcomponent;
    import dagger.android.AndroidInjectionModule;
    import dagger.android.AndroidInjector;
    
    /**
     * @Title: BaseFragComponent
     * @Des:
     * @Author: haichenyi
     * @Date: 2018/11/21 0021
     * @Email: haichenyi@yeah.net
     */
    @Subcomponent(modules = {AndroidInjectionModule.class})
    public interface BaseFragComponent extends AndroidInjector<BaseFragment>{
        @Subcomponent.Builder
        public abstract class Builder extends AndroidInjector.Builder<BaseFragment>{
    
        }
    }
    
    新建BaseFragment需要的Module
    package com.haichenyi.aloe.demo1.di.module;
    
    import com.haichenyi.aloe.demo1.di.component.BaseFragComponent;
    import com.haichenyi.aloe.demo1.ui.frag.Fragment01;
    import com.haichenyi.aloe.demo1.ui.frag.Fragment02;
    import com.haichenyi.aloe.demo1.ui.frag.Fragment03;
    import com.haichenyi.aloe.demo1.ui.frag.Fragment04;
    
    import dagger.Module;
    import dagger.android.ContributesAndroidInjector;
    
    /**
     * @Title: AllFragmentModule
     * @Des:
     * @Author: haichenyi
     * @Date: 2018/11/29 0029
     * @Email: haichenyi@yeah.net
     */
    @Module(subcomponents = BaseFragComponent.class)
    public abstract class AllFragmentModule {
    
        @ContributesAndroidInjector
        abstract Fragment01 contributeFragment01Injector();
    
        @ContributesAndroidInjector
        abstract Fragment02 contributeFragment02Injector();
    
        @ContributesAndroidInjector
        abstract Fragment03 contributeFragment03Injector();
    
        @ContributesAndroidInjector
        abstract Fragment04 contributeFragment04Injector();
    }
    
    

      跟activity一样,把继承BaseFragment的fragment,都添加到这里来

      然后就是把这个AllFragmentModule添加到AppComponent的@Component注解上就可以了。

    至此

    至此

    至此

      到这里,这个dagger.android就添加依赖完了,后面我们新建activity,直接继承BaseActivity就可以直接用了。新建fragment,直接继承BaseFragment就可以直接用了

    LiveData

    依赖的库

    现在项目创建完,都是自带的。lifecycle,不需要额外添加依赖库
    

    用法

      很简单,观察者模式,类似于EventBus的用法。一个地方注册,一个地方触发。

    MutableLiveData<String> liveData1 = new MutableLiveData<>();
    liveData1.observe(this, new Observer<String>() {
                @Override
                public void onChanged(@Nullable String s) {
                    Log.v("wz",s);
                }
            });
    liveData1.setValue("123");
    

      简单的来说,就像上面这样,新建一个LiveData对象,注册一个observer,然后,setValue去触发这个onChange方法。

      LiveData提供了两个方法触发onChange方法,一个是setValue:在当前线程触发回调;另一个postValue:在主线程触发回调。

      前面我们说过共享资源,LiveData是全局的,我们可以新建一个管理类,我这里给出来了。通过map简单的封装了一下添加,移除的方法(通过键,或者通过类名称移除当前类的所有观察者),项目里面有,有点长,就不贴出来了,我贴出来方法

      在我的BaseActivity或者BaseFragment,添加如下方法:

    /**
         * 设置LiveData的Observer(需要通过类名称手动移除Observer)
         *
         * @param aClass   当前类对象
         * @param key      键
         * @param observer 监听器
         * @param <T>      数据类型
         */
        protected synchronized <T> void setObserver(final Class aClass, final String key, final Observer<T> observer) {
            BaseLiveData<T> liveData = new BaseLiveData<>();
            liveData.observe(this, observer);
            LiveDataManager.getInstance().putLiveData(aClass, key, liveData);
        }
    
        /**
         * 设置LiveData的Observer(不需要通过类名称手动移除Observer)
         *
         * @param key      键
         * @param observer 监听器
         * @param <T>      数据类型
         */
        protected synchronized <T> void setObserver(final String key, final Observer<T> observer) {
            BaseLiveData<T> liveData = new BaseLiveData<>();
            liveData.observe(this, observer);
            LiveDataManager.getInstance().putLiveData(key, liveData);
        }
    

      在子类里面调用:

    @Override
        protected void initData() {
            super.initData();
            this.<String>setObserver("internet", ToastUtils::showTipMsg);
            this.<String>setObserver("internet2", ToastUtils::showTipMsg);
        }
    

      在P层里面去触发回调:

    package com.haichenyi.aloe.demo1.presenter;
    
    import com.haichenyi.aloe.demo1.base.BasePresenter;
    import com.haichenyi.aloe.demo1.base.BaseView;
    import com.haichenyi.aloe.demo1.impl.LiveDataManager;
    
    import javax.inject.Inject;
    
    /**
     * @Title: WelcomePresenter
     * @Des:
     * @Author: haichenyi
     * @Date: 2018/11/21 0021
     * @Email: haichenyi@yeah.net
     */
    public class WelcomePresenter extends BasePresenter<BaseView> {
    
        @Inject
        public WelcomePresenter() {
            //Dagger2 generate object.
        }
    
        public void getData() {
            LiveDataManager.getInstance().getLiveData("internet").callbackUI("123");
        }
    
        public void getData2() {
            LiveDataManager.getInstance().getLiveData("internet2").callbackUI("321");
        }
    }
    
    

      如上所示,我们的P层代码与之前的框架相比,简洁了很多。

    项目链接

    相关文章

      网友评论

        本文标题:Android项目框架之MVP+Dagger.Android+L

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