MVPArms是一個整合了大量主流開源項目的Android Mvp快速搭建框架,其中包含Dagger2
Retrofit
,Rxjava
以及Rxbinding
,RxCache
等Rx
系三方庫,而且提供UI
自適應方案,本框架將它們結合起來,並所有使用Dagger2
管理並提供給開發者使用,使用本框架開發你的項目就意味着你已經擁有一個MVP+Dagger2+Retrofit+Rxjava項目,發佈到github
上能夠很是輕鬆的拿star(在簡歷中展露頭腳),我提供一切迭代和維護成本你只須要在Readme裏面註明框架出處,還不趕快行動?前端
Dagger2
管理(將全部模塊使用Dagger
鏈接起來,毫不是簡單的使用)Rxjava
UI
自適應http
Request(請求參數,headers) Response(服務器返回的結果,headers,耗時)信息監聽,可解析json後根據狀態碼作相應的全局操做Rxjava
錯誤處理,錯誤後自動重試,捕捉整個應用的全部錯誤Android
開發能力Dagger2
,Rxjava
,Retrofit
的經驗,沒使用過也必須瞭解,否則很難使用Mvp
Google官方出品的Mvp
架構項目,含有多個不一樣的架構分支(此爲Dagger分支).Dagger2
Google根據Square的Dagger1出品的依賴注入框架,經過apt動態生成代碼,性能優於用反射技術依賴注入的框架.Rxjava
提供優雅的響應式Api解決異步請求.RxAndroid
爲Android提供響應式Api.Rxlifecycle
在Android上使用rxjava都知道的一個坑,就是生命週期的解除訂閱,這個框架經過綁定activity和fragment的生命週期完美解決.Rxbinding
JakeWharton大神的View綁定框架,優雅的處理View的響應事件.RxCache
是使用註解爲Retrofit加入二級緩存(內存,磁盤)的緩存庫Retrofit
Square出品的網絡請求庫,極大的減小了http請求的代碼和步驟.Okhttp
一樣Square出品,很少介紹,作Android都應該知道.Autolayout
鴻洋大神的Android全尺寸適配框架.Gson
Google官方的Json Convert框架.Butterknife
JakeWharton大神出品的view注入框架.Androideventbus
一個輕量級使用註解的Eventbus.Timber
JakeWharton大神出品Log框架,內部代碼極少,可是思想很是不錯.Glide
此庫爲本框架默認封裝圖片加載庫,可參照着例子更改成其餘的庫,Api和Picasso
差很少,緩存機制比Picasso
複雜,速度快,適合處理大型圖片流,支持gfit,Fresco
太大了!,在5.0一下優點很大,5.0以上系統默認使用的內存管理和Fresco
相似.Realm
速度和跨平臺性使它成爲現在最火的數據庫,美中不足的就是so庫太大LeakCanary
Square出品的專門用來檢測Android
和Java
的內存泄漏,經過通知欄提示內存泄漏信息RxErroHandler
Rxjava
錯誤處理庫,可在出現錯誤後重試
此框架適合本身作定製修改,全部暫時不上傳至
Jcenter
或Maven
,請自行下載或clonejava
compile project(':arms')
本框架提供一個引用大量第三方庫的config.gradle文件,用於第三方庫版本管理,將config.gradle複製進根目錄,並在項目的頂級build.gradle中引用它android
// Top-level build file where you can add configuration options common to all sub-projects/modules. apply from: "config.gradle" //這裏表示引用config.gradle文件 buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.1.2' the individual module build.gradle files } } allprojects { repositories { jcenter() maven { url "https://jitpack.io" }//這裏要使用rxcahche指定的倉庫 } } task clean(type: Delete) { delete rootProject.buildDir }
由於在頂級build.gradle中引用了它,因此在整個項目的全部build.gradle中均可以使用rootProject.xxx來使用它裏面的內容git
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile rootProject.ext.dependencies["junit"] compile rootProject.ext.dependencies["support-v4"] compile rootProject.ext.dependencies["gson"] compile rootProject.ext.dependencies["appcompat-v7"] compile rootProject.ext.dependencies["cardview-v7"] compile rootProject.ext.dependencies["autolayout"] compile rootProject.ext.dependencies["butterknife"] compile rootProject.ext.dependencies["androideventbus"] }
也可使用它來管理一些項目的信息,這樣有多個module也能夠直接使用一個信息github
android { compileSdkVersion rootProject.ext.android["compileSdkVersion"] buildToolsVersion rootProject.ext.android["buildToolsVersion"] useLibrary 'org.apache.http.legacy' defaultConfig { minSdkVersion rootProject.ext.android["minSdkVersion"] targetSdkVersion rootProject.ext.android["targetSdkVersion"] versionCode rootProject.ext.android["versionCode"] versionName rootProject.ext.android["versionName"] } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
本框架所有使用Dagger2管理,因此必須依賴Dagger2,找到app的build.gradle,加入以下代碼數據庫
apply plugin: 'com.android.application' apply plugin: 'com.neenbedankt.android-apt'//使用apt插件 buildscript { repositories { jcenter() mavenCentral() } dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'//使用apt } } dependencies { apt rootProject.ext.dependencies["dagger2-apt-compiler"]//依賴apt插件 provided rootProject.ext.dependencies["javax.annotation"]//dagger2必須依賴jsr250 annotation }
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
使用Autolayout 自適應框架必須配置Meta屬性及設計圖的寬高,詳情參考Autolayoutapache
//將設計圖的寬高配置後,配合AutoLauout控件使用,在設計圖尺寸之外的其它尺寸手機上,也能達到和設計圖同樣的顯示效果 <meta-data android:name="design_width" android:value="1080"/> <meta-data android:name="design_height" android:value="1920"/>
本框架默認使用
Glide
加載圖片,但提供一個管理器ImageLoader
提供統一接口,使用策略者模式可輕鬆替換圖片加載框架,本框架默認提供Glide
的自定義緩存配置信息,使用它以前先引用它的自定義配置信息json
<!--glide配置--> <meta-data android:name="com.jess.arms.widget.imageloader.glide.GlideConfiguration" android:value="GlideModule"/>
因爲本框架依賴大量三方庫,因此已經在arms Module
下的proguard-rules.pro中提供了全部規則,若是想使用它,請複製它替換app Module
中的proguard-rules.pro,混淆時能夠根據本身的需求修改或添加規則,混淆前務必注意將Java Bean,自定義組件添加進規則緩存
! 必定不能修改common包的包名,舊版本須要找到和common包下同名的類並刪除,而後從新引用common包裏的類
服務器
若是你得到本框架的方式是經過clone或者下載:
git pull origin master
拉取最新的版本並自動合併git rm --cache -r app/src/main/java/me/jessyan/mvparms
,下次拉取時就不會拉取Demo的內容若是你得到本框架的方式是經過fork到本身倉庫後,clone或下載:
git remote add arms https://github.com/JessYanCoding/MVPArms.git
添加遠程倉庫,arms是遠程倉庫的代號,可自定義,之後都經過這個代號對遠程倉庫做操做git fetch arms
拉取遠程倉庫最新的版本git merge arms/master --allow-unrelated-histories
合併遠程倉庫到當前分支--allow-unrelated-histories
只用在第一次合併時添加git rm --cache -r app/src/main/java/me/jessyan/mvparms
,下次拉取時就不會拉取Demo的內容
新建項目的Application繼承自
BaseApplication
,並在AndroidManifest中聲明
//BaseApplication爲抽象類,必須實現getGlobeConfigModule,這裏返回整個應用須要的配置信息(將app的全局配置信息封裝進module,使用Dagger注入到須要配置信息的地方) @Override protected GlobeConfigModule getGlobeConfigModule() { return GlobeConfigModule .buidler() .baseurl(Api.APP_DOMAIN)//必須提供baseurl .build(); }
Application生命週期是和App是同樣的,因此是適合提供一些單例對象,本框架使用
Dagger2
管理,因此使用AppComponent來提供全局全部的單例對象
@Singleton @Component(modules = {AppModule.class, ClientModule.class, ServiceModule.class, ImageModule.class, CacheModule.class, GlobeConfigModule.class}) public interface AppComponent { Application Application(); //服務管理器,retrofitApi ServiceManager serviceManager(); //緩存管理器 CacheManager cacheManager(); //Rxjava錯誤處理管理類 RxErrorHandler rxErrorHandler(); OkHttpClient okHttpClient(); //圖片管理器,用於加載圖片的管理類,默認使用glide,使用策略模式,可替換框架 ImageLoader imageLoader(); //gson Gson gson(); //用於管理全部activity AppManager appManager(); }
@Override public void onCreate() { super.onCreate(); mAppComponent = DaggerAppComponent .builder() .appModule(getAppModule())//baseApplication提供 .clientModule(getClientModule())//baseApplication提供 .globeConfigModule(getGlobeConfigModule())//全局配置 .imageModule(getImageModule())//baseApplication提供 .serviceModule(new ServiceModule())//需自行建立 .cacheModule(new CacheModule())//需自行建立 .build(); } //將AppComponent返回出去,供其它地方使用, AppComponent接口中聲明的方法返回的實例, 在getAppComponent()拿到對象後均可以直接使用 public AppComponent getAppComponent() { return mAppComponent; }
Retrofit
Api)和CacheModule(提供緩存)都需自行建立,詳情ServiceModule(2.1.2) ,CacheModule(2.1.3)
ServiceModule提供RetrofitApi對應的Service,這些Service對象在AppComponent中注入ServiceManager(需繼承BaseServiceManager)中統一管理
public interface CommonService { String HEADER_API_VERSION = "Accept: application/vnd.github.v3+json"; @Headers({HEADER_API_VERSION}) @GET("/users") Observable<List<User>> getUsers(@Query("since") int lastIdQueried, @Query("per_page") int perPage); }
@Module public class ServiceModule { @Singleton @Provides CommonService provideCommonService(Retrofit retrofit) { return retrofit.create(CommonService.class); } }
@Singleton public class ServiceManager implements BaseServiceManager { private CommonService mCommonService; //若是須要添加service只需在構造方法中添加對應的service, 在提供get方法返回出去,只要在ServiceModule提供了該service Dagger2會自行注入 @Inject public ServiceManager(CommonService commonService){ this.mCommonService = commonService; } public CommonService getCommonService() { return mCommonService; } }
Cache層默認使用
RxCache
,CacheModule提供RetrofitApi對應的Cache對象,這些Cache對象在AppComponent中注入CacheManager(需繼承BaseCacheManager)中統一管理
public interface CommonCache { @LifeCache(duration = 2, timeUnit = TimeUnit.MINUTES) Observable<Reply<List<User>>> getUsers(Observable<List<User>> oUsers, DynamicKey idLastUserQueried, EvictProvider evictProvider); }
@Module public class CacheModule { @Singleton @Provides CommonCache provideCommonService(RxCache rxCache) { return rxCache.using(CommonCache.class); } }
@Singleton public class CacheManager implements BaseCacheManager{ private CommonCache mCommonCache; //若是須要添加Cache只需在構造方法中添加對應的Cache, 在提供get方法返回出去,只要在CacheModule提供了該Cache Dagger2會自行注入 @Inject public CacheManager(CommonCache commonCache) { this.mCommonCache = commonCache; } public CommonCache getCommonCache() { return mCommonCache; } }
讓項目的基類Activity繼承BaseActivity,BaseActivity默認注入Presenter,因此若是要使用Presenter必須指定對應的範型,而且提供注入Presenter所須要的Component
public abstract class WEActivity<P extends BasePresenter> extends BaseActivity<P> { protected WEApplication mWeApplication; @Override protected void ComponentInject() { mWeApplication = (WEApplication) getApplication(); setupActivityComponent(mWeApplication.getAppComponent()); } //提供AppComponent(提供全部的單例對象)給子類,進行Component依賴 protected abstract void setupActivityComponent(AppComponent appComponent); }
讓項目的基類Fragment繼承BaseFragment,BaseFragment默認注入Presenter,因此若是要使用Presenter必須指定對應的範型,而且提供注入Presenter所須要的Component
public abstract class WEFragment<P extends BasePresenter> extends BaseFragment<P> { protected WEApplication mWeApplication; @Override protected void ComponentInject() { mWeApplication = (WEApplication)mActivity.getApplication(); setupFragmentComponent(mWeApplication.getAppComponent()); } //提供AppComponent(提供全部的單例對象)給子類,進行Component依賴 protected abstract void setupFragmentComponent(AppComponent appComponent); }
定義業務邏輯MVP,繼承MVP各自的基類便可,這裏能夠稍微粗力度的定義MVP類,即無需每一個Fragment和Activity(每一個頁面)都定義不一樣的MVP類,能夠按照相同的業務邏輯使用一組MVP類
這裏根據
public interface UserContract { //對於常用的關於UI的方法能夠定義到BaseView中,如顯示隱藏進度條,和顯示文字消息 interface View extends BaseView { void setAdapter(DefaultAdapter adapter); void startLoadMore(); void endLoadMore(); } //Model層定義接口,外部只需關心model返回的數據,無需關心內部細節,及是否使用緩存 interface Model extends IModel{ Observable<List<User>> getUsers(int lastIdQueried, boolean update); } }
通常讓Activity或Fragment實現Contract中定義的View接口,供Presenter調用對應方法操做UI,BaseActivity默認注入Presenter,如想使用Presenter,必須指定Presenter的範型,和實現setupActivityComponent來提供Presenter須要的Component和Module
public class UserActivity extends WEActivity<UserPresenter> implements UserContract.View { @Override protected void setupActivityComponent(AppComponent appComponent) { DaggerUserComponent .builder() .appComponent(appComponent) .userModule(new UserModule(this)) .build() .inject(this); } @Override protected View initView() { return LayoutInflater.from(this).inflate(R.layout.activity_user, null, false); } @Override protected void initData() { } }
Model實現Contract的Model接口,而且繼承BaseModel,指定範型爲,上面定義的ServiceManager和CacheManager,而後經過兩個Manager拿到須要的Service和Cache爲Presenter提供須要的數據(是否使用緩存請自行選擇)
@ActivityScope public class UserModel extends BaseModel<ServiceManager,CacheManager> implements UserContract.Model{ private CommonService mCommonService; private CommonCache mCommonCache; @Inject public UserModel(ServiceManager serviceManager, CacheManager cacheManager) { super(serviceManager, cacheManager); this.mCommonService = mServiceManager.getCommonService(); this.mCommonCache = mCacheManager.getCommonCache(); } @Override public Observable<List<User>> getUsers(int lastIdQueried, boolean update) { } }
Presenter在MVP中的大部分的做用爲經過從Model層接口獲取數據,在調用View層接口顯示數據,首先實現BasePresenter,指定Model和View的範型,注意必定要指定Contract中定義的接口,Presenter須要的Model和View,都使用Dagger2注入,這樣即解藕又方便測試,怎麼注入?
@ActivityScope public class UserPresenter extends BasePresenter<UserContract.Model, UserContract.View> { @Inject public UserPresenter(UserContract.Model model, UserContract.View rootView) { super(model, rootView); } //這裏定義業務方法,相應用戶的交互 public void requestUsers(final boolean pullToRefresh) { } }
這裏的Module提供當前業務邏輯對應的View和Model接口(Contract中定義的接口)的實現類,Model須要AppComponent中提供的ServiceManager和CacheManager來實現網絡請求和緩存,因此須要經過Component依賴AppComponent拿到這兩個Manager
@Module public class UserModule { private UserContract.View view; //構建UserModule時,將View的實現類傳進來,這樣就能夠提供View的實現類給presenter public UserModule(UserContract.View view) { this.view = view; } @ActivityScope @Provides UserContract.View provideUserView(){ return this.view; } @ActivityScope @Provides UserContract.Model provideUserModel(UserModel model){ return model; } }
這裏須要注意的是此Component必須依賴AppComponent,這樣才能提供Model須要的ServiceManager和CacheManager,提供inject()方法就能將Module及AppComponent中提供的對象注入到對應的類中,inject()中的參數不能是接口,怎麼注入?
@ActivityScope @Component(modules = UserModule.class,dependencies = AppComponent.class) public interface UserComponent { void inject(UserActivity activity); }
在上面的代碼中ActivityScope大量出如今Module和Component中,Dagger2使用Scope限制每一個Module中提供的對象的生命,Dagger2默認只提供一個
@Singleton
Scope即單例,本框架提供@ActvityScope和@FragmentScope,若有其餘需求請自行實現,Module和Component定義相同的Scope後Module中提供的對象的生命週期會和Component中同樣(即在Component生命週期內,如需使用到Moudle中提供的對象,只會調用一次@Provide註解的方法獲得此對象)
GlobeConfigModule使用建造者模式將App的全局配置信息封裝進Module(使用Dagger注入到須要配置信息的地方),能夠配置CacheFile,InterCeptor等,由於使用的是建造者模式因此如你有其餘配置信息須要使用
Dagger
注入,直接就能夠添加進Builder而且不會影響到其餘地方
//如需添加個Boolean字段提供給Log工具類,來判斷是否打印Log @Module public class GlobeConfigModule { private Boolean isLog; private GlobeConfigModule(Buidler buidler) { this.isLog = builder.isLog } public static Buidler buidler() { return new Buidler(); } public static final class Buidler { private Boolean isLog; private Buidler() {} //1.給Builder中添加個方法接受isLog字段 public Buidler isLog(Boolean isLog) { this.isLog = isLog; return this; } public GlobeConfigModule build() { return new GlobeConfigModule(this); } } //2.使用@Provides,將isLog返回出去,供Dagger注入到Log工具類 @Singleton @Provides Boolean provideIsLog() { return isLog; } }
經過GlobeConfigModule.globeHttpHandler()方法傳入GlobeHttpHandler
@Override protected GlobeConfigModule getGlobeConfigModule() { return GlobeConfigModule .buidler() .baseurl(Api.APP_DOMAIN) .globeHttpHandler(new GlobeHttpHandler() {// 這裏能夠提供一個全局處理http響應結果的處理類, // 這裏能夠比客戶端提早一步拿到服務器返回的結果,能夠作一些操做,好比token超時,從新獲取 @Override public Response onHttpResultResponse(String httpResult, Interceptor.Chain chain, Response response) { //這裏能夠先客戶端一步拿到每一次http請求的結果,能夠解析成json,作一些操做,如檢測到token過時後 //從新請求token,並從新執行請求 try { if (!TextUtils.isEmpty(httpResult)) { JSONArray array = new JSONArray(httpResult); JSONObject object = (JSONObject) array.get(0); String login = object.getString("login"); String avatar_url = object.getString("avatar_url"); Timber.tag(TAG).w("result ------>" + login + " || avatar_url------>" + avatar_url); } } catch (JSONException e) { e.printStackTrace(); return response; } //這裏若是發現token過時,能夠先請求最新的token,而後在拿新的token放入request裏去從新請求 //注意在這個回調以前已經調用過proceed,因此這裏必須本身去創建網絡請求,如使用okhttp使用新的request去請求 // create a new request and modify it accordingly using the new token // Request newRequest = chain.request().newBuilder().header("token", newToken) // .build(); // // retry the request // // response.body().close(); //若是使用okhttp將新的請求,請求成功後,將返回的response return出去便可 //若是不須要返回新的結果,則直接把response參數返回出去 return response; } // 這裏能夠在請求服務器以前能夠拿到request,作一些操做好比給request統一添加token或者header @Override public Request onHttpRequestBefore(Interceptor.Chain chain, Request request) { //若是須要再請求服務器以前作一些操做,則從新返回一個作過操做的的requeat如增長header,不作操做則返回request //return chain.request().newBuilder().header("token", tokenId) // .build(); return request; } }) .build(); }
若是須要使用Rxjava的全局錯誤處理,需經過GlobeConfigModule.responseErroListener()方法傳入ResponseErroListener,並在每次使用Rxjava調用subscribe時,使用ErrorHandleSubscriber,並傳入AppComponent中提供的RxErrorHandler,此Subscribe,默認已經實現OnError方法,如想自定義能夠重寫OnError方法
@Override protected GlobeConfigModule getGlobeConfigModule() { return GlobeConfigModule .buidler() .baseurl(Api.APP_DOMAIN) .responseErroListener(new ResponseErroListener() { // 用來提供處理全部錯誤的監聽 // rxjava必要要使用ErrorHandleSubscriber(默認實現Subscriber的onError方法),此監聽才生效 @Override public void handleResponseError(Context context, Exception e) { Timber.tag(TAG).w("------------>" + e.getMessage()); UiUtils.SnackbarText("net error"); } }).build(); }
Observable .just(1) .retryWhen(new RetryWithDelay(3,2))//遇到錯誤時重試,第一個參數爲重試幾回,第二個參數爲重試的間隔 .subscribe(new ErrorHandleSubscriber<Integer>(mErrorHandler) { @Override public void onNext(Integer Integer) { } });
本框架默認使用
Glide
實現圖片加載功能,使用ImagerLoader提供統一的接口,ImagerLoader使用策略模式和建造者模式,能夠動態切換圖片框架(好比說切換成Picasso
),而且加載圖片時傳入的參數也能夠隨意擴展(loadImage方法在須要擴展參數時,也不須要改動,所有經過Builder擴展,好比你想讓內部的圖片加載框架,清除緩存你只須要定義個boolean字段,內部根據這個字段if|else,其餘操做同理)
public class PicassoImageLoaderStrategy implements BaseImageLoaderStrategy<PicassoImageConfig> { @Override public void loadImage(Context ctx, PicassoImageConfig config) { Picasso.with(ctx) .load(config.getUrl()) .into(config.getImageView()); } }
public class PicassoImageConfig extends ImageConfig{ private PicassoImageConfig(Buidler builder) { this.url = builder.url; this.imageView = builder.imageView; this.placeholder = builder.placeholder; this.errorPic = builder.errorPic; } public static Buidler builder() { return new Buidler(); } public static final class Buidler { private String url; private ImageView imageView; private int placeholder; protected int errorPic; private Buidler() { } public Buidler url(String url) { this.url = url; return this; } public Buidler placeholder(int placeholder) { this.placeholder = placeholder; return this; } public Buidler errorPic(int errorPic){ this.errorPic = errorPic; return this; } public Buidler imagerView(ImageView imageView) { this.imageView = imageView; return this; } public PicassoImageConfig build() { if (url == null) throw new IllegalStateException("url is required"); if (imageView == null) throw new IllegalStateException("imageview is required"); return new PicassoImageConfig(this); } } }
Glide
)方法一 在ImageModule中返回PicassoImageLoaderStrategy @Module public class ImageModule { @Singleton @Provides public BaseImageLoaderStrategy provideImageLoaderStrategy() { return new PicassoImageLoaderStrategy(); } @Singleton @Provides public ImageLoader provideImageLoader(BaseImageLoaderStrategy strategy) { return new ImageLoader(strategy); } } 方法2 拿到AppComponent中的 ImagerLoader mApplication .getAppComponent() .imageLoader() .setLoadImgStrategy(new PicassoImageLoaderStrategy()); 使用方法 mApplication .getAppComponent() .imageLoader() .loadImage(mApplication, GlideImageConfig .builder() .url(data.getAvatarUrl()) .imagerView(mAvater) .build());
本框架使用
AndroidEventBus
實現事件總線,此框架使用註解標記目標方法,統一將Tag的常量寫到EventBusTag接口中,便於管理,若是要在當前對象中使用AndroidEventBus
請在須要使用的Activity,Fragment,Presenter中重寫useEventBus()
,返回true表明使用,默認返回true
本框架使用AutoLayout框架,實現控件自適應,此框架要讓組件自適應,必須讓它的父控件,從新測量,和重寫LayoutParams,而官方只默認提供了三個ViewGroup,AutoRelativeLayout,AutoLinearLayout,AutoFrameLayout實現了這些操做,爲了方便開發者使用,本框架提供了一些經常使用的AutoLayout組件,在框架的widget包下的autolayout包中,在
xml
中引用便可使子控件自適應,而且還提供一個 Template(在最後面)用於生成自適應所須要的的Auto系列View,如須要使ScrollView的子控件自適應,使用此Template輸入ScrollView,便可生成AutoScrollView,在xml
中引用便可
框架提供一個建造者模式的自定義PopupWindow組件CustomPopupWindow,本身實現佈局後就能夠直接使用這個實現PopupWindow,使用建造者模式,隨意擴展自定義參數
本框架提供DefaultAdapter和BaseHolder基類快速實現Recycleview.
本框架使用RxPermissions用於權限管理(適配android6.0),並提供PermissionUtil工具類一行代碼實現權限請求.適配Android6.0權限管理詳解
PermissionUtil.launchCamera(new RequestPermission() { @Override public void onRequestPermissionSuccess() { launchCapture();//請求權限成功後作一些操做 } }, mRxPermissions, mRootView, mErrorHandler);
在主項目(app)的build.gradle中配置是否開啓打印Log或則是否使用
LeakCanary
,等調試工具
android { buildTypes { debug { //這兩個變量是自定義的,本身也能夠自定義字段,他會默認配置到BuildConfig中,app中能夠根據這些字段執行一些操做 buildConfigField "boolean", "LOG_DEBUG", "true" buildConfigField "boolean", "USE_CANARY", "true" minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } release { buildConfigField "boolean", "LOG_DEBUG", "false" buildConfigField "boolean", "USE_CANARY", "false" minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }
public class WEApplication extends BaseApplication { @Override public void onCreate() { if (BuildConfig.LOG_DEBUG) {//Timber日誌打印 Timber.plant(new Timber.DebugTree()); } if (BuildConfig.USE_CANARY) {//leakCanary內存泄露檢查 LeakCanary.install(this); } } }
AppManager用於管理全部的Activity,內部持有一個含有全部存活的Activity(未調用onDestroy)的List,和一個當前在最前端的Activity(未調用onPause),AppManager封裝有多種方法,能夠很方便的對它們進行操做,也能夠在未持有AppManager的狀況下,經過
EventBus
遠程遙控它的全部方法,這樣咱們能夠在整個app的任何地方對任何Activity進行全局操做,好比在app請求網絡超時時讓最前端的Activity顯示鏈接超時的交互頁面(這個邏輯不用寫到當前請求的Activity裏,能夠在一個單例類裏作全局的統一操做,由於能夠隨時經過AppManager拿到當前的Activity)
EventBus
post Message實現,經過不一樣的what區分不一樣的方法和Handler同理,能夠根據本身的需求適當的在AppManager中添加對應的方法/** * 經過eventbus post事件,遠程遙控執行對應方法 */ @Subscriber(tag = APPMANAGER_MESSAGE, mode = ThreadMode.MAIN) public void onReceive(Message message) { switch (message.what) { case START_ACTIVITY: dispatchStart(message); break; case SHOW_SNACKBAR: showSnackbar((String) message.obj, message.arg1 == 0 ? false : true); break; case KILL_ALL: killAll(); break; case APP_EXIT: AppExit(); break; } }
感謝本框架所使用到的全部三方庫的Author,以及全部爲Open Sourece
作無私貢獻的Developer和Organizations,使咱們能更好的工做和學習,本人也會將業餘時間回報給開源社區