Repository: wu928320442/EasyAndroid Branch: master Commit: 35d2b3091980 Files: 106 Total size: 136.5 KB Directory structure: gitextract_ng9b39p4/ ├── .gitignore ├── .idea/ │ ├── compiler.xml │ ├── copyright/ │ │ └── profiles_settings.xml │ ├── encodings.xml │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── README.md ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── wjj/ │ │ └── easy/ │ │ └── easyandroidHelper/ │ │ ├── AppApplication.java │ │ ├── common/ │ │ │ ├── base/ │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── BaseFragment.java │ │ │ │ ├── BasePresenter.java │ │ │ │ ├── BaseView.java │ │ │ │ ├── SimpleActivity.java │ │ │ │ └── SimpleFragment.java │ │ │ ├── di/ │ │ │ │ ├── ActivityCommonComponent.java │ │ │ │ ├── AppCommonComponent.java │ │ │ │ ├── AppCommonModule.java │ │ │ │ └── FragmentCommonComponent.java │ │ │ └── net/ │ │ │ ├── ApiService.java │ │ │ ├── AppHttp.java │ │ │ ├── CookieHead.java │ │ │ └── CookieInterceptor.java │ │ ├── model/ │ │ │ ├── ListInfo.java │ │ │ ├── LoginInfo.java │ │ │ ├── LoginResponse.java │ │ │ └── base/ │ │ │ ├── BaseChartInfo.java │ │ │ ├── BaseChartListInfo.java │ │ │ ├── BaseResponseInfo.java │ │ │ ├── BaseResponseListInfo.java │ │ │ └── BaseStatus.java │ │ ├── module/ │ │ │ ├── login/ │ │ │ │ ├── LoginActivity.java │ │ │ │ ├── LoginContract.java │ │ │ │ ├── LoginPresenter.java │ │ │ │ └── domain/ │ │ │ │ ├── GetVerifyCodeTask.java │ │ │ │ └── LoginTask.java │ │ │ └── main/ │ │ │ ├── HomeContract.java │ │ │ ├── HomeFragment.java │ │ │ ├── HomePresenter.java │ │ │ ├── MainActivity.java │ │ │ ├── MyContract.java │ │ │ ├── MyFragment.java │ │ │ ├── MyPresenter.java │ │ │ ├── adapter/ │ │ │ │ └── HomeAdapter.java │ │ │ └── domain/ │ │ │ └── GetListTask.java │ │ ├── utils/ │ │ │ └── SecretUtils.java │ │ └── widget/ │ │ └── dialog/ │ │ ├── BaseDialog.java │ │ └── DialogLoading.java │ └── res/ │ ├── anim/ │ │ ├── roll_down.xml │ │ ├── roll_up.xml │ │ ├── slide_in_bottom.xml │ │ └── slide_out_bottom.xml │ ├── drawable/ │ │ └── bg_color_white_corners_10.xml │ ├── layout/ │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── dialog_loading.xml │ │ ├── fragment_home.xml │ │ ├── fragment_my.xml │ │ ├── home_list_item.xml │ │ └── view_main_tab.xml │ ├── values/ │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ ├── values-v21/ │ │ └── styles.xml │ └── values-w820dp/ │ └── dimens.xml ├── build.gradle ├── easyandroid/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── wjj/ │ │ └── easy/ │ │ └── easyandroid/ │ │ ├── http/ │ │ │ └── Http.java │ │ ├── mvp/ │ │ │ ├── EasyBasePresenter.java │ │ │ ├── EasyBasePresenterFrg.java │ │ │ ├── EasyBaseView.java │ │ │ ├── EasyBaseViewFrg.java │ │ │ ├── di/ │ │ │ │ ├── components/ │ │ │ │ │ ├── ActivityComponent.java │ │ │ │ │ ├── AppComponent.java │ │ │ │ │ └── FragmentComponent.java │ │ │ │ ├── modules/ │ │ │ │ │ ├── ActivityModule.java │ │ │ │ │ ├── AppModule.java │ │ │ │ │ └── FragmentModule.java │ │ │ │ └── scopes/ │ │ │ │ ├── ActivityScope.java │ │ │ │ ├── ApplicationScope.java │ │ │ │ └── FragmentScope.java │ │ │ └── domain/ │ │ │ ├── executor/ │ │ │ │ ├── Executor.java │ │ │ │ ├── MainThread.java │ │ │ │ └── impl/ │ │ │ │ ├── MainThreadImpl.java │ │ │ │ └── ThreadExecutor.java │ │ │ └── usecases/ │ │ │ ├── AbstractUseCase.java │ │ │ └── UseCase.java │ │ └── ui/ │ │ ├── EasyActivity.java │ │ └── EasyFragment.java │ └── res/ │ └── values/ │ └── strings.xml ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.iml .gradle /local.properties /.idea/workspace.xml /.idea/libraries .DS_Store /build /captures .externalNativeBuild ================================================ FILE: .idea/compiler.xml ================================================ ================================================ FILE: .idea/copyright/profiles_settings.xml ================================================ ================================================ FILE: .idea/encodings.xml ================================================ ================================================ FILE: .idea/gradle.xml ================================================ ================================================ FILE: .idea/misc.xml ================================================ 1.8 ================================================ FILE: .idea/modules.xml ================================================ ================================================ FILE: .idea/runConfigurations.xml ================================================ ================================================ FILE: .idea/vcs.xml ================================================ ================================================ FILE: README.md ================================================ 最新版RxEasyAndroid 支持RxJava2 可移步到 https://github.com/wu928320442/RxEasyAndroid ----------------本版本为非RxJava2版本--------------- # 需要的环境 * JDK1.8 * SDK * AndroidStudio开发工具 # 特性 * 整合主流HTTP网络、图片加载、MVP(Clean+Dagger2)架构的一套快速高效的开发框架 * 包含app library 两个Module 组件化开发 # 用到的第三方框架 * SDK自带扩展依赖包 * Retrofit2网络层处理 使用OKHTTP3处理 * Fresco图片加载处理 使用OKHTTP3处理 * OKHTTP3 HTTP基础库,提供给网络层处理和图片加载 * PersistentCookieJar快速Cookie持久化与缓存库 * Dagger2 依赖注入库,整合Activity,Fragment,Presenter,Task之间的依赖关系 * Butterknife View的注入库 * BaseRecyclerViewAdapterHelper Recycler下拉加载库 * Utilcode实用工具库 * Logger 一个简洁漂亮的日志打印库 # 类库导入 ```gradle compile 'com.wjj.easy:easyandroid:1.0.0' ``` # 联系方式 * **QQ** 928320442 * **Android开发交流群** 323876830 * **Email** wujiajun311@gmail.com ================================================ FILE: app/.gitignore ================================================ /build ================================================ FILE: app/build.gradle ================================================ apply plugin: 'com.android.application' apply plugin: 'com.jakewharton.butterknife' android { compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion defaultConfig { applicationId rootProject.ext.applicationId minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile project(path: ':easyandroid') //butterknife viewInject compile "com.jakewharton:butterknife:$rootProject.butterknife" compile "com.jakewharton:butterknife-compiler:$rootProject.butterknife" compile 'com.wjj.easy:qrcodestyle:1.0.0' } ================================================ FILE: app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /Users/wujiajun/Library/Android/sdk/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} #-------------------------------------------基本不用动区域-------------------------------------------- #---------------------------------基本指令区---------------------------------- -optimizationpasses 5 -dontskipnonpubliclibraryclassmembers -printmapping proguardMapping.txt -optimizations !code/simplification/cast,!field/*,!class/merging/* -keepattributes *Annotation*,InnerClasses -keepattributes Signature -keepattributes SourceFile,LineNumberTable #---------------------------------------------------------------------------- #---------------------------------默认保留区--------------------------------- #继承activity,application,service,broadcastReceiver,contentprovider....不进行混淆 -keep public class * extends android.app.Activity -keep public class * extends android.app.Application -keep public class * extends android.support.multidex.MultiDexApplication -keep public class * extends android.app.Service -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.ContentProvider -keep public class * extends android.app.backup.BackupAgentHelper -keep public class * extends android.preference.Preference -keep public class * extends android.view.View -keep public class com.android.vending.licensing.ILicensingService -keep class android.support.** {*;} -keep class **JNI* {*;} -keep public class * extends android.view.View{ *** get*(); void set*(***); public (android.content.Context); public (android.content.Context, android.util.AttributeSet); public (android.content.Context, android.util.AttributeSet, int); } -keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet); public (android.content.Context, android.util.AttributeSet, int); } #这个主要是在layout 中写的onclick方法android:onclick="onClick",不进行混淆 -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } -keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve(); } -keep class **.R$* { *; } -keepclassmembers class * { void *(*Event); } -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } #// natvie 方法不混淆 -keepclasseswithmembernames class * { native ; } #保持 Parcelable 不被混淆 -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } #---------------------第三方--------------- #butterknife -keep class **$$ViewBinder { *; } #BaseRecyclerViewAdapterHelper -keep class com.chad.library.adapter.** { *; } ================================================ FILE: app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/AppApplication.java ================================================ package com.wjj.easy.easyandroidHelper; import android.app.Application; import com.wjj.easy.easyandroidHelper.common.di.AppCommonComponent; import com.wjj.easy.easyandroidHelper.common.di.AppCommonModule; import com.wjj.easy.easyandroidHelper.common.di.DaggerAppCommonComponent; /** * Created by wujiajun on 17/4/6. */ public class AppApplication extends Application { AppCommonComponent aComponent; @Override public void onCreate() { super.onCreate(); aComponent = DaggerAppCommonComponent.builder().appCommonModule(new AppCommonModule(this)).build(); } public AppCommonComponent getAppComponent() { return aComponent; } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/base/BaseActivity.java ================================================ package com.wjj.easy.easyandroidHelper.common.base; import android.os.Bundle; import android.support.annotation.Nullable; import com.blankj.utilcode.util.ToastUtils; import com.wjj.easy.easyandroid.mvp.EasyBasePresenter; import com.wjj.easy.easyandroid.mvp.di.modules.ActivityModule; import com.wjj.easy.easyandroid.ui.EasyActivity; import com.wjj.easy.easyandroidHelper.AppApplication; import com.wjj.easy.easyandroidHelper.common.di.ActivityCommonComponent; import com.wjj.easy.easyandroidHelper.common.di.DaggerActivityCommonComponent; import com.wjj.easy.easyandroidHelper.widget.dialog.DialogLoading; import javax.inject.Inject; import butterknife.ButterKnife; /** * Activity业务基类 * Created by wujiajun on 17/4/10. */ public abstract class BaseActivity

extends EasyActivity { protected DialogLoading loading; @Inject protected P mPresenter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(); initInject(); if (mPresenter != null) mPresenter.attachView(this); initEventAndData(); } protected void initView() { ButterKnife.bind(this); loading = new DialogLoading(this); } public void toast(String msg) { ToastUtils.showShortToast(msg); } public void showLoading() { loading.show(); } public void hiddenLoading() { loading.hide(); } protected ActivityCommonComponent getActivityComponent() { return DaggerActivityCommonComponent.builder() .appCommonComponent(((AppApplication) getApplication()).getAppComponent()) .activityModule(getActivityModule()) .build(); } protected ActivityModule getActivityModule() { return new ActivityModule(this); } public P getPresenter() { return mPresenter; } protected abstract void initInject(); protected abstract void initEventAndData(); } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/base/BaseFragment.java ================================================ package com.wjj.easy.easyandroidHelper.common.base; import android.view.View; import com.blankj.utilcode.util.ToastUtils; import com.wjj.easy.easyandroid.mvp.EasyBasePresenter; import com.wjj.easy.easyandroid.mvp.di.modules.FragmentModule; import com.wjj.easy.easyandroid.ui.EasyFragment; import com.wjj.easy.easyandroidHelper.AppApplication; import com.wjj.easy.easyandroidHelper.common.di.DaggerFragmentCommonComponent; import com.wjj.easy.easyandroidHelper.common.di.FragmentCommonComponent; import com.wjj.easy.easyandroidHelper.widget.dialog.DialogLoading; import javax.inject.Inject; import butterknife.ButterKnife; /** * Fragment业务基类 * * @author wujiajun */ public abstract class BaseFragment

extends EasyFragment { @Inject protected P mPresenter; protected DialogLoading loading; @Override protected void initView(View view) { ButterKnife.bind(this, view); loading = new DialogLoading(getActivity()); } @Override protected void init(View view) { initInject(); if (mPresenter != null) mPresenter.attachView(this); initEventAndData(); } @Override public void onStart() { super.onStart(); mPresenter.start(); } public void toast(String msg) { ToastUtils.showShortToast(msg); } public void showLoading() { loading.show(); } public void hiddenLoading() { loading.hide(); } protected FragmentCommonComponent getFragmentComponent() { return DaggerFragmentCommonComponent.builder() .appCommonComponent(((AppApplication) getActivity().getApplication()).getAppComponent()) .fragmentModule(getFragmentModule()) .build(); } protected FragmentModule getFragmentModule() { return new FragmentModule(this); } protected abstract void initInject(); protected abstract void initEventAndData(); public void setPresenter(P presenter) { mPresenter = presenter; } public P getPresenter() { return mPresenter; } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/base/BasePresenter.java ================================================ package com.wjj.easy.easyandroidHelper.common.base; import com.wjj.easy.easyandroid.mvp.EasyBasePresenter; import com.wjj.easy.easyandroid.mvp.EasyBaseView; import com.wjj.easy.easyandroid.mvp.domain.executor.Executor; import com.wjj.easy.easyandroid.mvp.domain.executor.MainThread; import com.wjj.easy.easyandroid.mvp.domain.usecases.AbstractUseCase; import javax.inject.Inject; /** * Presenter基类 * * @author wujiajun */ public class BasePresenter implements EasyBasePresenter { protected V mView; @Inject Executor threadExecutor; @Inject MainThread mainThread; @Override public void start() { } public void attachView(V view) { mView = view; } public V getView() { return mView; } public Executor getThreadExecutor() { return threadExecutor; } protected void execute(AbstractUseCase task) { getThreadExecutor().execute(task); } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/base/BaseView.java ================================================ package com.wjj.easy.easyandroidHelper.common.base; import com.wjj.easy.easyandroid.mvp.EasyBasePresenter; import com.wjj.easy.easyandroid.mvp.EasyBaseView; /** * BaseView业务基类 * Created by wujiajun on 17/4/14. */ public interface BaseView extends EasyBaseView { void toast(String msg); void showLoading(); void hiddenLoading(); } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/base/SimpleActivity.java ================================================ package com.wjj.easy.easyandroidHelper.common.base; import android.os.Bundle; import android.support.annotation.Nullable; import com.blankj.utilcode.util.ToastUtils; import com.wjj.easy.easyandroid.ui.EasyActivity; import com.wjj.easy.easyandroidHelper.widget.dialog.DialogLoading; import butterknife.ButterKnife; /** * Activity业务基类简单实现(不包含Presenter) * * @author wujiajun */ public abstract class SimpleActivity extends EasyActivity { protected DialogLoading loading; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(); initEventAndData(); } protected void initView() { ButterKnife.bind(this); loading = new DialogLoading(this); } public void toast(String msg) { ToastUtils.showShortToast(msg); } public void showLoading() { loading.show(); } public void hiddenLoading() { loading.hide(); } protected abstract void initEventAndData(); } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/base/SimpleFragment.java ================================================ package com.wjj.easy.easyandroidHelper.common.base; import android.view.View; import com.blankj.utilcode.util.ToastUtils; import com.wjj.easy.easyandroid.ui.EasyFragment; import com.wjj.easy.easyandroidHelper.widget.dialog.DialogLoading; import butterknife.ButterKnife; /** * Fragment业务基类(不包含Presenter) * * @author wujiajun */ public abstract class SimpleFragment extends EasyFragment { protected DialogLoading loading; @Override protected void initView(View view) { ButterKnife.bind(this, view); loading = new DialogLoading(getActivity()); } @Override protected void init(View view) { initEventAndData(); } @Override public void onStart() { super.onStart(); } public void toast(String msg) { ToastUtils.showShortToast(msg); } public void showLoading() { loading.show(); } public void hiddenLoading() { loading.hide(); } protected abstract void initEventAndData(); } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/di/ActivityCommonComponent.java ================================================ package com.wjj.easy.easyandroidHelper.common.di; import com.wjj.easy.easyandroid.mvp.di.components.ActivityComponent; import com.wjj.easy.easyandroid.mvp.di.modules.ActivityModule; import com.wjj.easy.easyandroid.mvp.di.scopes.ActivityScope; import com.wjj.easy.easyandroidHelper.module.login.LoginActivity; import com.wjj.easy.easyandroidHelper.module.main.MainActivity; import dagger.Component; /** * Activity注入器 * @author wujiajun */ @ActivityScope @Component(dependencies = AppCommonComponent.class, modules = {ActivityModule.class}) public interface ActivityCommonComponent extends ActivityComponent { void inject(LoginActivity activity); void inject(MainActivity activity); } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/di/AppCommonComponent.java ================================================ package com.wjj.easy.easyandroidHelper.common.di; import com.wjj.easy.easyandroid.mvp.di.components.AppComponent; import com.wjj.easy.easyandroid.mvp.di.scopes.ApplicationScope; import com.wjj.easy.easyandroid.mvp.domain.executor.Executor; import com.wjj.easy.easyandroid.mvp.domain.executor.MainThread; import com.wjj.easy.easyandroidHelper.common.net.ApiService; import dagger.Component; /** * Application注入器 * * @author wujiajun */ @ApplicationScope @Component(modules = AppCommonModule.class) public interface AppCommonComponent extends AppComponent { ApiService getApiService(); Executor getExecutor(); MainThread getMainThread(); } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/di/AppCommonModule.java ================================================ package com.wjj.easy.easyandroidHelper.common.di; import android.content.Context; import com.blankj.utilcode.util.Utils; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory; import com.facebook.imagepipeline.core.ImagePipelineConfig; import com.franmontiel.persistentcookiejar.ClearableCookieJar; import com.franmontiel.persistentcookiejar.PersistentCookieJar; import com.franmontiel.persistentcookiejar.cache.SetCookieCache; import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; import com.wjj.easy.easyandroid.http.Http; import com.wjj.easy.easyandroid.mvp.di.modules.AppModule; import com.wjj.easy.easyandroid.mvp.domain.executor.Executor; import com.wjj.easy.easyandroid.mvp.domain.executor.MainThread; import com.wjj.easy.easyandroid.mvp.domain.executor.impl.MainThreadImpl; import com.wjj.easy.easyandroid.mvp.domain.executor.impl.ThreadExecutor; import com.wjj.easy.easyandroidHelper.common.net.ApiService; import com.wjj.easy.easyandroidHelper.common.net.CookieInterceptor; import dagger.Module; import dagger.Provides; /** * Application Module * * @author wujiajun */ @Module public class AppCommonModule extends AppModule { private Http mHttp; public AppCommonModule(Context context) { super(context); initHttp(); initImage(); initUtils(); } /** * Http初始化 */ private void initHttp() { //cookie cache & persistor ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(provideContext())); mHttp = new Http.HttpBuilder() .setBaseUrl(ApiService.HOST) .setCookieJar(cookieJar) .setTimeout(15) .addInterceptor(new CookieInterceptor()) .build(); } /** * Fresco初始化 */ private void initImage() { ImagePipelineConfig config = OkHttpImagePipelineConfigFactory .newBuilder(provideContext(), mHttp.getClient()) .build(); Fresco.initialize(provideContext(), config); } /** * Utils库初始化 */ private void initUtils() { Utils.init(provideContext()); } @Provides ApiService provideApiService() { return mHttp.getRetrofit().create(ApiService.class); } @Provides Executor provideExecutor() { return ThreadExecutor.getInstance(); } @Provides MainThread provideMainThread() { return MainThreadImpl.getInstance(); } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/di/FragmentCommonComponent.java ================================================ package com.wjj.easy.easyandroidHelper.common.di; import com.wjj.easy.easyandroid.mvp.di.components.FragmentComponent; import com.wjj.easy.easyandroid.mvp.di.modules.FragmentModule; import com.wjj.easy.easyandroid.mvp.di.scopes.FragmentScope; import com.wjj.easy.easyandroidHelper.module.main.HomeFragment; import com.wjj.easy.easyandroidHelper.module.main.MyFragment; import dagger.Component; /** * Fragment注入器 * * @author wujiajun */ @FragmentScope @Component(dependencies = AppCommonComponent.class, modules = {FragmentModule.class}) public interface FragmentCommonComponent extends FragmentComponent { void inject(HomeFragment fragment); void inject(MyFragment fragment); } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/net/ApiService.java ================================================ package com.wjj.easy.easyandroidHelper.common.net; import com.wjj.easy.easyandroidHelper.model.ListInfo; import com.wjj.easy.easyandroidHelper.model.LoginResponse; import com.wjj.easy.easyandroidHelper.model.base.BaseStatus; import retrofit2.Call; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.POST; import retrofit2.http.Query; /** * Created by wujiajun on 17/4/5. */ public interface ApiService { // 线上 String HOST = "http://dw.qianbao666.com/";//dcw.qbao.com dw.qianbao666.com /** * 获取注册验证码 */ @FormUrlEncoded @POST(HOST + "app/sendSMS.do") Call getVerifyCode(@Field("username") String username, @Field("password") String pwd); /** * 用户登录 */ @FormUrlEncoded @POST(HOST + "app/login.do") Call login(@Field("username") String username, @Field("password") String pwd, @Field("code") String verifyCode); /** * 获取列表数据 */ @GET("http://baoyue.qbao.com/app/task/list.json") Call getList(@Query("type") int type, @Query("page") int page, @Query("rows") int rows); } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/net/AppHttp.java ================================================ package com.wjj.easy.easyandroidHelper.common.net; import com.wjj.easy.easyandroid.http.Http; import com.wjj.easy.easyandroidHelper.model.ListInfo; import com.wjj.easy.easyandroidHelper.model.LoginResponse; import com.wjj.easy.easyandroidHelper.model.base.BaseStatus; import javax.inject.Inject; import retrofit2.Call; /** * Created by wujiajun on 17/4/5. */ public class AppHttp { private ApiService apiService; @Inject public AppHttp(ApiService apiService) { this.apiService = apiService; } public void getVerifyCode(String username, String pwd, final Http.HttpCallback callback) { Call call = apiService.getVerifyCode(username, pwd); call.enqueue(new Http.CallbackDefault(callback)); call.request(); } public void login(String username, String pwd, String verifyCode, final Http.HttpCallback callback) { Call call = apiService.login(username, pwd, verifyCode); call.enqueue(new Http.CallbackDefault(callback)); call.request(); } public void getList(int index, final Http.HttpCallback callback) { Call call = apiService.getList(1,index,20); call.enqueue(new Http.CallbackDefault(callback)); call.request(); } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/net/CookieHead.java ================================================ package com.wjj.easy.easyandroidHelper.common.net; /** * Created by wujiajun on 17/4/11. */ public enum CookieHead { CLIENT_TYPE("client_type", "android"), USER_NAME("user_name", ""); private String head; private String value; CookieHead(String head, String value) { this.head = head; this.value = value; } public String getHead() { return head; } public String getValue() { return value; } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/common/net/CookieInterceptor.java ================================================ package com.wjj.easy.easyandroidHelper.common.net; import java.io.IOException; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; /** * Created by wujiajun on 17/4/11. */ public class CookieInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request(); Request request = original.newBuilder() .header(CookieHead.USER_NAME.getHead(), CookieHead.CLIENT_TYPE.getValue()) .header(CookieHead.CLIENT_TYPE.getHead(), "wjj") .method(original.method(), original.body()) .build(); return chain.proceed(request); } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/model/ListInfo.java ================================================ package com.wjj.easy.easyandroidHelper.model; import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; import java.util.List; /** * Created by ljw on 2017/4/13. */ public class ListInfo implements Parcelable { /** * success : true * returnCode : 0 * message : ok * data : [{"taskId":2539544,"title":"李茶的姑妈","content":"李茶的姑妈","imageUrl":"https://qn-message.qbcdn.com/5aeceeb6753d48638a596b842ed7c98e","amt":"290","doTime":"2017-04-18","city":"南京","address":"江苏省南京市","payKind":"元","taskTypeName":"宝约优选","onlyVip":0,"hasMemberAmt":0,"memberAmt":"0","isFree":false},{"taskId":2539751,"title":"浪漫白色女神节相约鹦鹉螺市集","content":"浪漫白色女神节相约鹦鹉螺市集","imageUrl":"https://qn-message.qbcdn.com/2c5216f7e2cd49dfb1a92ec7d59da636","amt":"1","doTime":"2017-06-18","city":"上海","address":"上海市上海市","payKind":"元","taskTypeName":"宝约优选","onlyVip":0,"hasMemberAmt":0,"memberAmt":"0","isFree":false},{"taskId":2539926,"title":"走进J Studio艺术沙龙 | 用画笔定格粉红樱花,画出心中最美花海","content":"走进J Studio艺术沙龙 | 用画笔定格粉红樱花,画出心中最美花海","imageUrl":"https://qn-message.qbcdn.com/16930371610448289a859eb802e9837a","amt":"140","doTime":"2017-05-05","city":"上海","address":"上海市上海市","payKind":"元","taskTypeName":"宝约优选","onlyVip":0,"hasMemberAmt":0,"memberAmt":"0","isFree":false},{"taskId":2539933,"title":"花艺课堂 | 摘几束鲜花 搭出别样精彩","content":"花艺课堂 | 摘几束鲜花 搭出别样精彩","imageUrl":"https://qn-message.qbcdn.com/c2354e61e34d415e8b46fa0091eafda6","amt":"188","doTime":"2017-04-28","city":"上海","address":"上海市上海市","payKind":"元","taskTypeName":"宝约优选","onlyVip":0,"hasMemberAmt":0,"memberAmt":"0","isFree":false},{"taskId":2539935,"title":"最会\u201c讲故事的人\u201d英国艺术家瑞安·甘德在华首展","content":"最会\u201c讲故事的人\u201d英国艺术家瑞安·甘德在华首展","imageUrl":"https://qn-message.qbcdn.com/d09c37f19d654cef9c8b82f8cee8e17b","amt":"1","doTime":"2017-05-14","city":"上海","address":"上海市上海市","payKind":"元","taskTypeName":"宝约优选","onlyVip":0,"hasMemberAmt":0,"memberAmt":"0","isFree":false},{"taskId":2539949,"title":"ING手持吸尘器 G3006 | 机身小巧轻盈,手持轻轻松松","content":"ING手持吸尘器 G3006 | 机身小巧轻盈,手持轻轻松松","imageUrl":"https://qn-message.qbcdn.com/e8ab5b49f67c465a98060b68d209a8dd","amt":"1,192","doTime":"2017-04-30","city":"上海","address":"上海市上海市","payKind":"元","taskTypeName":"宝约优选","onlyVip":0,"hasMemberAmt":0,"memberAmt":"0","isFree":false},{"taskId":2539950,"title":"ING手持吸尘器 G3010 | 拒绝束缚·做有态度的吸尘器","content":"ING手持吸尘器 G3010 | 拒绝束缚·做有态度的吸尘器","imageUrl":"https://qn-message.qbcdn.com/9e24b97a47e242169f787979559218d9","amt":"1,639","doTime":"2017-04-30","city":"上海","address":"上海市上海市","payKind":"元","taskTypeName":"宝约优选","onlyVip":0,"hasMemberAmt":0,"memberAmt":"0","isFree":false},{"taskId":2539952,"title":"ING手持吸尘器 G3009 | 单手除尘·更轻便","content":"ING手持吸尘器 G3009 | 单手除尘·更轻便","imageUrl":"https://qn-message.qbcdn.com/416d3fa70ec24f2daac9a2492c1b0307","amt":"3,180","doTime":"2017-04-30","city":"上海","address":"上海市上海市","payKind":"元","taskTypeName":"宝约优选","onlyVip":0,"hasMemberAmt":0,"memberAmt":"0","isFree":false},{"taskId":2539983,"title":"摘草莓亲子活动|春の果实 新鲜采摘才好吃","content":"摘草莓亲子活动|春の果实 新鲜采摘才好吃","imageUrl":"https://qn-message.qbcdn.com/747deaa8a96048588bfc640c879e3285","amt":"80","doTime":"2017-04-24","city":"上海","address":"上海市上海市","payKind":"元","taskTypeName":"宝约优选","onlyVip":0,"hasMemberAmt":0,"memberAmt":"0","isFree":false},{"taskId":2540049,"title":"\u201c凝固\u2014基弗在中国\u201d安塞姆·基弗作品展 南京站","content":"\u201c凝固\u2014基弗在中国\u201d安塞姆·基弗作品展 南京站","imageUrl":"https://qn-message.qbcdn.com/3b52d69597114e3b924f21a1cb59a8ef","amt":"62","doTime":"2017-05-04","city":"南京","address":"江苏省南京市","payKind":"元","taskTypeName":"宝约优选","onlyVip":0,"hasMemberAmt":0,"memberAmt":"0","isFree":false}] */ private boolean success; private int returnCode; private String message; private List data; public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public int getReturnCode() { return returnCode; } public void setReturnCode(int returnCode) { this.returnCode = returnCode; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public List getData() { return data; } public void setData(List data) { this.data = data; } public static class DataBean { @Override public String toString() { return "DataBean{" + "taskId=" + taskId + ", title='" + title + '\'' + ", content='" + content + '\'' + ", imageUrl='" + imageUrl + '\'' + ", amt='" + amt + '\'' + ", doTime='" + doTime + '\'' + ", city='" + city + '\'' + ", address='" + address + '\'' + ", payKind='" + payKind + '\'' + ", taskTypeName='" + taskTypeName + '\'' + ", onlyVip=" + onlyVip + ", hasMemberAmt=" + hasMemberAmt + ", memberAmt='" + memberAmt + '\'' + ", isFree=" + isFree + '}'; } /** * taskId : 2539544 * title : 李茶的姑妈 * content : 李茶的姑妈 * imageUrl : https://qn-message.qbcdn.com/5aeceeb6753d48638a596b842ed7c98e * amt : 290 * doTime : 2017-04-18 * city : 南京 * address : 江苏省南京市 * payKind : 元 * taskTypeName : 宝约优选 * onlyVip : 0 * hasMemberAmt : 0 * memberAmt : 0 * isFree : false */ private int taskId; private String title; private String content; private String imageUrl; private String amt; private String doTime; private String city; private String address; private String payKind; private String taskTypeName; private int onlyVip; private int hasMemberAmt; private String memberAmt; private boolean isFree; public int getTaskId() { return taskId; } public void setTaskId(int taskId) { this.taskId = taskId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getImageUrl() { return imageUrl; } public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; } public String getAmt() { return amt; } public void setAmt(String amt) { this.amt = amt; } public String getDoTime() { return doTime; } public void setDoTime(String doTime) { this.doTime = doTime; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getPayKind() { return payKind; } public void setPayKind(String payKind) { this.payKind = payKind; } public String getTaskTypeName() { return taskTypeName; } public void setTaskTypeName(String taskTypeName) { this.taskTypeName = taskTypeName; } public int getOnlyVip() { return onlyVip; } public void setOnlyVip(int onlyVip) { this.onlyVip = onlyVip; } public int getHasMemberAmt() { return hasMemberAmt; } public void setHasMemberAmt(int hasMemberAmt) { this.hasMemberAmt = hasMemberAmt; } public String getMemberAmt() { return memberAmt; } public void setMemberAmt(String memberAmt) { this.memberAmt = memberAmt; } public boolean isIsFree() { return isFree; } public void setIsFree(boolean isFree) { this.isFree = isFree; } } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeByte(this.success ? (byte) 1 : (byte) 0); dest.writeInt(this.returnCode); dest.writeString(this.message); dest.writeList(this.data); } public ListInfo() { } protected ListInfo(Parcel in) { this.success = in.readByte() != 0; this.returnCode = in.readInt(); this.message = in.readString(); this.data = new ArrayList(); in.readList(this.data, DataBean.class.getClassLoader()); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public ListInfo createFromParcel(Parcel source) { return new ListInfo(source); } @Override public ListInfo[] newArray(int size) { return new ListInfo[size]; } }; @Override public String toString() { return "ListInfo{" + "success=" + success + ", returnCode=" + returnCode + ", message='" + message + '\'' + ", data=" + data + '}'; } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/model/LoginInfo.java ================================================ package com.wjj.easy.easyandroidHelper.model; import android.os.Parcel; import android.os.Parcelable; /** * Created by zhaotun on 2016/12/20. */ public class LoginInfo implements Parcelable { /** * mobile : 15670388343 * sessionId : 8996AD494B77221C98EE7C6D359224A1.o214zsug */ private String mobile; private String sessionId; public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public String getSessionId() { return sessionId; } public void setSessionId(String sessionId) { this.sessionId = sessionId; } @Override public String toString() { return "LoginInfo{" + "mobile='" + mobile + '\'' + ", sessionId='" + sessionId + '\'' + '}'; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.mobile); dest.writeString(this.sessionId); } protected LoginInfo(Parcel in) { this.mobile = in.readString(); this.sessionId = in.readString(); } public static final Creator CREATOR = new Creator() { @Override public LoginInfo createFromParcel(Parcel source) { return new LoginInfo(source); } @Override public LoginInfo[] newArray(int size) { return new LoginInfo[size]; } }; } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/model/LoginResponse.java ================================================ package com.wjj.easy.easyandroidHelper.model; import com.wjj.easy.easyandroidHelper.model.base.BaseResponseInfo; /** * Created by zhaotun on 2016/12/20. */ public class LoginResponse extends BaseResponseInfo { } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/model/base/BaseChartInfo.java ================================================ package com.wjj.easy.easyandroidHelper.model.base; import android.os.Parcel; import android.os.Parcelable; /** * Created by zhaotun on 2016/12/26. */ public class BaseChartInfo implements Parcelable { private boolean success; private int totalCount; private int recordsTotal; private int recordsFiltered; private T data; public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } public int getRecordsTotal() { return recordsTotal; } public void setRecordsTotal(int recordsTotal) { this.recordsTotal = recordsTotal; } public int getRecordsFiltered() { return recordsFiltered; } public void setRecordsFiltered(int recordsFiltered) { this.recordsFiltered = recordsFiltered; } public T getData() { return data; } public void setData(T data) { this.data = data; } @Override public String toString() { return "BaseChartInfo{" + "success=" + success + ", totalCount=" + totalCount + ", recordsTotal=" + recordsTotal + ", recordsFiltered=" + recordsFiltered + ", data=" + data + '}'; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeByte(this.success ? (byte) 1 : (byte) 0); dest.writeInt(this.totalCount); dest.writeInt(this.recordsTotal); dest.writeInt(this.recordsFiltered); dest.writeString(this.data.getClass().getName()); dest.writeParcelable(this.data, flags); } public BaseChartInfo() { } protected BaseChartInfo(Parcel in) { this.success = in.readByte() != 0; this.totalCount = in.readInt(); this.recordsTotal = in.readInt(); this.recordsFiltered = in.readInt(); try { String className = in.readString(); this.data = in.readParcelable(Class.forName(className).getClassLoader()); } catch (Exception e) { e.printStackTrace(); } } public static final Creator CREATOR = new Creator() { @Override public BaseChartInfo createFromParcel(Parcel source) { return new BaseChartInfo(source); } @Override public BaseChartInfo[] newArray(int size) { return new BaseChartInfo[size]; } }; } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/model/base/BaseChartListInfo.java ================================================ package com.wjj.easy.easyandroidHelper.model.base; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; /** * Created by zhaotun on 2016/12/26. */ public class BaseChartListInfo implements Parcelable { public static final String PARCELABLE_ARRAY_LIST_DATA_KEY = "parcelable_array_list_data_key"; private boolean success; private int totalCount; private int recordsTotal; private int recordsFiltered; private ArrayList data; public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } public int getRecordsTotal() { return recordsTotal; } public void setRecordsTotal(int recordsTotal) { this.recordsTotal = recordsTotal; } public int getRecordsFiltered() { return recordsFiltered; } public void setRecordsFiltered(int recordsFiltered) { this.recordsFiltered = recordsFiltered; } public ArrayList getData() { return data; } public void setData(ArrayList data) { this.data = data; } @Override public String toString() { return "BaseChartInfo{" + "success=" + success + ", totalCount=" + totalCount + ", recordsTotal=" + recordsTotal + ", recordsFiltered=" + recordsFiltered + ", data=" + data + '}'; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeByte(this.success ? (byte) 1 : (byte) 0); dest.writeInt(this.totalCount); dest.writeInt(this.recordsTotal); dest.writeInt(this.recordsFiltered); Bundle bundle = new Bundle(); bundle.putParcelableArrayList(PARCELABLE_ARRAY_LIST_DATA_KEY, data); dest.writeBundle(bundle); } public BaseChartListInfo() { } protected BaseChartListInfo(Parcel in) { this.success = in.readByte() != 0; this.totalCount = in.readInt(); this.recordsTotal = in.readInt(); this.recordsFiltered = in.readInt(); try { this.data = in.readBundle().getParcelableArrayList(PARCELABLE_ARRAY_LIST_DATA_KEY); } catch (Exception e) { e.printStackTrace(); } } public static final Creator CREATOR = new Creator() { @Override public BaseChartListInfo createFromParcel(Parcel source) { return new BaseChartListInfo(source); } @Override public BaseChartListInfo[] newArray(int size) { return new BaseChartListInfo[size]; } }; } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/model/base/BaseResponseInfo.java ================================================ package com.wjj.easy.easyandroidHelper.model.base; import android.os.Parcel; import android.os.Parcelable; /** * Created by zhaotun . */ public class BaseResponseInfo extends BaseStatus { private T data; public T getData() { return data; } public void setData(T data) { this.data = data; } @Override public String toString() { return super.toString() + " BaseResponseInfo{" + "data=" + data + '}'; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeString(this.data.getClass().getName()); dest.writeParcelable(this.data, flags); } public BaseResponseInfo() { } protected BaseResponseInfo(Parcel in) { super(in); try { String className = in.readString(); this.data = in.readParcelable(Class.forName(className).getClassLoader()); } catch (Exception e) { e.printStackTrace(); } } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public BaseResponseInfo createFromParcel(Parcel source) { return new BaseResponseInfo(source); } @Override public BaseResponseInfo[] newArray(int size) { return new BaseResponseInfo[size]; } }; } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/model/base/BaseResponseListInfo.java ================================================ package com.wjj.easy.easyandroidHelper.model.base; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; /** * Created by zhaotun . */ public class BaseResponseListInfo extends BaseStatus { public static final String PARCELABLE_ARRAY_LIST_DATA_KEY = "parcelable_array_list_data_key"; private ArrayList data; public ArrayList getData() { return data; } public void setData(ArrayList data) { this.data = data; } @Override public String toString() { return super.toString() + " BaseResponseListInfo{" + "data=" + data + '}'; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); Bundle bundle = new Bundle(); bundle.putParcelableArrayList(PARCELABLE_ARRAY_LIST_DATA_KEY, data); dest.writeBundle(bundle); } public BaseResponseListInfo() { } protected BaseResponseListInfo(Parcel in) { super(in); try { this.data = in.readBundle().getParcelableArrayList(PARCELABLE_ARRAY_LIST_DATA_KEY); } catch (Exception e) { e.printStackTrace(); } } public static final Creator CREATOR = new Creator() { @Override public BaseResponseListInfo createFromParcel(Parcel source) { return new BaseResponseListInfo(source); } @Override public BaseResponseListInfo[] newArray(int size) { return new BaseResponseListInfo[size]; } }; } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/model/base/BaseStatus.java ================================================ package com.wjj.easy.easyandroidHelper.model.base; import android.os.Parcel; import android.os.Parcelable; /** * Created by zhaotun */ public class BaseStatus implements Parcelable { public static final int RESPONSE_CODE_SUCCESS = 0; private int code;// 0成功 private String message; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public boolean isSuccess() { return code == RESPONSE_CODE_SUCCESS; } @Override public String toString() { return "BaseStatus{" + "code=" + code + ", message='" + message + '\'' + '}'; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(this.code); dest.writeString(this.message); } public BaseStatus() { } protected BaseStatus(Parcel in) { this.code = in.readInt(); this.message = in.readString(); } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/login/LoginActivity.java ================================================ package com.wjj.easy.easyandroidHelper.module.login; import android.content.Intent; import android.support.v4.content.ContextCompat; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.EditText; import android.widget.TextView; import com.wjj.easy.easyandroidHelper.R; import com.wjj.easy.easyandroidHelper.common.base.BaseActivity; import com.wjj.easy.easyandroidHelper.module.main.MainActivity; import butterknife.BindView; import butterknife.OnClick; /** * 登录Activity * * @author wujiajun */ public class LoginActivity extends BaseActivity implements LoginContract.View { @BindView(R.id.set_user_name) EditText setUserName; @BindView(R.id.set_pwd) EditText setPwd; @BindView(R.id.set_verify_code) EditText setVerifyCode; @BindView(R.id.get_verify_code) TextView getVerifyCode; @BindView(R.id.tv_login) TextView tvLogin; @BindView(R.id.tool_bar) Toolbar toolbar; @Override protected void initInject() { getActivityComponent().inject(this); } @Override protected void initEventAndData() { toolbar.setLogo(R.mipmap.icon_app); toolbar.setTitle(R.string.app_name); toolbar.setTitleTextColor(ContextCompat.getColor(this, R.color.white)); toolbar.setTitleMarginStart(getResources().getDimensionPixelSize(R.dimen.padding_size_30)); setSupportActionBar(toolbar); } @Override protected int getContentView() { return R.layout.activity_login; } @OnClick({R.id.get_verify_code, R.id.tv_login}) public void onClick(View view) { switch (view.getId()) { case R.id.get_verify_code: getPresenter().getVerifyCode(setUserName.getText().toString(), setPwd.getText().toString()); startActivity(new Intent(this, MainActivity.class)); break; case R.id.tv_login: getPresenter().login(setUserName.getText().toString(), setPwd.getText().toString(), setVerifyCode.getText().toString()); break; } } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/login/LoginContract.java ================================================ package com.wjj.easy.easyandroidHelper.module.login; import com.wjj.easy.easyandroid.mvp.EasyBasePresenter; import com.wjj.easy.easyandroidHelper.common.base.BaseView; /** * LoginContract * Created by wujiajun on 17/4/7. */ public interface LoginContract { interface View extends BaseView { } interface Presenter extends EasyBasePresenter { void getVerifyCode(String userName, String pwd); void login(String userName, String pwd, String verifyCode); } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/login/LoginPresenter.java ================================================ package com.wjj.easy.easyandroidHelper.module.login; import com.wjj.easy.easyandroid.mvp.domain.usecases.UseCase; import com.wjj.easy.easyandroidHelper.common.base.BasePresenter; import com.wjj.easy.easyandroidHelper.model.LoginResponse; import com.wjj.easy.easyandroidHelper.model.base.BaseStatus; import com.wjj.easy.easyandroidHelper.module.login.domain.GetVerifyCodeTask; import com.wjj.easy.easyandroidHelper.module.login.domain.LoginTask; import javax.inject.Inject; /** * Login Presenter * Created by wujiajun on 17/4/7. */ public class LoginPresenter extends BasePresenter implements LoginContract.Presenter { @Inject GetVerifyCodeTask mGetVerifyCodeTask; @Inject LoginTask mLoginTask; @Inject public LoginPresenter() { } @Override public void getVerifyCode(String userName, String pwd) { mGetVerifyCodeTask.setUserName(userName); mGetVerifyCodeTask.setPwd(pwd); mGetVerifyCodeTask.setCallback(new UseCase.Callback() { @Override public void success(BaseStatus baseStatus) { getView().toast("getVerifyCode success!"); } @Override public void fail() { getView().toast("getVerifyCode fail!"); } }); getThreadExecutor().execute(mGetVerifyCodeTask); } @Override public void login(String userName, String pwd, String verifyCode) { getView().showLoading(); mLoginTask.setUserName(userName); mLoginTask.setPwd(pwd); mLoginTask.setVerifyCode(verifyCode); mLoginTask.setCallback(new UseCase.Callback() { @Override public void success(LoginResponse loginResponse) { getView().toast("login success!"); } @Override public void fail() { getView().toast("login fail!"); } }); getThreadExecutor().execute(mLoginTask); } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/login/domain/GetVerifyCodeTask.java ================================================ package com.wjj.easy.easyandroidHelper.module.login.domain; import com.wjj.easy.easyandroid.http.Http; import com.wjj.easy.easyandroid.mvp.domain.usecases.AbstractUseCase; import com.wjj.easy.easyandroidHelper.common.net.AppHttp; import com.wjj.easy.easyandroidHelper.model.base.BaseStatus; import com.wjj.easy.easyandroidHelper.utils.SecretUtils; import javax.inject.Inject; /** * 获取验证码任务 * * @author wujiajun */ public class GetVerifyCodeTask extends AbstractUseCase { String publicKey = "11"; String userName; String pwd; @Inject AppHttp appHttp; @Inject public GetVerifyCodeTask() { } @Override public void run() { appHttp.getVerifyCode(userName, SecretUtils.encryptByPublicKey(pwd, publicKey), new Http.HttpCallback() { @Override public void onResponse(BaseStatus baseStatus) { getCallback().success(baseStatus); } @Override public void onFailure(Throwable t) { getCallback().fail(); } }); } public void setUserName(String userName) { this.userName = userName; } public void setPwd(String pwd) { this.pwd = pwd; } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/login/domain/LoginTask.java ================================================ package com.wjj.easy.easyandroidHelper.module.login.domain; import com.wjj.easy.easyandroid.http.Http; import com.wjj.easy.easyandroid.mvp.domain.usecases.AbstractUseCase; import com.wjj.easy.easyandroidHelper.common.net.AppHttp; import com.wjj.easy.easyandroidHelper.model.LoginResponse; import com.wjj.easy.easyandroidHelper.utils.SecretUtils; import javax.inject.Inject; /** * 登录任务 * * @author wujiajun */ public class LoginTask extends AbstractUseCase { String publicKey = "11"; String userName; String pwd; String verifyCode; @Inject AppHttp appHttp; @Inject public LoginTask() { } @Override public void run() { appHttp.login(userName, SecretUtils.encryptByPublicKey(pwd, publicKey), verifyCode, new Http.HttpCallback() { @Override public void onResponse(LoginResponse baseStatus) { getCallback().success(baseStatus); } @Override public void onFailure(Throwable t) { getCallback().fail(); } }); } public void setUserName(String userName) { this.userName = userName; } public void setPwd(String pwd) { this.pwd = pwd; } public void setVerifyCode(String verifyCode) { this.verifyCode = verifyCode; } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/main/HomeContract.java ================================================ package com.wjj.easy.easyandroidHelper.module.main; import com.wjj.easy.easyandroid.mvp.EasyBasePresenter; import com.wjj.easy.easyandroidHelper.common.base.BaseView; import com.wjj.easy.easyandroidHelper.model.ListInfo; /** * Created by wujiajun on 17/4/6. */ public interface HomeContract { interface View extends BaseView { void showList(ListInfo list); } interface Presenter extends EasyBasePresenter { void getList(int index); } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/main/HomeFragment.java ================================================ package com.wjj.easy.easyandroidHelper.module.main; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import com.wjj.easy.easyandroidHelper.R; import com.wjj.easy.easyandroidHelper.common.base.BaseFragment; import com.wjj.easy.easyandroidHelper.model.ListInfo; import com.wjj.easy.easyandroidHelper.module.main.adapter.HomeAdapter; import butterknife.BindView; /** * 首页 * Created by wujiajun on 17/4/12. */ public class HomeFragment extends BaseFragment implements HomeContract.View { @BindView(R.id.rv_list) RecyclerView rvList; HomeAdapter homeAdapter; @Override protected int getContentView() { return R.layout.fragment_home; } @Override protected void initInject() { getFragmentComponent().inject(this); } @Override protected void initEventAndData() { showLoading(); homeAdapter = new HomeAdapter(R.layout.home_list_item); rvList.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); // 设置Item添加和移除的动画 rvList.setItemAnimator(new DefaultItemAnimator()); rvList.setAdapter(homeAdapter); rvList.postDelayed(new Runnable() { @Override public void run() { getPresenter().getList(1); } }, 1000); } @Override public void showList(ListInfo list) { Log.e("HomeFragment", "list : " + list.toString()); homeAdapter.setNewData(list.getData()); hiddenLoading(); } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/main/HomePresenter.java ================================================ package com.wjj.easy.easyandroidHelper.module.main; import com.wjj.easy.easyandroid.mvp.domain.executor.Executor; import com.wjj.easy.easyandroid.mvp.domain.usecases.UseCase; import com.wjj.easy.easyandroidHelper.common.base.BasePresenter; import com.wjj.easy.easyandroidHelper.model.ListInfo; import com.wjj.easy.easyandroidHelper.module.main.domain.GetListTask; import javax.inject.Inject; /** * Created by wujiajun on 17/4/6. */ public class HomePresenter extends BasePresenter implements HomeContract.Presenter { @Inject GetListTask getListTask; @Inject public HomePresenter() { } @Override public void getList(int page) { getListTask.setIndex(page); getListTask.setCallback(new UseCase.Callback() { @Override public void success(ListInfo list) { getView().showList(list); } @Override public void fail() { getView().hiddenLoading(); } }); execute(getListTask); } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/main/MainActivity.java ================================================ package com.wjj.easy.easyandroidHelper.module.main; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewPager; import android.support.v7.widget.Toolbar; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import com.wjj.easy.easyandroidHelper.R; import com.wjj.easy.easyandroidHelper.common.base.SimpleActivity; import butterknife.BindView; import butterknife.ButterKnife; /** * 主页 * * @author wujiajun */ public class MainActivity extends SimpleActivity { private Fragment[] fragments = new Fragment[]{new HomeFragment(), new MyFragment()}; @BindView(R.id.activity_main) RelativeLayout activityMain; @BindView(R.id.view_pager) ViewPager viewPager; @BindView(R.id.tab_layout) TabLayout tabLayout; @BindView(R.id.tool_bar) Toolbar toolbar; @Override protected void initEventAndData() { toolbar.setLogo(R.mipmap.icon_app); toolbar.setTitle(R.string.app_name); toolbar.setTitleTextColor(ContextCompat.getColor(this, R.color.white)); toolbar.setTitleMarginStart(getResources().getDimensionPixelSize(R.dimen.padding_size_30)); setSupportActionBar(toolbar); viewPager.setAdapter(new MainPageAdapter(getSupportFragmentManager())); tabLayout.setupWithViewPager(viewPager); tabLayout.getTabAt(0).setCustomView(R.layout.view_main_tab); tabLayout.getTabAt(1).setCustomView(R.layout.view_main_tab); selectTab(tabLayout.getTabAt(0)); unSelectTab(tabLayout.getTabAt(1)); tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { selectTab(tab); } @Override public void onTabUnselected(TabLayout.Tab tab) { unSelectTab(tab); } @Override public void onTabReselected(TabLayout.Tab tab) { selectTab(tab); } }); viewPager.setCurrentItem(0); } private void selectTab(TabLayout.Tab tab) { ImageView icon = ButterKnife.findById(tab.getCustomView(), R.id.tab_icon_iv); TextView title = ButterKnife.findById(tab.getCustomView(), R.id.tab_title_tv); if (tab.getPosition() == 0) { icon.setImageResource(R.mipmap.tab_home_selected); title.setText(R.string.home_tab); } else { icon.setImageResource(R.mipmap.tab_user_selected); title.setText(R.string.my_tab); } title.setTextColor(ContextCompat.getColor(this, R.color.black)); } private void unSelectTab(TabLayout.Tab tab) { ImageView icon = ButterKnife.findById(tab.getCustomView(), R.id.tab_icon_iv); TextView title = ButterKnife.findById(tab.getCustomView(), R.id.tab_title_tv); if (tab.getPosition() == 0) { icon.setImageResource(R.mipmap.tab_home_unselected); title.setText(R.string.home_tab); } else { icon.setImageResource(R.mipmap.tab_user_unselected); title.setText(R.string.my_tab); } title.setTextColor(ContextCompat.getColor(this, R.color.grey)); } @Override protected int getContentView() { return R.layout.activity_main; } private class MainPageAdapter extends FragmentPagerAdapter { public MainPageAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return fragments[position]; } @Override public int getCount() { return fragments.length; } } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/main/MyContract.java ================================================ package com.wjj.easy.easyandroidHelper.module.main; import com.wjj.easy.easyandroid.mvp.EasyBasePresenter; import com.wjj.easy.easyandroidHelper.common.base.BaseView; /** * Created by wujiajun on 17/4/6. */ public interface MyContract { interface View extends BaseView { } interface Presenter extends EasyBasePresenter { } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/main/MyFragment.java ================================================ package com.wjj.easy.easyandroidHelper.module.main; import android.net.Uri; import com.facebook.drawee.view.SimpleDraweeView; import com.wjj.easy.easyandroidHelper.R; import com.wjj.easy.easyandroidHelper.common.base.BaseFragment; import butterknife.BindView; /** * 我的 * Created by wujiajun on 17/4/12. */ public class MyFragment extends BaseFragment implements MyContract.View { @BindView(R.id.my_image_view) SimpleDraweeView myImageView; @Override protected int getContentView() { return R.layout.fragment_my; } @Override protected void initInject() { getFragmentComponent().inject(this); } @Override protected void initEventAndData() { Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/logo.png"); myImageView.setImageURI(uri); } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/main/MyPresenter.java ================================================ package com.wjj.easy.easyandroidHelper.module.main; import com.wjj.easy.easyandroidHelper.common.base.BasePresenter; import javax.inject.Inject; /** * Created by wujiajun on 17/4/6. */ public class MyPresenter extends BasePresenter implements MyContract.Presenter { @Inject public MyPresenter() { } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/main/adapter/HomeAdapter.java ================================================ package com.wjj.easy.easyandroidHelper.module.main.adapter; import android.graphics.drawable.Drawable; import android.view.View; import android.widget.TextView; import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.BaseViewHolder; import com.facebook.drawee.view.SimpleDraweeView; import com.wjj.easy.easyandroidHelper.R; import com.wjj.easy.easyandroidHelper.model.ListInfo; import java.text.NumberFormat; import java.util.List; import javax.inject.Inject; /** * Created by ljw on 2017/4/14. */ public class HomeAdapter extends BaseQuickAdapter { Drawable right_vip; Drawable right_free; public HomeAdapter(int layoutResId, List data) { super(layoutResId, data); } @Inject public HomeAdapter(int layoutResId) { super(layoutResId); } @Override protected void convert(BaseViewHolder holder, ListInfo.DataBean info) { if(info==null) return; SimpleDraweeView ivIcon = holder.getView(R.id.dv_img); ivIcon.setImageURI(info.getImageUrl()); holder.setText(R.id.tv_date, info.getDoTime()); holder.setText(R.id.tv_city, info.getCity()); holder.setText(R.id.tv_label, info.getTaskTypeName()); TextView tv_name = holder.getView(R.id.tv_name); TextView tv_member_price = holder.getView(R.id.tv_member_price); if(right_vip==null) { right_vip = mContext.getResources().getDrawable(R.mipmap.icon_vip_all); right_vip.setBounds(0, 0, right_vip.getMinimumWidth(), right_vip.getMinimumHeight()); } if(right_free == null){ right_free = mContext.getResources().getDrawable(R.mipmap.ic_free); right_free.setBounds(0, 0, right_free.getMinimumWidth(), right_free.getMinimumHeight()); } tv_name.setText(info.getTitle()); if (info.getOnlyVip() == 1){ // 会员专享活动 tv_name.setCompoundDrawables(null, null, right_vip, null); tv_member_price.setVisibility(View.GONE); if(info.isIsFree()){ // 免费活动 holder.setText(R.id.tv_price,"免费报名"); holder.getView(R.id.tv_price_y).setVisibility(View.GONE); }else { // 非免费 holder.getView(R.id.tv_price_y).setVisibility(View.VISIBLE); holder.setText(R.id.tv_price, Integer.toString(info.getHasMemberAmt())); } }else if(info.isIsFree()){ // 免费活动 tv_name.setCompoundDrawables(null,null,right_free,null); tv_member_price.setVisibility(View.GONE); holder.setText(R.id.tv_price,"免费报名"); tv_member_price.setVisibility(View.GONE); holder.getView(R.id.tv_price_y).setVisibility(View.GONE); }else { // 普通活动(不是免费活动,也不是会员专享活动) holder.setText(R.id.tv_price,info.getAmt()); holder.getView(R.id.tv_price_y).setVisibility(View.VISIBLE); tv_name.setCompoundDrawables(null,null,null,null); if(info.getHasMemberAmt() == 1) { tv_member_price.setVisibility(View.VISIBLE); tv_member_price.setText(String.format("会员价:%s", NumberFormat.getInstance().format(info.getMemberAmt()))); } } } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/module/main/domain/GetListTask.java ================================================ package com.wjj.easy.easyandroidHelper.module.main.domain; import com.wjj.easy.easyandroid.http.Http; import com.wjj.easy.easyandroid.mvp.domain.usecases.AbstractUseCase; import com.wjj.easy.easyandroidHelper.common.net.AppHttp; import com.wjj.easy.easyandroidHelper.model.ListInfo; import javax.inject.Inject; /** * Created by ljw on 2017/4/13. */ public class GetListTask extends AbstractUseCase{ int index; @Inject AppHttp appHttp; @Inject public GetListTask() { } @Override public void run() { appHttp.getList(index, new Http.HttpCallback() { @Override public void onResponse(ListInfo listInfos) { getCallback().success(listInfos); } @Override public void onFailure(Throwable t) { getCallback().fail(); } }); } public void setIndex(int index) { this.index = index; } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/utils/SecretUtils.java ================================================ package com.wjj.easy.easyandroidHelper.utils; import android.util.Base64; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.List; import javax.crypto.Cipher; /** * 加解密 * * @author zhaotun */ public class SecretUtils { public enum SecroType { TYPE_RSA; } public static final String CRYPTO_TYPE_RSA = "RSA";// 非对称加密密钥算法 public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//加密填充方式 RSA/ECB/PKCS1Padding RSA/ECB/NoPadding public static final String CRYPTO_TYPE_DES = "DES"; public static final String CRYPTO_TYPE_DES_ALGORITHM = "DES/CBC/PKCS5Padding"; private static final byte[] DESIV = "12345678".getBytes(); private static final String CHARSET_UTF8 = "UTF-8"; public static final int DEFAULT_KEY_SIZE = 2048;//秘钥默认长度 public static final byte[] DEFAULT_SPLIT = "#PART#".getBytes(); // 当要加密的内容超过bufferSize,则采用partSplit进行分块加密 public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;// 当前秘钥支持加密的最大字节数 private PublicKey keyPublic; private Cipher cipher; private SecretUtils() { } public static String encryptByPublicKey(String data, String pubKey) { try { // SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); byte[] buffer = Base64.decode(pubKey, Base64.DEFAULT); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance(CRYPTO_TYPE_RSA); PublicKey publicKey = keyFactory.generatePublic(keySpec); // 加密数据 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); cp.init(Cipher.ENCRYPT_MODE, publicKey); byte[] output = cp.doFinal(data.getBytes(CHARSET_UTF8)); // 必须先encode成 byte[],再转成encodeToString,否则服务器解密会失败 byte[] encode = Base64.encode(output, Base64.DEFAULT); String aa=new String(encode); return aa;//Base64.encodeToString(encode, Base64.DEFAULT); } catch (Exception e) { e.printStackTrace(); return data; } } /** * TODO:有待验证 * * @param data * @param pubKey * @return */ public static String decryptByPublicKey(String data, String pubKey) { try { byte[] buffer = Base64.decode(pubKey, Base64.DEFAULT); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); KeyFactory kf = KeyFactory.getInstance(CRYPTO_TYPE_RSA); PublicKey publicKey = kf.generatePublic(keySpec); // 数据解密 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); cipher.init(Cipher.DECRYPT_MODE, publicKey); byte[] output = cipher.doFinal(data.getBytes(CHARSET_UTF8)); // 必须先encode成 byte[],再转成encodeToString,否则服务器解密会失败 byte[] encode = Base64.encode(output, Base64.DEFAULT); return new String(encode); } catch (Exception e) { e.printStackTrace(); return data; } } /** * 用公钥对字符串进行加密 * * @param data 原文 */ public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) { try { // 得到公钥 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); KeyFactory kf = KeyFactory.getInstance(CRYPTO_TYPE_RSA); PublicKey keyPublic = kf.generatePublic(keySpec); // 加密数据 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); cp.init(Cipher.ENCRYPT_MODE, keyPublic); return cp.doFinal(data); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 私钥加密 * * @param data 待加密数据 * @param privateKey 密钥 * @return byte[] 加密数据 */ public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception { try { // 得到私钥 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory kf = KeyFactory.getInstance(CRYPTO_TYPE_RSA); PrivateKey keyPrivate = kf.generatePrivate(keySpec); // 数据加密 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); cipher.init(Cipher.ENCRYPT_MODE, keyPrivate); return cipher.doFinal(data); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 公钥解密 * * @param data 待解密数据 * @param publicKey 密钥 * @return byte[] 解密数据 */ public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { // 得到公钥 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); KeyFactory kf = KeyFactory.getInstance(CRYPTO_TYPE_RSA); PublicKey keyPublic = kf.generatePublic(keySpec); // 数据解密 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); cipher.init(Cipher.DECRYPT_MODE, keyPublic); return cipher.doFinal(data); } /** * 使用私钥进行解密 */ public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception { // 得到私钥 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory kf = KeyFactory.getInstance(CRYPTO_TYPE_RSA); PrivateKey keyPrivate = kf.generatePrivate(keySpec); // 解密数据 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); cp.init(Cipher.DECRYPT_MODE, keyPrivate); byte[] arr = cp.doFinal(encrypted); return arr; } /** * 用公钥对字符串进行分段加密 */ public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) throws Exception { int dataLen = data.length; if (dataLen <= DEFAULT_BUFFERSIZE) { return encryptByPublicKey(data, publicKey); } List allBytes = new ArrayList(2048); int bufIndex = 0; int subDataLoop = 0; byte[] buf = new byte[DEFAULT_BUFFERSIZE]; for (int i = 0; i < dataLen; i++) { buf[bufIndex] = data[i]; if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { subDataLoop++; if (subDataLoop != 1) { for (byte b : DEFAULT_SPLIT) { allBytes.add(b); } } byte[] encryptBytes = encryptByPublicKey(buf, publicKey); for (byte b : encryptBytes) { allBytes.add(b); } bufIndex = 0; if (i == dataLen - 1) { buf = null; } else { buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)]; } } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } /** * 分段加密 * * @param data 要加密的原始数据 * @param privateKey 秘钥 */ public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) throws Exception { int dataLen = data.length; if (dataLen <= DEFAULT_BUFFERSIZE) { return encryptByPrivateKey(data, privateKey); } List allBytes = new ArrayList(2048); int bufIndex = 0; int subDataLoop = 0; byte[] buf = new byte[DEFAULT_BUFFERSIZE]; for (int i = 0; i < dataLen; i++) { buf[bufIndex] = data[i]; if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { subDataLoop++; if (subDataLoop != 1) { for (byte b : DEFAULT_SPLIT) { allBytes.add(b); } } byte[] encryptBytes = encryptByPrivateKey(buf, privateKey); for (byte b : encryptBytes) { allBytes.add(b); } bufIndex = 0; if (i == dataLen - 1) { buf = null; } else { buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)]; } } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } /** * 公钥分段解密 * * @param encrypted 待解密数据 * @param publicKey 密钥 */ public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) throws Exception { int splitLen = DEFAULT_SPLIT.length; if (splitLen <= 0) { return decryptByPublicKey(encrypted, publicKey); } int dataLen = encrypted.length; List allBytes = new ArrayList(1024); int latestStartIndex = 0; for (int i = 0; i < dataLen; i++) { byte bt = encrypted[i]; boolean isMatchSplit = false; if (i == dataLen - 1) { // 到data的最后了 byte[] part = new byte[dataLen - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPublicKey(part, publicKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } else if (bt == DEFAULT_SPLIT[0]) { // 这个是以split[0]开头 if (splitLen > 1) { if (i + splitLen < dataLen) { // 没有超出data的范围 for (int j = 1; j < splitLen; j++) { if (DEFAULT_SPLIT[j] != encrypted[i + j]) { break; } if (j == splitLen - 1) { // 验证到split的最后一位,都没有break,则表明已经确认是split段 isMatchSplit = true; } } } } else { // split只有一位,则已经匹配了 isMatchSplit = true; } } if (isMatchSplit) { byte[] part = new byte[i - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPublicKey(part, publicKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } /** * 使用私钥分段解密 */ public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey) throws Exception { int splitLen = DEFAULT_SPLIT.length; if (splitLen <= 0) { return decryptByPrivateKey(encrypted, privateKey); } int dataLen = encrypted.length; List allBytes = new ArrayList(1024); int latestStartIndex = 0; for (int i = 0; i < dataLen; i++) { byte bt = encrypted[i]; boolean isMatchSplit = false; if (i == dataLen - 1) { // 到data的最后了 byte[] part = new byte[dataLen - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPrivateKey(part, privateKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } else if (bt == DEFAULT_SPLIT[0]) { // 这个是以split[0]开头 if (splitLen > 1) { if (i + splitLen < dataLen) { // 没有超出data的范围 for (int j = 1; j < splitLen; j++) { if (DEFAULT_SPLIT[j] != encrypted[i + j]) { break; } if (j == splitLen - 1) { // 验证到split的最后一位,都没有break,则表明已经确认是split段 isMatchSplit = true; } } } } else { // split只有一位,则已经匹配了 isMatchSplit = true; } } if (isMatchSplit) { byte[] part = new byte[i - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPrivateKey(part, privateKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/widget/dialog/BaseDialog.java ================================================ package com.wjj.easy.easyandroidHelper.widget.dialog; import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.Gravity; import android.view.Window; import android.view.WindowManager.LayoutParams; import com.wjj.easy.easyandroidHelper.R; import butterknife.ButterKnife; /** * Created by zhaotun */ public abstract class BaseDialog extends Dialog { protected float mDimAmount = 0.6f; protected float mWidthScale = 0.9f; protected int gravity = Gravity.CENTER_VERTICAL; protected int animId = -1; protected int x = 0; protected int y = 0; protected int h = LayoutParams.WRAP_CONTENT; protected boolean mShouldSetWindow = true; public BaseDialog(Context context) { super(context, R.style.dialog_custom_roll_up_down); } public BaseDialog(Context context, int theme) { super(context, theme); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(getContentView()); ButterKnife.bind(this); init(); if (mShouldSetWindow) { setWindow(x, y); } } protected void setWindow(int x, int y) { Window dialogWindow = getWindow(); LayoutParams lp = dialogWindow.getAttributes(); DisplayMetrics d = getContext().getResources().getDisplayMetrics(); // 获取屏幕宽、高用 lp.width = (int) (d.widthPixels * mWidthScale); lp.height = h; lp.x = x; lp.y = y; lp.gravity = gravity; lp.dimAmount = mDimAmount; dialogWindow.addFlags(LayoutParams.FLAG_DIM_BEHIND); if (animId != -1) { dialogWindow.setWindowAnimations(animId); } } public void shouldSetWindow(boolean shouldSetWindow) { this.mShouldSetWindow = shouldSetWindow; } protected abstract int getContentView(); protected abstract void init(); } ================================================ FILE: app/src/main/java/com/wjj/easy/easyandroidHelper/widget/dialog/DialogLoading.java ================================================ package com.wjj.easy.easyandroidHelper.widget.dialog; import android.content.Context; import android.widget.TextView; import com.wjj.easy.easyandroidHelper.R; import butterknife.BindView; /** * Created by zhaotun on 2017/2/21. */ public class DialogLoading extends BaseDialog { @BindView(R.id.tv_loading_text) TextView tvText; public DialogLoading(Context context) { this(context, false); } public DialogLoading(Context context, boolean shouldSetWindow) { super(context, R.style.customDialog_loading); shouldSetWindow(shouldSetWindow); setCanceledOnTouchOutside(false); setCancelable(true); } @Override protected int getContentView() { return R.layout.dialog_loading; } @Override protected void init() { } public void setText(String text) { if (tvText != null) { tvText.setText(text); } } } ================================================ FILE: app/src/main/res/anim/roll_down.xml ================================================ ================================================ FILE: app/src/main/res/anim/roll_up.xml ================================================ ================================================ FILE: app/src/main/res/anim/slide_in_bottom.xml ================================================ ================================================ FILE: app/src/main/res/anim/slide_out_bottom.xml ================================================ ================================================ FILE: app/src/main/res/drawable/bg_color_white_corners_10.xml ================================================ ================================================ FILE: app/src/main/res/layout/activity_login.xml ================================================ ================================================ FILE: app/src/main/res/layout/activity_main.xml ================================================ ================================================ FILE: app/src/main/res/layout/dialog_loading.xml ================================================ ================================================ FILE: app/src/main/res/layout/fragment_home.xml ================================================ ================================================ FILE: app/src/main/res/layout/fragment_my.xml ================================================ ================================================ FILE: app/src/main/res/layout/home_list_item.xml ================================================ ================================================ FILE: app/src/main/res/layout/view_main_tab.xml ================================================ ================================================ FILE: app/src/main/res/values/colors.xml ================================================ #00bcd4 #00bcd4 #ff4081 #ffffff #9e9e9e #000000 #f0f3f8 #90909b ================================================ FILE: app/src/main/res/values/dimens.xml ================================================ 16dp 16dp 8sp 9sp 10sp 11sp 12sp 13sp 14sp 15sp 16sp 17sp 18sp 20sp 22sp 23sp 24sp 25sp 30sp 34sp 35sp 39sp 40sp 45sp 50sp 72sp 100sp 145sp 150sp 1dp 1px 2dp 3dp 4dp 5dp 6dp 7dp 8dp 9dp 10dp 11dp 12dp 13dp 14dp 15dp 16dp 17dp 18dp 19dp 20dp 21dp 22dp 23dp 24dp 25dp 26dp 27dp 28dp 29dp 30dp 32dp 33dp 35dp 36dp 39dp 40dp 42dp 44dp 45dp 46dp 47dp 48dp 50dp 51dp 55dp 56dp 58dp 60dp 63dp 65dp 68dp 70dp 72dp 73dp 75dp 78dp 80dp 85dp 88dp 90dp 95dp 98dp 100dp 107dp 110dp 112dp 135dp 140dp 148dp 150dp 151dp 160dp 165dp 170dp 190dp 200dp 210dp 215dp 220dp 225dp 228dp 250dp 260dp 275dp 300dp 332dp 350dp 400dp 500dp 540dp ================================================ FILE: app/src/main/res/values/strings.xml ================================================ EasyAndroid 首页 我的 加载中... ================================================ FILE: app/src/main/res/values/styles.xml ================================================ ================================================ FILE: app/src/main/res/values-v21/styles.xml ================================================ ================================================ FILE: app/src/main/res/values-w820dp/dimens.xml ================================================ 64dp ================================================ FILE: build.gradle ================================================ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:2.2.3' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4' classpath 'com.jakewharton:butterknife-gradle-plugin:8.5.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' } } allprojects { repositories { jcenter() maven { url "https://jitpack.io" } mavenCentral() } } task clean(type: Delete) { delete rootProject.buildDir } // Define versions in a single place ext { // Sdk and tools minSdkVersion = 19 targetSdkVersion = 25 compileSdkVersion = 25 buildToolsVersion = '25.0.2' applicationId = "com.wjj.easy.easyandroidHelper" // App dependencies supportLibraryVersion = '25.2.0' retrofit2 = '2.2.0' okhttp3 = '3.4.1' persistentCookieJar = 'v1.0.1' fresco = '1.2.0' dagger2 = '2.0.2' annotation = '10.0-b28' butterknife = '8.5.1' utilcode = '1.3.7' orhanobutLogger = '1.15' baseRecyclerViewAdapterHelper = '2.9.9' } ================================================ FILE: easyandroid/.gitignore ================================================ /build ================================================ FILE: easyandroid/build.gradle ================================================ apply plugin: 'com.android.library' apply plugin: 'com.neenbedankt.android-apt' android { compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) //support lib compile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion" compile "com.android.support:design:$rootProject.supportLibraryVersion" //retrofit2 compile "com.squareup.retrofit2:retrofit:$rootProject.retrofit2" compile "com.squareup.retrofit2:converter-gson:$rootProject.retrofit2" //okhttp3 compile "com.squareup.okhttp3:okhttp:$rootProject.okhttp3" compile "com.squareup.okhttp3:logging-interceptor:$rootProject.okhttp3" //persistentCookieJar compile "com.github.franmontiel:PersistentCookieJar:$rootProject.persistentCookieJar" //fresco compile "com.facebook.fresco:fresco:$rootProject.fresco" compile "com.facebook.fresco:imagepipeline-okhttp3:$rootProject.fresco" //dagger2 apt "com.google.dagger:dagger-compiler:$rootProject.dagger2" compile "com.google.dagger:dagger:$rootProject.dagger2" compile "com.google.dagger:dagger-compiler:$rootProject.dagger2" compile "org.glassfish:javax.annotation:$rootProject.annotation" //recyclerViewAdapter compile "com.github.CymChad:BaseRecyclerViewAdapterHelper:$rootProject.baseRecyclerViewAdapterHelper" //utilcode compile "com.blankj:utilcode:$rootProject.utilcode" //logger compile "com.orhanobut:logger:$rootProject.orhanobutLogger" } ext { bintrayRepo = 'maven'////bintray上的仓库名,一般为maven bintrayName = 'EasyAndroid'//bintray上的项目名 publishedGroupId = 'com.wjj.easy'//JCenter的GroupId artifact = 'easyandroid'//JCenter的ArtifactId siteUrl = 'https://github.com/wu928320442/EasyAndroid.git' gitUrl = 'https://github.com/wu928320442/EasyAndroid.git' libraryVersion = '1.0.0'//版本号 libraryName = 'easyandroid'//项目名字,没什么用 libraryDescription = 'A lib for Android'//项目描述,没什么用 //开发者信息 developerId = 'juju' developerName = 'juju' developerEmail = 'wujiajun311@gmail.com' //以上所有信息自行修改,以下不变 licenseName = 'The Apache Software License, Version 2.0' licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' allLicenses = ["Apache-2.0"] } apply from:'https://cdn.rawgit.com/Jude95/JCenter/master/install.gradle' apply from:'https://cdn.rawgit.com/Jude95/JCenter/master/bintray.gradle' ================================================ FILE: easyandroid/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /Users/wujiajun/Library/Android/sdk/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} #retrofit2 -dontwarn retrofit2.** -keep class retrofit2.** { *; } -keepattributes Signature -keepattributes Exceptions #utilcode -keep class com.blankj.utilcode.** { *; } -keepclassmembers class com.blankj.utilcode.** { *; } -dontwarn com.blankj.utilcode.** ================================================ FILE: easyandroid/src/main/AndroidManifest.xml ================================================ ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/http/Http.java ================================================ package com.wjj.easy.easyandroid.http; import com.franmontiel.persistentcookiejar.ClearableCookieJar; import com.wjj.easy.easyandroid.BuildConfig; import java.util.ArrayList; import java.util.concurrent.TimeUnit; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; /** * HTTP网络配置 * 1.OkHttpClient配置 * 2.Retrofit配置 * 3.Builder构建初始化数据 * Created by wujiajun on 17/4/5. */ public class Http { private static final boolean DEBUG = /*BuildConfig.DEBUG*/true; private HttpBuilder mBuilder; private OkHttpClient mClient; private Retrofit mRetrofit; public Http(HttpBuilder builder) { mBuilder = builder; configOKHttp(); configRetrofit(); } private void configOKHttp() { HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder builder = new OkHttpClient.Builder(); if (DEBUG) { builder.addInterceptor(loggingInterceptor); } for (Interceptor interceptor : mBuilder.interceptors) { builder.addInterceptor(interceptor); } mClient = builder.retryOnConnectionFailure(true) .connectTimeout(mBuilder.timeout, TimeUnit.SECONDS) .cookieJar(mBuilder.cookieJar).build(); } private void configRetrofit() { mRetrofit = new Retrofit.Builder() .baseUrl(mBuilder.baseUrl) .client(mClient) .addConverterFactory(GsonConverterFactory.create()) .build(); } /** * HTTP响应回调 * * @param 响应Bean */ public interface HttpCallback { /** * 成功响应 * * @param t 响应Bean */ void onResponse(T t); /** * 失败响应 * * @param t 异常 */ void onFailure(Throwable t); } /** * Retrofit2 Callback缺省实现 * 转换业务接口返回数据 * * @param */ public static class CallbackDefault implements Callback { HttpCallback httpCallback; public CallbackDefault(HttpCallback httpCallback) { this.httpCallback = httpCallback; } @Override public void onResponse(Call call, Response response) { httpCallback.onResponse(response.body()); } @Override public void onFailure(Call call, Throwable t) { httpCallback.onFailure(t); } } /** * HTTP 构建类 */ public static final class HttpBuilder { private String baseUrl; private ClearableCookieJar cookieJar; private long timeout; private ArrayList interceptors = new ArrayList(); public HttpBuilder setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; return this; } public HttpBuilder setCookieJar(ClearableCookieJar cookieJar) { this.cookieJar = cookieJar; return this; } public HttpBuilder setTimeout(long timeout) { this.timeout = timeout; return this; } public HttpBuilder addInterceptor(Interceptor interceptor) { interceptors.add(interceptor); return this; } public Http build() { return new Http(this); } } public Retrofit getRetrofit() { return mRetrofit; } public OkHttpClient getClient() { return mClient; } } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/EasyBasePresenter.java ================================================ package com.wjj.easy.easyandroid.mvp; /** * MVP Presenter层基类 * 适用范围:在Activity使用 * Created by wujiajun on 17/4/6. */ public interface EasyBasePresenter { void start(); void attachView(V view); } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/EasyBasePresenterFrg.java ================================================ package com.wjj.easy.easyandroid.mvp; /** * MVP Presenter层基类 * 适用范围:Fragment中使用 * Created by wujiajun on 17/4/13. */ public interface EasyBasePresenterFrg extends EasyBasePresenter { void setupListeners(); } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/EasyBaseView.java ================================================ package com.wjj.easy.easyandroid.mvp; /** * MVP View层基类 * 适用范围:在Activity使用 * Created by wujiajun on 17/4/6. */ public interface EasyBaseView { } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/EasyBaseViewFrg.java ================================================ package com.wjj.easy.easyandroid.mvp; /** * MVP View层基类 * 适用范围:在Fragment使用 * Created by wujiajun on 17/4/13. */ public interface EasyBaseViewFrg extends EasyBaseView { // void setPresenter(T presenter); } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/di/components/ActivityComponent.java ================================================ package com.wjj.easy.easyandroid.mvp.di.components; import android.app.Activity; import com.wjj.easy.easyandroid.mvp.di.modules.ActivityModule; import com.wjj.easy.easyandroid.mvp.di.scopes.ActivityScope; import dagger.Component; /** * Activity注射组件 * * @author wujiajun */ @ActivityScope @Component(dependencies = AppComponent.class, modules = {ActivityModule.class}) public interface ActivityComponent { /** * 获取注入的Activity * * @return Activity */ Activity getActivity(); } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/di/components/AppComponent.java ================================================ package com.wjj.easy.easyandroid.mvp.di.components; import android.content.Context; import com.wjj.easy.easyandroid.mvp.di.modules.AppModule; import com.wjj.easy.easyandroid.mvp.di.scopes.ApplicationScope; import javax.inject.Singleton; import dagger.Component; /** * Application注射组件 * * @author wujiajun */ @ApplicationScope @Component(modules = {AppModule.class}) public interface AppComponent { Context getContext(); } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/di/components/FragmentComponent.java ================================================ package com.wjj.easy.easyandroid.mvp.di.components; import android.app.Activity; import android.support.v4.app.Fragment; import com.wjj.easy.easyandroid.mvp.di.modules.FragmentModule; import com.wjj.easy.easyandroid.mvp.di.scopes.FragmentScope; import dagger.Component; /** * Fragment注射组件 * * @author wujiajun */ @FragmentScope @Component(modules = FragmentModule.class) public interface FragmentComponent { // /** // * 获取注入的Fragment // * // * @return // */ // Fragment getFragment(); Activity getActivity(); } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/di/modules/ActivityModule.java ================================================ package com.wjj.easy.easyandroid.mvp.di.modules; import android.app.Activity; import com.wjj.easy.easyandroid.mvp.di.scopes.ActivityScope; import dagger.Module; import dagger.Provides; /** * Activity注入提供者Module * * @author wujiajun */ @Module public class ActivityModule { private final Activity activity; public ActivityModule(Activity activity) { this.activity = activity; } /** * 提供注入Activity * 注意ActivityScope的作用 所有依赖于ActivityScope的组件都依赖于Activity的生命周期 * * @return Activity */ @Provides @ActivityScope public Activity provideActivity() { return activity; } } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/di/modules/AppModule.java ================================================ package com.wjj.easy.easyandroid.mvp.di.modules; import android.content.Context; import com.wjj.easy.easyandroid.mvp.di.scopes.ApplicationScope; import javax.inject.Singleton; import dagger.Module; import dagger.Provides; /** * Application注入提供者Module * * @author wujiajun */ @Module public class AppModule { Context context; public AppModule(Context context) { this.context = context; } @ApplicationScope @Provides public Context provideContext() { return context; } } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/di/modules/FragmentModule.java ================================================ package com.wjj.easy.easyandroid.mvp.di.modules; import android.app.Activity; import android.support.v4.app.Fragment; import com.wjj.easy.easyandroid.mvp.di.scopes.FragmentScope; import dagger.Module; import dagger.Provides; /** * Activity注入提供者Module * * @author wujiajun */ @Module public class FragmentModule { private Fragment fragment; public FragmentModule(Fragment fragment) { this.fragment = fragment; } // /** // * 提供注入Fragment // * 注意FragmentScope的作用 所有依赖于FragmentScope的组件都依赖于Fragment的生命周期 // * // * @return Activity // */ // @FragmentScope // @Provides // Fragment provideFragment() { // return fragment; // } @Provides @FragmentScope public Activity provideActivity() { return fragment.getActivity(); } } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/di/scopes/ActivityScope.java ================================================ package com.wjj.easy.easyandroid.mvp.di.scopes; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Scope; /** * Activity域注解 * 目的是管理域内对象的生命周期 * * @author wujiajun */ @Scope @Retention(RetentionPolicy.RUNTIME) public @interface ActivityScope { } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/di/scopes/ApplicationScope.java ================================================ package com.wjj.easy.easyandroid.mvp.di.scopes; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Scope; /** * Application域注解 * 目的是管理域内对象的生命周期 * * @author wujiajun */ @Scope @Retention(RetentionPolicy.RUNTIME) public @interface ApplicationScope { } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/di/scopes/FragmentScope.java ================================================ package com.wjj.easy.easyandroid.mvp.di.scopes; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Scope; /** * Fragment域注解 * 目的是管理域内对象的生命周期 * * @author wujiajun */ @Scope @Retention(RetentionPolicy.RUNTIME) public @interface FragmentScope { } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/domain/executor/Executor.java ================================================ package com.wjj.easy.easyandroid.mvp.domain.executor; import com.wjj.easy.easyandroid.mvp.domain.usecases.AbstractUseCase; /** * Executor抽象接口 * 目的是专门在后台执行任务 * * @author wujiajun */ public interface Executor { /** * 执行用例的方法 * 方法会调用用例的run方法,然后调用用例的Start方法,这个方法应该在后台操作,用例可能比较耗时 * * @param interactor */ void execute(final AbstractUseCase interactor); } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/domain/executor/MainThread.java ================================================ package com.wjj.easy.easyandroid.mvp.domain.executor; /** * MainThread定义了一个能够在主线程使用用例执行的接口 * 举个例子:如果一个用例需要显示一个对象到UI上,能够使用这个确保run执行的内容是在主线程中 * @author wujiajun */ public interface MainThread { /** * 执行一个Runnable * 确保Runnable中的内容在主线程中运行 * * @param runnable */ void post(final Runnable runnable); } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/domain/executor/impl/MainThreadImpl.java ================================================ package com.wjj.easy.easyandroid.mvp.domain.executor.impl; import android.os.Handler; import android.os.Looper; import com.wjj.easy.easyandroid.mvp.domain.executor.MainThread; /** * MainThread具体实现类 * 确保Runnable中的内容在主线程中执行 * * @author wujiajun */ public class MainThreadImpl implements MainThread { private static MainThread sMainThread; private Handler mHandler; private MainThreadImpl() { mHandler = new Handler(Looper.getMainLooper()); } @Override public void post(Runnable runnable) { mHandler.post(runnable); } public static MainThread getInstance() { if (sMainThread == null) { sMainThread = new MainThreadImpl(); } return sMainThread; } } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/domain/executor/impl/ThreadExecutor.java ================================================ package com.wjj.easy.easyandroid.mvp.domain.executor.impl; import com.wjj.easy.easyandroid.mvp.domain.executor.Executor; import com.wjj.easy.easyandroid.mvp.domain.usecases.AbstractUseCase; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * Executor具体实现类 * 实现用例的执行,用例生命周期的更新 * 注意它是个单例模式 * * @author wujiajun */ public class ThreadExecutor implements Executor { // This is a singleton private static volatile ThreadExecutor sThreadExecutor; private static final int CORE_POOL_SIZE = 3; private static final int MAX_POOL_SIZE = 5; private static final int KEEP_ALIVE_TIME = 120; private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; private static final BlockingQueue WORK_QUEUE = new LinkedBlockingQueue(); private ThreadPoolExecutor mThreadPoolExecutor; private ThreadExecutor() { long keepAlive = KEEP_ALIVE_TIME; mThreadPoolExecutor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAX_POOL_SIZE, keepAlive, TIME_UNIT, WORK_QUEUE); } @Override public void execute(final AbstractUseCase interactor) { mThreadPoolExecutor.submit(new Runnable() { @Override public void run() { //执行用例逻辑 interactor.run(); //更新用例状态 interactor.onFinished(); } }); } /** * Executor实例 * * @return */ public static Executor getInstance() { if (sThreadExecutor == null) { sThreadExecutor = new ThreadExecutor(); } return sThreadExecutor; } } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/domain/usecases/AbstractUseCase.java ================================================ package com.wjj.easy.easyandroid.mvp.domain.usecases; import com.wjj.easy.easyandroid.mvp.domain.executor.Executor; import com.wjj.easy.easyandroid.mvp.domain.executor.MainThread; import javax.inject.Inject; /** * Domain层中抽象UseCase * 实现UseCase的基本操作,生命周期控制 * 举个例子:当Activity被销毁的时候,我们应该取消掉这个任务 volatile的目的是为了多线程都可以调用 * * @author wujiajun */ public abstract class AbstractUseCase implements UseCase { @Inject protected Executor mThreadExecutor; @Inject protected MainThread mMainThread; protected volatile boolean mIsCanceled; protected volatile boolean mIsRunning; protected Callback mCallback; /** * 业务逻辑实现方法 * 别主动调用他,Executor中自动执行调用 * * @see Executor */ public abstract void run(); /** * 取消当前任务 */ public void cancel() { mIsCanceled = true; mIsRunning = false; } /** * 检测任务是否正在进行中 * * @return true进行中 false处理完成/还没有处理/被取消掉 */ public boolean isRunning() { return mIsRunning; } /** * 完成操作 */ public void onFinished() { mIsRunning = false; mIsCanceled = false; } /** * 执行任务 */ public void execute() { this.mIsRunning = true; mThreadExecutor.execute(this); } /** * 设置任务回调接口 * * @param callback */ public void setCallback(Callback callback) { this.mCallback = callback; } /** * 获取任务回调接口 * * @return */ public Callback getCallback() { return mCallback; } } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/mvp/domain/usecases/UseCase.java ================================================ package com.wjj.easy.easyandroid.mvp.domain.usecases; /** * Domain层中UseCase抽象接口 * * @author wujiajun */ public interface UseCase { /** * UserCase执行方法 * 可在任何线程执行 */ void execute(); /** * 任务回调通用接口 */ interface Callback { void success(T t); void fail(); } } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/ui/EasyActivity.java ================================================ package com.wjj.easy.easyandroid.ui; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import com.orhanobut.logger.Logger; import com.wjj.easy.easyandroid.BuildConfig; import com.wjj.easy.easyandroid.mvp.EasyBaseView; /** * Activity基类 * Created by wujiajun on 17/4/14. */ public abstract class EasyActivity extends AppCompatActivity implements EasyBaseView { private final static String TAG = EasyActivity.class.getSimpleName(); private final static boolean DEBUG = BuildConfig.DEBUG; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(getContentView()); } @Override protected void onStart() { super.onStart(); if (DEBUG) { Logger.t(TAG).d("onStart"); } } @Override protected void onRestart() { super.onRestart(); if (DEBUG) { Logger.t(TAG).d("onRestart"); } } @Override protected void onResume() { super.onResume(); if (DEBUG) { Logger.t(TAG).d("onResume"); } } @Override protected void onStop() { super.onStop(); if (DEBUG) { Logger.t(TAG).d("onStop"); } } @Override protected void onDestroy() { super.onDestroy(); if (DEBUG) { Logger.t(TAG).d("onDestroy"); } } protected abstract int getContentView(); } ================================================ FILE: easyandroid/src/main/java/com/wjj/easy/easyandroid/ui/EasyFragment.java ================================================ package com.wjj.easy.easyandroid.ui; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.orhanobut.logger.Logger; import com.wjj.easy.easyandroid.BuildConfig; import com.wjj.easy.easyandroid.mvp.EasyBasePresenter; import com.wjj.easy.easyandroid.mvp.EasyBaseView; import javax.inject.Inject; /** * Created by wujiajun on 17/4/14. */ public abstract class EasyFragment extends Fragment implements EasyBaseView { private final static String TAG = EasyFragment.class.getSimpleName(); private final static boolean DEBUG = BuildConfig.DEBUG; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(getContentView(), container, false); initView(view); init(view); return view; } protected abstract void init(View view); protected abstract void initView(View view); @Override public void onStart() { super.onStart(); if (DEBUG) { Logger.t(TAG).d("onStart"); } } @Override public void onResume() { super.onResume(); if (DEBUG) { Logger.t(TAG).d("onResume"); } } @Override public void onPause() { super.onPause(); if (DEBUG) { Logger.t(TAG).d("onPause"); } } @Override public void onStop() { super.onStop(); if (DEBUG) { Logger.t(TAG).d("onStop"); } } @Override public void onDestroy() { super.onDestroy(); if (DEBUG) { Logger.t(TAG).d("onDestroy"); } } protected abstract int getContentView(); } ================================================ FILE: easyandroid/src/main/res/values/strings.xml ================================================ androidlib ================================================ FILE: gradle/wrapper/gradle-wrapper.properties ================================================ #Mon Dec 28 10:00:20 PST 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip ================================================ FILE: gradle.properties ================================================ # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. org.gradle.jvmargs=-Xmx1536m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true ================================================ FILE: gradlew ================================================ #!/usr/bin/env bash ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS="" APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn ( ) { echo "$*" } die ( ) { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; esac # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules function splitJvmOpts() { JVM_OPTS=("$@") } eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" ================================================ FILE: gradlew.bat ================================================ @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windowz variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* goto execute :4NT_args @rem Get arguments from the 4NT Shell from JP Software set CMD_LINE_ARGS=%$ :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: settings.gradle ================================================ include ':app', ':easyandroid'