個人博客:haichenyi.com。感謝關(guān)注
??之前的那個系列從零開始搭建一個主流的項目框架(一?~?八),盡管把dagger2中inject activity 優(yōu)化了一下,但是依然顯得繁瑣,每一個activity里面都要寫一個inject方法。Dagger.Android只用在基類里面inject一次,子類里不用管,直接用。
??還有就是之前的MVP架構(gòu),每次更新頁面的時候都要在每個頁面對應(yīng)的Contract——View里面寫方法,在P層去實現(xiàn)然后在Activity里面也要實現(xiàn)一遍,這樣太繁瑣,現(xiàn)在用上LiveData,解決了這個問題,并且LiveData的優(yōu)點:
- 能保證UI與數(shù)據(jù)保持一致。LiveData是觀察者模式,與EventBus一樣,一個地方注冊observer,另一個地方去響應(yīng),調(diào)用setValue()方法通知頁面更新。
- 與activity的生命周期同步,不會出現(xiàn)內(nèi)存泄漏。LiveData的observer對象是與lifeCycle綁定的,當(dāng)lifeCycle對象被onDestory的時候,observer對象也被clean up了
- 當(dāng)activity處于stop activity狀態(tài)時,不會崩潰。當(dāng)observer處于inactive狀態(tài)時,例如,activity被按了返回鍵,observer將不會響應(yīng)來自LiveData的事件
- 不需要更多的手動管理生命周期。LiveData負(fù)責(zé)自動管理生命周期
- 保證數(shù)據(jù)是最新的。比如處于后臺的activity,返回到前臺是時,他會自動獲取最新數(shù)據(jù)。
- 響應(yīng)屏幕旋轉(zhuǎn)等配置變化。
- 共享資源。新建一個專門的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;
}
}
??實現(xiàn)HasActivityInjector接口,這部分可以直接復(fù)制過去就可以了
新建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> {
}
}
??這里實現(xiàn)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注解里面?zhèn)髂闵厦鎰?chuàng)建的ActivityComponent類
重要的事情說三遍,不然報錯都不知道為什么
重要的事情說三遍,不然報錯都不知道為什么
重要的事情說三遍,不然報錯都不知道為什么
??接下來,在你創(chuàng)建的AppComponent類里面,的注解@Component,添加AllActivitiesModule.class,如下:
@Singleton
@Component(modules = {AndroidInjectionModule.class, AppModule.class, AllActivitiesModule.class})
public interface AppComponent {
void inject(BaseApp baseApp);
}
??然后,你新建Activity就直接繼承你創(chuàng)建的BaseActivity,然后,在你上面創(chuàng)建的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里面創(chuàng)建的三個activity:WelcomeActivity,F(xiàn)ragmentActivity,SwipeBackActivity,這樣就可以用了。
Fragment
重要的事情說三遍,不然報錯都不知道為什么
重要的事情說三遍,不然報錯都不知道為什么
重要的事情說三遍,不然報錯都不知道為什么
??官方文檔上面介紹的是app包下面fragment的集成方式,實現(xiàn)的是HasFragmentInjector接口。
??我這里介紹的是v4包下面的fragment的集成方式,絕大多數(shù)情況下,我們用的都是v4包下面的fragment,實現(xiàn)的是HasSupportFragmentInjector接口。
??強調(diào)一遍,一個是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;
}
}
??如上,實現(xiàn)的是HasSupportFragmentInjector,然后實現(xiàn)supportFragmentInjector方法即可。
??記得,這里繼承的是BaseActivity,要在前面創(chuàng)建的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> {
}
}
??這里的泛型傳你上面創(chuàng)建的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
依賴的庫
現(xiàn)在項目創(chuàng)建完,都是自帶的。lifecycle,不需要額外添加依賴庫
用法
??很簡單,觀察者模式,類似于EventBus的用法。一個地方注冊,一個地方觸發(fā)。
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去觸發(fā)這個onChange方法。
??LiveData提供了兩個方法觸發(fā)onChange方法,一個是setValue:在當(dāng)前線程觸發(fā)回調(diào);另一個postValue:在主線程觸發(fā)回調(diào)。
??前面我們說過共享資源,LiveData是全局的,我們可以新建一個管理類,我這里給出來了。通過map簡單的封裝了一下添加,移除的方法(通過鍵,或者通過類名稱移除當(dāng)前類的所有觀察者),項目里面有,有點長,就不貼出來了,我貼出來方法
??在我的BaseActivity或者BaseFragment,添加如下方法:
/**
* 設(shè)置LiveData的Observer(需要通過類名稱手動移除Observer)
*
* @param aClass 當(dāng)前類對象
* @param key 鍵
* @param observer 監(jiān)聽器
* @param <T> 數(shù)據(jù)類型
*/
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);
}
/**
* 設(shè)置LiveData的Observer(不需要通過類名稱手動移除Observer)
*
* @param key 鍵
* @param observer 監(jiān)聽器
* @param <T> 數(shù)據(jù)類型
*/
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);
}
??在子類里面調(diào)用:
@Override
protected void initData() {
super.initData();
this.<String>setObserver("internet", ToastUtils::showTipMsg);
this.<String>setObserver("internet2", ToastUtils::showTipMsg);
}
??在P層里面去觸發(fā)回調(diào):
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層代碼與之前的框架相比,簡潔了很多。