个人博客:haichenyi.com。感谢关注
之前的那个系列从零开始搭建一个主流的项目框架(一 ~ 八),尽管把dagger2中inject activity 优化了一下,但是依然显得繁琐,每一个activity里面都要写一个inject方法。Dagger.Android只用在基类里面inject一次,子类里不用管,直接用。
还有就是之前的MVP架构,每次更新页面的时候都要在每个页面对应的Contract——View里面写方法,在P层去实现然后在Activity里面也要实现一遍,这样太繁琐,现在用上LiveData,解决了这个问题,并且LiveData的优点:
- 能保证UI与数据保持一致。LiveData是观察者模式,与EventBus一样,一个地方注册observer,另一个地方去响应,调用setValue()方法通知页面更新。
- 与activity的生命周期同步,不会出现内存泄漏。LiveData的observer对象是与lifeCycle绑定的,当lifeCycle对象被onDestory的时候,observer对象也被clean up了
- 当activity处于stop activity状态时,不会崩溃。当observer处于inactive状态时,例如,activity被按了返回键,observer将不会响应来自LiveData的事件
- 不需要更多的手动管理生命周期。LiveData负责自动管理生命周期
- 保证数据是最新的。比如处于后台的activity,返回到前台是时,他会自动获取最新数据。
- 响应屏幕旋转等配置变化。
- 共享资源。新建一个专门的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'
集成
- 集成到application中
- 集成到activity中
- 集成到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层代码与之前的框架相比,简洁了很多。
网友评论