├── .gitignore ├── .idea ├── caches │ └── build_file_checksums.ser ├── checkstyle-idea.xml ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── CommonSDK ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── vea │ │ └── atoms │ │ └── mvp │ │ └── commonsdk │ │ ├── adapter │ │ ├── BaseRecyclerAdapter.java │ │ ├── IBaseShowItemList.java │ │ ├── ListFactory.java │ │ ├── RecyclerRefreshLayout.java │ │ ├── ShowItemList.java │ │ ├── ViewPageInfo.java │ │ └── ViewPagerAdapterFragment.java │ │ ├── core │ │ ├── GlobalConfiguration.java │ │ ├── GlobalHttpHandlerImpl.java │ │ └── RouterHub.java │ │ ├── http │ │ └── Api.java │ │ └── utils │ │ ├── ARouterUtils.java │ │ └── ImageLoader.java │ └── res │ ├── layout │ └── public_recycler_footer_view.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── CommonService ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── org │ │ └── vea │ │ └── atoms │ │ └── mvp │ │ └── commonservice │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── org │ │ │ └── vea │ │ │ └── atoms │ │ │ └── mvp │ │ │ └── commonservice │ │ │ └── IUserService.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── org │ └── vea │ └── atoms │ └── mvp │ └── commonservice │ └── ExampleUnitTest.java ├── Module-gank ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── vea │ │ └── atoms │ │ └── mvp │ │ └── gank │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── debug │ │ └── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── vea │ │ │ └── atoms │ │ │ └── mvp │ │ │ └── gank │ │ │ ├── app │ │ │ ├── AppLifecyclesImpl.java │ │ │ ├── GankConstants.java │ │ │ └── GlobalConfiguration.java │ │ │ ├── di │ │ │ ├── component │ │ │ │ └── GankComponent.java │ │ │ └── module │ │ │ │ └── GankModule.java │ │ │ └── mvp │ │ │ ├── contract │ │ │ └── GirlContract.java │ │ │ ├── model │ │ │ ├── entity │ │ │ │ ├── GankBaseResponse.java │ │ │ │ └── GankItemBean.java │ │ │ └── service │ │ │ │ └── GankService.java │ │ │ ├── presenter │ │ │ └── GirlPresenter.java │ │ │ └── ui │ │ │ ├── activity │ │ │ └── GankMainActivity.java │ │ │ ├── adapter │ │ │ └── GirlListAdapter.java │ │ │ └── fragment │ │ │ └── GirlFragment.java │ └── res │ │ ├── layout │ │ ├── gank_activity_main.xml │ │ ├── gank_fragment_tech.xml │ │ └── gank_item_girl.xml │ │ └── values │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── vea │ └── atoms │ └── mvp │ └── gank │ └── ExampleUnitTest.java ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── org │ │ └── vea │ │ └── atoms │ │ └── mvp │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── vea │ │ │ └── atoms │ │ │ └── mvp │ │ │ └── demo │ │ │ ├── app │ │ │ ├── AppLifecyclesImpl.java │ │ │ └── GlobalConfiguration.java │ │ │ ├── di │ │ │ ├── component │ │ │ │ └── DemoComponent.java │ │ │ └── module │ │ │ │ └── DemoModule.java │ │ │ ├── mvp │ │ │ ├── adapter │ │ │ │ └── ManListAdapter.java │ │ │ ├── contract │ │ │ │ └── MainContract.java │ │ │ ├── model │ │ │ │ ├── entity │ │ │ │ │ ├── BaseResponse.java │ │ │ │ │ └── User.java │ │ │ │ └── service │ │ │ │ │ └── DemoService.java │ │ │ ├── presenter │ │ │ │ └── MainPresenter.java │ │ │ └── ui │ │ │ │ ├── MainActivity.java │ │ │ │ └── SplashActivity.java │ │ │ └── utils │ │ │ └── JsonServiceImpl.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ └── layer_splash_bg.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_splash.xml │ │ └── item_man.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_girl.png │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── splash_logo.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── org │ └── vea │ └── atoms │ └── mvp │ └── ExampleUnitTest.java ├── atoms ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── vea │ │ └── atoms │ │ └── mvp │ │ ├── app │ │ ├── ActivityManager.java │ │ ├── AppDelegate.java │ │ ├── AppLifecycles.java │ │ ├── AppManager.java │ │ ├── BaseApplication.java │ │ ├── IApp.java │ │ └── ILogout.java │ │ ├── base │ │ ├── BaseActivity.java │ │ ├── BaseFragment.java │ │ ├── BaseLazyFragment.java │ │ ├── BasePresenter.java │ │ ├── IPresenter.java │ │ └── IView.java │ │ ├── di │ │ ├── component │ │ │ └── AppComponent.java │ │ ├── module │ │ │ ├── AppModule.java │ │ │ ├── ClientModule.java │ │ │ └── GlobalConfigModule.java │ │ └── scope │ │ │ ├── ActivityScope.java │ │ │ └── FragmentScope.java │ │ ├── http │ │ ├── BaseUrl.java │ │ ├── GlobalHttpHandler.java │ │ └── log │ │ │ ├── DefaultFormatPrinter.java │ │ │ ├── FormatPrinter.java │ │ │ └── RequestInterceptor.java │ │ ├── integration │ │ ├── ConfigModule.java │ │ ├── IRepositoryManager.java │ │ ├── ManifestParser.java │ │ ├── RepositoryManager.java │ │ └── cache │ │ │ ├── Cache.java │ │ │ ├── CacheType.java │ │ │ ├── IntelligentCache.java │ │ │ └── LruCache.java │ │ └── utils │ │ ├── AtomsUtils.java │ │ ├── CharacterHandler.java │ │ ├── Preconditions.java │ │ ├── UrlEncoderUtils.java │ │ └── ZipHelper.java │ └── res │ └── values │ └── strings.xml ├── build.gradle ├── config.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── image └── atoms_banner_v1.0.jpg ├── qrcode_for_gh_e708d5b47c85_258.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .idea/ 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | 10 | # VSCode 11 | .classpath 12 | .project 13 | .settings/ 14 | .vscode/ 15 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/checkstyle-idea.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CommonSDK/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /CommonSDK/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | compileSdkVersion rootProject.ext.android["compileSdkVersion"] 6 | 7 | defaultConfig { 8 | minSdkVersion rootProject.ext.android["minSdkVersion"] 9 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 10 | versionCode Integer.parseInt(APP_CODE) 11 | versionName APP_VERSION 12 | 13 | } 14 | 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | 22 | compileOptions { 23 | targetCompatibility JavaVersion.VERSION_1_8 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | } 26 | 27 | resourcePrefix "public_" //给 Module 内的资源名增加前缀, 避免资源名冲突 28 | 29 | } 30 | 31 | dependencies { 32 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 33 | 34 | api project(':atoms') 35 | 36 | api rootProject.ext.dependencies["arouter"] 37 | 38 | // 如果想要同时支持多个BaseUrl ,否则可以去掉 39 | api rootProject.ext.dependencies["retrofit-url-manager"] 40 | // 加载图片框架 41 | api rootProject.ext.dependencies["glide"] 42 | 43 | api rootProject.ext.dependencies["fastjson"] 44 | 45 | api rootProject.ext.dependencies["okhttp-logging"] 46 | } 47 | -------------------------------------------------------------------------------- /CommonSDK/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /CommonSDK/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /CommonSDK/src/main/java/com/vea/atoms/mvp/commonsdk/adapter/IBaseShowItemList.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.commonsdk.adapter; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by xwc on 2018/4/18. 7 | */ 8 | 9 | public interface IBaseShowItemList { 10 | 11 | /** 12 | * @param isRefresh 是否刷新 13 | * @param data 数据 14 | */ 15 | void showData(boolean isRefresh, List data); 16 | } 17 | -------------------------------------------------------------------------------- /CommonSDK/src/main/java/com/vea/atoms/mvp/commonsdk/adapter/ListFactory.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.commonsdk.adapter; 2 | 3 | 4 | /** 5 | * Created by xwc on 2018/4/18. 6 | */ 7 | 8 | public class ListFactory { 9 | 10 | 11 | public IBaseShowItemList createShowItemList(BaseRecyclerAdapter adapter, RecyclerRefreshLayout refresh) { 12 | return new ShowItemList(adapter, refresh); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /CommonSDK/src/main/java/com/vea/atoms/mvp/commonsdk/adapter/ShowItemList.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.commonsdk.adapter; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by xwc on 2018/4/18. 7 | */ 8 | 9 | public class ShowItemList implements IBaseShowItemList { 10 | 11 | public static int NUM_OF_PAGE = 20; 12 | 13 | private BaseRecyclerAdapter adapter; 14 | 15 | private RecyclerRefreshLayout refreshLayout; 16 | 17 | public ShowItemList(BaseRecyclerAdapter adapter, RecyclerRefreshLayout refreshLayout) { 18 | this.adapter = adapter; 19 | this.refreshLayout = refreshLayout; 20 | } 21 | 22 | @Override 23 | public void showData(boolean isRefresh, List data) { 24 | if (isRefresh) refresh(data); 25 | else more(data); 26 | } 27 | 28 | private void more(List data) { 29 | 30 | adapter.addAll(data); 31 | if (data.size() < NUM_OF_PAGE) { 32 | showNoMoreView(); 33 | } else { 34 | showHasMoreViw(); 35 | } 36 | refreshLayout.onComplete(); 37 | } 38 | 39 | private void refresh(List data) { 40 | 41 | adapter.clear(); 42 | adapter.addAll(data); 43 | 44 | if (data.size() < NUM_OF_PAGE) { 45 | showNoMoreView(); 46 | } else { 47 | showHasMoreViw(); 48 | } 49 | refreshLayout.onComplete(); 50 | } 51 | 52 | private void showNoMoreView() { 53 | adapter.setState(BaseRecyclerAdapter.STATE_NO_MORE, true); 54 | refreshLayout.setCanLoadMore(false); 55 | } 56 | 57 | private void showHasMoreViw() { 58 | refreshLayout.setCanLoadMore(true); 59 | adapter.setState(BaseRecyclerAdapter.STATE_LOAD_MORE, true); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /CommonSDK/src/main/java/com/vea/atoms/mvp/commonsdk/adapter/ViewPageInfo.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.commonsdk.adapter; 2 | 3 | import android.os.Bundle; 4 | 5 | /** 6 | * ================================================ 7 | * Created by Vea on 2016/11/30. 8 | * ================================================ 9 | */ 10 | public final class ViewPageInfo { 11 | public final String tag; 12 | public final Class clss; 13 | public final Bundle args; 14 | public final String title; 15 | 16 | public ViewPageInfo(String _title, String _tag, Class _class, Bundle _args) { 17 | title = _title; 18 | tag = _tag; 19 | clss = _class; 20 | args = _args; 21 | } 22 | } -------------------------------------------------------------------------------- /CommonSDK/src/main/java/com/vea/atoms/mvp/commonsdk/adapter/ViewPagerAdapterFragment.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.commonsdk.adapter; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.support.v4.app.FragmentManager; 10 | import android.support.v4.app.FragmentStatePagerAdapter; 11 | import android.support.v4.util.ArrayMap; 12 | import android.support.v4.view.PagerAdapter; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Map; 16 | 17 | /** 18 | * FragmentPagerAdapter是Android-support-v4支持包里面出现的一个新的适配器,继承自PagerAdapter, 19 | * 是专门用来给支持包中出现的ViewPager进行数据适配的。 20 | *

21 | * PagerAdapter在之前的文章中进行过简单的介绍,不记得怎么使用的可以先去看一下。 22 | *

23 | * FragmentPagerAdapter,见名知意,这个适配器就是用来实现Fragment在ViewPager里面进行滑动切换的, 24 | * 因此,如果我们想实现Fragment的左右滑动,可以选择ViewPager和FragmentPagerAdapter实现。 25 | *

26 | * FragmentPagerAdapter拥有自己的缓存策略,当和ViewPager配合使用的时候, 27 | * 会缓存当前Fragment以及左边一个、右边一个,一共三个Fragment对象。 28 | *

29 | * 假如有三个Fragment,那么在ViewPager初始化之后,3个fragment都会加载完成, 30 | * 中间的Fragment在整个生命周期里面只会加载一次,当最左边的Fragment处于显示状态,最右边的Fragment由于超出缓存范围, 31 | * 会被销毁,当再次滑到中间的Fragment的时候,最右边的Fragment会被再次初始化。 32 | *

33 | * 在当前版本来说,最适合用来做固定的较少数量的场合, 34 | * 比如说一个有3个tab标签的fragment滑动界面。FragmentPagerAdapter会对我们浏览过Fragment进行缓存, 35 | * 保存这些界面的临时状态,这样当我们左右滑动的时候,界面切换更加的流畅。 36 | * 但是,这样也会增加程序占用的内存。如果应用场景是更多的Fragment,请使用FragmentStatePagerAdapter。 37 | *

38 | *

39 | *

40 | *

41 | * Created by Vea on 2016/11/30. 42 | */ 43 | @SuppressLint("Recycle") 44 | public class ViewPagerAdapterFragment extends FragmentStatePagerAdapter { 45 | 46 | private Context mContext; 47 | public ArrayList mTabs = new ArrayList<>(); 48 | private Map mFragments = new ArrayMap<>(); 49 | 50 | public ViewPagerAdapterFragment(FragmentManager fm, Context context) { 51 | super(fm); 52 | mContext = context; 53 | } 54 | 55 | public void addTab(@Nullable String title, @NonNull String tag, Class clss, @Nullable Bundle args) { 56 | ViewPageInfo viewPageInfo = new ViewPageInfo(title, tag, clss, args); 57 | mTabs.add(viewPageInfo); 58 | } 59 | 60 | @Override 61 | public int getCount() { 62 | return mTabs.size(); 63 | } 64 | 65 | @Override 66 | public int getItemPosition(Object object) { 67 | return PagerAdapter.POSITION_NONE; 68 | } 69 | 70 | @Override 71 | public Fragment getItem(int position) { 72 | ViewPageInfo info = mTabs.get(position); 73 | 74 | Fragment fragment = mFragments.get(info.tag); 75 | if (fragment == null) { 76 | fragment = Fragment.instantiate(mContext, info.clss.getName(), info.args); 77 | // 避免重复创建而进行缓存 78 | mFragments.put(info.tag, fragment); 79 | } 80 | 81 | return fragment; 82 | } 83 | 84 | @Override 85 | public CharSequence getPageTitle(int position) { 86 | return mTabs.get(position).title; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /CommonSDK/src/main/java/com/vea/atoms/mvp/commonsdk/core/GlobalHttpHandlerImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.commonsdk.core; 17 | 18 | import android.content.Context; 19 | 20 | import com.vea.atoms.mvp.http.GlobalHttpHandler; 21 | 22 | import okhttp3.Interceptor; 23 | import okhttp3.Request; 24 | import okhttp3.Response; 25 | 26 | /** 27 | * ================================================ 28 | * 展示 {@link GlobalHttpHandler} 的用法 29 | *

30 | * Created by Vea on 04/09/2017 17:06 31 | * ================================================ 32 | */ 33 | public class GlobalHttpHandlerImpl implements GlobalHttpHandler { 34 | private Context context; 35 | 36 | public GlobalHttpHandlerImpl(Context context) { 37 | this.context = context; 38 | } 39 | 40 | /** 41 | * 这里可以先客户端一步拿到每一次 Http 请求的结果, 可以先解析成 Json, 再做一些操作, 如检测到 token 过期后 42 | * 重新请求 token, 并重新执行请求 43 | * 44 | * @param httpResult 服务器返回的结果 (已被框架自动转换为字符串) 45 | * @param chain {@link okhttp3.Interceptor.Chain} 46 | * @param response {@link Response} 47 | * @return 48 | */ 49 | @Override 50 | public Response onHttpResultResponse(String httpResult, Interceptor.Chain chain, Response response) { 51 | /* 这里如果发现 token 过期, 可以先请求最新的 token, 然后在拿新的 token 放入 Request 里去重新请求 52 | 注意在这个回调之前已经调用过 proceed(), 所以这里必须自己去建立网络请求, 如使用 Okhttp 使用新的 Request 去请求 53 | create a new request and modify it accordingly using the new token 54 | Request newRequest = chain.request().newBuilder().header("token", newToken) 55 | .build(); 56 | 57 | retry the request 58 | 59 | response.body().close(); 60 | 如果使用 Okhttp 将新的请求, 请求成功后, 再将 Okhttp 返回的 Response return 出去即可 61 | 如果不需要返回新的结果, 则直接把参数 response 返回出去即可 */ 62 | return response; 63 | } 64 | 65 | /** 66 | * 这里可以在请求服务器之前拿到 {@link Request}, 做一些操作比如给 {@link Request} 统一添加 token 或者 header 以及参数加密等操作 67 | * 68 | * @param chain {@link okhttp3.Interceptor.Chain} 69 | * @param request {@link Request} 70 | * @return 71 | */ 72 | @Override 73 | public Request onHttpRequestBefore(Interceptor.Chain chain, Request request) { 74 | /* 如果需要再请求服务器之前做一些操作, 则重新返回一个做过操作的的 Request 如增加 Header, 不做操作则直接返回参数 request 75 | return chain.request().newBuilder().header("token", tokenId) 76 | .build(); */ 77 | return request; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /CommonSDK/src/main/java/com/vea/atoms/mvp/commonsdk/core/RouterHub.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.commonsdk.core; 17 | 18 | /** 19 | * ================================================ 20 | * RouterHub 用来定义路由器的路由地址, 以组件名作为前缀, 对每个组件的路由地址进行分组, 可以统一查看和管理所有分组的路由地址 21 | *

22 | * RouterHub 存在于基础库, 可以被看作是所有组件都需要遵守的通讯协议, 里面不仅可以放路由地址常量, 还可以放跨组件传递数据时命名的各种 Key 值 23 | * 再配以适当注释, 任何组件开发人员不需要事先沟通只要依赖了这个协议, 就知道了各自该怎样协同工作, 既提高了效率又降低了出错风险, 约定的东西自然要比口头上说强 24 | *

25 | * 如果您觉得把每个路由地址都写在基础库的 RouterHub 中, 太麻烦了, 也可以在每个组件内部建立一个私有 RouterHub, 将不需要跨组件的 26 | * 路由地址放入私有 RouterHub 中管理, 只将需要跨组件的路由地址放入基础库的公有 RouterHub 中管理, 如果您不需要集中管理所有路由地址的话 27 | * 这也是比较推荐的一种方式 28 | *

29 | * 路由地址的命名规则为 组件名 + 页面名, 如订单组件的订单详情页的路由地址可以命名为 "/order/OrderDetailActivity" 30 | *

31 | * ARouter 将路由地址中第一个 '/' 后面的字符称为 Group, 比如上面的示例路由地址中 order 就是 Group, 以 order 开头的地址都被分配该 Group 下 32 | * 切记不同的组件中不能出现名称一样的 Group, 否则会发生该 Group 下的部分路由地址找不到的情况!!! 33 | * 所以每个组件使用自己的组件名作为 Group 是比较好的选择, 毕竟组件不会重名 34 | *

35 | * Created by Vea on 2018/8/25 36 | * ================================================ 37 | */ 38 | public interface RouterHub { 39 | /** 40 | * 组名 41 | */ 42 | String APP = "/app";//宿主 App 组件 43 | 44 | String GANK = "/gank";//干货集中营组件 45 | 46 | /* app =============================================================*/ 47 | String APP_MAIN_ACTIVITY = APP + "/MainActivity"; 48 | 49 | 50 | /* gank =============================================================*/ 51 | String GANK_MAIN_ACTIVITY = GANK + "/GankMainActivity"; 52 | } 53 | -------------------------------------------------------------------------------- /CommonSDK/src/main/java/com/vea/atoms/mvp/commonsdk/http/Api.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.commonsdk.http; 17 | 18 | /** 19 | * ================================================ 20 | * CommonSDK 的 Api 可以定义公用的关于 API 的相关常量, 比如说请求地址, 错误码等, 每个组件的 Api 可以定义组件自己的私有常量 21 | *

22 | * Created by Vea on 30/03/2018 17:16 23 | * ================================================ 24 | */ 25 | public interface Api { 26 | String APP_DOMAIN = "https://api.github.com"; 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /CommonSDK/src/main/java/com/vea/atoms/mvp/commonsdk/utils/ARouterUtils.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.commonsdk.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | 6 | import com.alibaba.android.arouter.launcher.ARouter; 7 | 8 | /** 9 | * ARouter 工具类 10 | * 11 | * @author lishide 12 | * @date 2018/10/08 13 | */ 14 | public class ARouterUtils { 15 | private ARouterUtils() { 16 | throw new IllegalStateException("you can't instantiate me!"); 17 | } 18 | 19 | /** 20 | * 使用 {@link ARouter} 根据 {@code path} 跳转到对应的页面, 这个方法因为没有使用 {@link Activity} 跳转 21 | * 所以 {@link ARouter} 会自动给 {@link android.content.Intent} 加上 Intent.FLAG_ACTIVITY_NEW_TASK 22 | * 如果不想自动加上这个 Flag 请使用 {@link ARouter#getInstance()#navigation(Context, String)} 并传入 {@link Activity} 23 | * 24 | * @param path {@code path} 25 | */ 26 | public static void navigation(String path) { 27 | ARouter.getInstance().build(path).navigation(); 28 | } 29 | 30 | /** 31 | * 使用 {@link ARouter} 根据 {@code path} 跳转到对应的页面, 如果参数 {@code context} 传入的不是 {@link Activity} 32 | * {@link ARouter} 就会自动给 {@link android.content.Intent} 加上 Intent.FLAG_ACTIVITY_NEW_TASK 33 | * 如果不想自动加上这个 Flag 请使用 {@link Activity} 作为 {@code context} 传入 34 | * 35 | * @param context 36 | * @param path 37 | */ 38 | public static void navigation(Context context, String path) { 39 | ARouter.getInstance().build(path).navigation(context); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /CommonSDK/src/main/java/com/vea/atoms/mvp/commonsdk/utils/ImageLoader.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.commonsdk.utils; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapShader; 6 | import android.graphics.Canvas; 7 | import android.graphics.Paint; 8 | import android.widget.ImageView; 9 | 10 | import com.bumptech.glide.Glide; 11 | import com.bumptech.glide.Priority; 12 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; 13 | import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; 14 | import com.bumptech.glide.request.RequestOptions; 15 | 16 | import java.security.MessageDigest; 17 | 18 | /** 19 | * ================================================ 20 | * Glide 图片加载辅助类,支持圆形图片 21 | *

22 | * Created by Vea on 30/03/2018 17:16 23 | * ================================================ 24 | */ 25 | public class ImageLoader { 26 | 27 | private ImageLoader() { 28 | } 29 | 30 | public static void load(Context context, ImageView view, String url) { 31 | Glide.with(context).load(url).into(view); 32 | } 33 | 34 | public static void load(Context context, ImageView view, int drawableRes) { 35 | Glide.with(context).load(drawableRes).into(view); 36 | } 37 | 38 | /** 39 | * @param placeholder 加载中的图片 40 | * @param error 加载失败显示的图片 41 | */ 42 | public static void load(Context context, ImageView view, String url, int placeholder, int error) { 43 | RequestOptions options = new RequestOptions() 44 | .centerCrop() 45 | .placeholder(placeholder) 46 | .error(error) 47 | .priority(Priority.HIGH); 48 | 49 | Glide.with(context).load(url).apply(options).into(view); 50 | } 51 | 52 | /** 53 | * 加载圆形图片 54 | * 55 | * @param context 56 | * @param view 57 | * @param url 58 | */ 59 | public static void loadCircleImage(Context context, ImageView view, String url) { 60 | RequestOptions options = new RequestOptions() 61 | .centerCrop() 62 | .priority(Priority.HIGH) 63 | .transform(new GlideCircleTransform()); 64 | Glide.with(context).load(url).apply(options).into(view); 65 | } 66 | 67 | /** 68 | * 加载圆形图片 69 | * 70 | * @param context 71 | * @param view 72 | * @param url 73 | * @param error 74 | */ 75 | public static void loadCircleImage(Context context, ImageView view, String url, int error) { 76 | RequestOptions options = new RequestOptions() 77 | .centerCrop() 78 | .placeholder(error) 79 | .error(error) 80 | .priority(Priority.HIGH) 81 | .transform(new GlideCircleTransform()); 82 | Glide.with(context).load(url).apply(options).into(view); 83 | } 84 | 85 | public static class GlideCircleTransform extends BitmapTransformation { 86 | 87 | public GlideCircleTransform() { 88 | super(); 89 | } 90 | 91 | @Override 92 | public Bitmap transform(BitmapPool pool, Bitmap toTransform, 93 | int outWidth, int outHeight) { 94 | return circleCrop(pool, toTransform); 95 | } 96 | 97 | private static Bitmap circleCrop(BitmapPool pool, Bitmap source) { 98 | if (source == null) return null; 99 | int size = Math.min(source.getWidth(), source.getHeight()); 100 | int x = (source.getWidth() - size) / 2; 101 | int y = (source.getHeight() - size) / 2; 102 | 103 | Bitmap squared = Bitmap.createBitmap(source, x, y, size, size); 104 | Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888); 105 | if (result == null) { 106 | result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); 107 | } 108 | Canvas canvas = new Canvas(result); 109 | Paint paint = new Paint(); 110 | paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); 111 | paint.setAntiAlias(true); 112 | float r = size / 2f; 113 | canvas.drawCircle(r, r, r, paint); 114 | return result; 115 | } 116 | 117 | @Override 118 | public void updateDiskCacheKey(MessageDigest messageDigest) { 119 | 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /CommonSDK/src/main/res/layout/public_recycler_footer_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /CommonSDK/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #663366 4 | #663366 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /CommonSDK/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CommonSDK 3 | 4 | -------------------------------------------------------------------------------- /CommonSDK/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | -------------------------------------------------------------------------------- /CommonService/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /CommonService/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | compileSdkVersion rootProject.ext.android["compileSdkVersion"] 6 | 7 | defaultConfig { 8 | minSdkVersion rootProject.ext.android["minSdkVersion"] 9 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 10 | versionCode Integer.parseInt(APP_CODE) 11 | versionName APP_VERSION 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | 14 | } 15 | 16 | buildTypes { 17 | release { 18 | postprocessing { 19 | removeUnusedCode false 20 | removeUnusedResources false 21 | obfuscate false 22 | optimizeCode false 23 | proguardFile 'proguard-rules.pro' 24 | } 25 | } 26 | } 27 | 28 | } 29 | 30 | dependencies { 31 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /CommonService/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /CommonService/src/androidTest/java/org/vea/atoms/mvp/commonservice/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package org.vea.atoms.mvp.commonservice; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("org.vea.atoms.mvp.commonservice.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CommonService/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /CommonService/src/main/java/org/vea/atoms/mvp/commonservice/IUserService.java: -------------------------------------------------------------------------------- 1 | package org.vea.atoms.mvp.commonservice; 2 | 3 | 4 | /** 5 | * ================================================ 6 | * 向外提供数据传递接口服务 7 | *

8 | * Created by Vea on 2018/8/30. 9 | * ================================================ 10 | */ 11 | public interface IUserService { 12 | String getAvatarUrl(); 13 | 14 | int getId(); 15 | 16 | String getLogin(); 17 | 18 | void setAvatarUrl(String avatar_url); 19 | 20 | void setId(int id); 21 | 22 | void setLogin(String login); 23 | } 24 | -------------------------------------------------------------------------------- /CommonService/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CommonService 3 | 4 | -------------------------------------------------------------------------------- /CommonService/src/test/java/org/vea/atoms/mvp/commonservice/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package org.vea.atoms.mvp.commonservice; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /Module-gank/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Module-gank/build.gradle: -------------------------------------------------------------------------------- 1 | if (isRunGankModule.toBoolean()) { 2 | apply plugin: 'com.android.application' 3 | } else { 4 | apply plugin: 'com.android.library' 5 | } 6 | apply plugin: 'com.jakewharton.butterknife' 7 | apply plugin: 'kotlin-android' 8 | android { 9 | compileSdkVersion rootProject.ext.android["compileSdkVersion"] 10 | 11 | defaultConfig { 12 | minSdkVersion rootProject.ext.android["minSdkVersion"] 13 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 14 | versionCode Integer.parseInt(APP_CODE) 15 | versionName APP_VERSION 16 | 17 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 18 | 19 | javaCompileOptions { 20 | annotationProcessorOptions { 21 | arguments = [moduleName: project.getName()] 22 | includeCompileClasspath true 23 | } 24 | } 25 | 26 | } 27 | 28 | buildTypes { 29 | release { 30 | minifyEnabled false 31 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 32 | } 33 | } 34 | 35 | 36 | compileOptions { 37 | targetCompatibility JavaVersion.VERSION_1_8 38 | sourceCompatibility JavaVersion.VERSION_1_8 39 | } 40 | 41 | resourcePrefix "gank_" //给 Module 内的资源名增加前缀, 避免资源名冲突 42 | 43 | 44 | sourceSets { 45 | main { 46 | jniLibs.srcDirs = ['libs'] 47 | if (isRunGankModule.toBoolean()) { 48 | manifest.srcFile 'src/main/debug/AndroidManifest.xml' 49 | } else { 50 | manifest.srcFile 'src/main/AndroidManifest.xml' 51 | } 52 | } 53 | } 54 | 55 | } 56 | 57 | dependencies { 58 | implementation fileTree(dir: 'libs', include: ['*.jar']) 59 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 60 | 61 | testImplementation rootProject.ext.dependencies["junit"] 62 | androidTestImplementation rootProject.ext.dependencies["runner"] 63 | androidTestImplementation rootProject.ext.dependencies["espresso-core"] 64 | 65 | api project(':CommonSDK') 66 | api project(":CommonService") 67 | 68 | 69 | if (isRunGankModule.toBoolean()) { 70 | 71 | annotationProcessor rootProject.ext.dependencies["arouter-compiler"] 72 | annotationProcessor rootProject.ext.dependencies["butterknife-compiler"] 73 | annotationProcessor rootProject.ext.dependencies["dagger2-compiler"] 74 | 75 | debugImplementation rootProject.ext.dependencies["canary-debug"] 76 | releaseImplementation rootProject.ext.dependencies["canary-release"] 77 | } else { 78 | compileOnly rootProject.ext.dependencies["arouter-compiler"] 79 | compileOnly rootProject.ext.dependencies["butterknife-compiler"] 80 | compileOnly rootProject.ext.dependencies["dagger2-compiler"] 81 | 82 | compileOnly rootProject.ext.dependencies["canary-debug"] 83 | compileOnly rootProject.ext.dependencies["canary-release"] 84 | } 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /Module-gank/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /Module-gank/src/androidTest/java/com/vea/atoms/mvp/gank/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.gank; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.vea.atoms.mvp.gank.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Module-gank/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Module-gank/src/main/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 19 | 20 | 21 | 25 | 28 | 31 | 32 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/app/AppLifecyclesImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.app; 17 | 18 | import android.app.Application; 19 | import android.content.Context; 20 | import android.support.annotation.NonNull; 21 | 22 | import com.squareup.leakcanary.LeakCanary; 23 | import com.vea.atoms.mvp.app.AppLifecycles; 24 | import com.vea.atoms.mvp.gank.BuildConfig; 25 | import com.vea.atoms.mvp.gank.mvp.model.service.GankService; 26 | 27 | import me.jessyan.retrofiturlmanager.RetrofitUrlManager; 28 | 29 | 30 | /** 31 | * ================================================ 32 | * 展示 {@link AppLifecycles} 的用法 33 | *

34 | * Created by Vea on 2018/8/20 35 | * ================================================ 36 | */ 37 | public class AppLifecyclesImpl implements AppLifecycles { 38 | 39 | @Override 40 | public void attachBaseContext(@NonNull Application application, @NonNull Context base) { 41 | 42 | } 43 | 44 | @Override 45 | public void onCreate(@NonNull Application application) { 46 | if (LeakCanary.isInAnalyzerProcess(application)) { 47 | // This process is dedicated to LeakCanary for heap analysis. 48 | // You should not init your app in this process. 49 | return; 50 | } 51 | //使用 RetrofitUrlManager 切换 BaseUrl 52 | RetrofitUrlManager.getInstance().putDomain(GankService.GANK_DOMAIN_NAME, GankService.GANK_DOMAIN); 53 | if (!BuildConfig.DEBUG) { 54 | LeakCanary.install(application); 55 | } 56 | } 57 | 58 | @Override 59 | public void onTerminate(@NonNull Application application) { 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/app/GankConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.app; 17 | 18 | 19 | /** 20 | * ================================================ 21 | * 存放一些静态的变量 22 | *

23 | * Created by Vea on 2016/11/24 24 | * ================================================ 25 | */ 26 | public interface GankConstants { 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/app/GlobalConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.app; 17 | 18 | import android.content.Context; 19 | 20 | import com.vea.atoms.mvp.app.AppDelegate; 21 | import com.vea.atoms.mvp.app.AppLifecycles; 22 | import com.vea.atoms.mvp.di.module.GlobalConfigModule; 23 | import com.vea.atoms.mvp.integration.ConfigModule; 24 | import com.vea.atoms.mvp.integration.ManifestParser; 25 | 26 | import java.util.List; 27 | 28 | 29 | /** 30 | * ================================================ 31 | * 组件的全局配置信息在此配置, 需要将此实现类声明到 AndroidManifest 中 32 | * CommonSDK 中已有 {@link GlobalConfiguration} 配置有所有组件都可公用的配置信息 33 | * 这里用来配置一些组件自身私有的配置信息 34 | * 35 | * @see AppDelegate 36 | * @see ManifestParser 37 | * Created by Vea on 12/04/2017 17:25 38 | * ================================================ 39 | */ 40 | public final class GlobalConfiguration implements ConfigModule { 41 | 42 | @Override 43 | public void applyOptions(Context context, GlobalConfigModule.Builder builder) { 44 | 45 | } 46 | 47 | @Override 48 | public void injectAppLifecycle(Context context, List lifecycles) { 49 | // AppLifecycles 的所有方法都会在基类 Application 的对应的生命周期中被调用,所以在对应的方法中可以扩展一些自己需要的逻辑 50 | // 可以根据不同的逻辑添加多个实现类 51 | lifecycles.add(new AppLifecyclesImpl()); 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/di/component/GankComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.di.component; 17 | 18 | import com.vea.atoms.mvp.di.component.AppComponent; 19 | import com.vea.atoms.mvp.di.scope.ActivityScope; 20 | import com.vea.atoms.mvp.gank.di.module.GankModule; 21 | import com.vea.atoms.mvp.gank.mvp.contract.GirlContract; 22 | import com.vea.atoms.mvp.gank.mvp.ui.fragment.GirlFragment; 23 | 24 | import dagger.BindsInstance; 25 | import dagger.Component; 26 | 27 | /** 28 | * ================================================ 29 | * 展示 Component 的用法 30 | *

31 | * Created by Vea on 09/04/2016 11:17 32 | * ================================================ 33 | */ 34 | @ActivityScope 35 | @Component(modules = GankModule.class, dependencies = AppComponent.class) 36 | public interface GankComponent { 37 | 38 | void inject(GirlFragment activity); 39 | 40 | @Component.Builder 41 | interface Builder { 42 | @BindsInstance 43 | GankComponent.Builder view(GirlContract.View view); 44 | 45 | GankComponent.Builder appComponent(AppComponent appComponent); 46 | 47 | GankComponent build(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/di/module/GankModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.di.module; 17 | 18 | import com.vea.atoms.mvp.commonsdk.adapter.BaseRecyclerAdapter; 19 | import com.vea.atoms.mvp.di.scope.ActivityScope; 20 | import com.vea.atoms.mvp.gank.mvp.contract.GirlContract; 21 | import com.vea.atoms.mvp.gank.mvp.ui.adapter.GirlListAdapter; 22 | 23 | import dagger.Module; 24 | import dagger.Provides; 25 | 26 | /** 27 | * ================================================ 28 | * 展示 Module 的用法 29 | *

30 | * Created by Vea on 09/04/2016 11:10 31 | * ================================================ 32 | */ 33 | @Module 34 | public class GankModule { 35 | 36 | @ActivityScope 37 | @Provides 38 | static GirlListAdapter provideListAdapter(GirlContract.View view) { 39 | GirlListAdapter adapter = new GirlListAdapter(view.getFragmentActivity()); 40 | adapter.setState(BaseRecyclerAdapter.STATE_HIDE, false); 41 | return adapter; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/mvp/contract/GirlContract.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.mvp.contract; 17 | 18 | import android.app.Activity; 19 | 20 | import com.vea.atoms.mvp.base.IPresenter; 21 | import com.vea.atoms.mvp.base.IView; 22 | import com.vea.atoms.mvp.gank.mvp.model.entity.GankItemBean; 23 | import com.vea.atoms.mvp.gank.mvp.presenter.GirlPresenter; 24 | import com.vea.atoms.mvp.gank.mvp.ui.fragment.GirlFragment; 25 | 26 | import java.util.List; 27 | 28 | /** 29 | * ================================================ 30 | * 约定协议 31 | * 32 | * @see GirlPresenter 33 | * @see GirlFragment 34 | * Created by Vea on 2016/11/24 35 | * ================================================ 36 | */ 37 | public interface GirlContract { 38 | 39 | interface View extends IView { 40 | 41 | void getGankDataSuccess(List mList, boolean isRefresh); 42 | 43 | /** 44 | * @param isRefresh 刷新为true,加载更多为false 45 | */ 46 | void getGankDataFailure(boolean isRefresh); 47 | 48 | Activity getFragmentActivity(); 49 | } 50 | 51 | interface Presenter extends IPresenter { 52 | 53 | void getGankData(boolean isRefresh); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/mvp/model/entity/GankBaseResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.mvp.model.entity; 17 | 18 | 19 | /** 20 | * ================================================ 21 | * 如果你服务器返回的数据格式固定为这种方式(这里只提供思想,服务器返回的数据格式可能不一致,可根据自家服务器返回的格式作更改) 22 | * 指定范型即可改变 {@code data} 字段的类型, 达到重用 {@link GankBaseResponse} 23 | *

24 | * Created by Vea on 26/09/2016 15:19 25 | * ================================================ 26 | */ 27 | public class GankBaseResponse { 28 | private boolean error; 29 | private T results; 30 | 31 | public T getResults() { 32 | return results; 33 | } 34 | 35 | public void setResults(T results) { 36 | this.results = results; 37 | } 38 | 39 | public boolean getError() { 40 | return error; 41 | } 42 | 43 | public void setError(boolean error) { 44 | this.error = error; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/mvp/model/entity/GankItemBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.mvp.model.entity; 17 | 18 | /** 19 | * ================================================ 20 | * Created by Vea on 08/05/2016 12:05 21 | * ================================================ 22 | */ 23 | public class GankItemBean { 24 | /** 25 | * _id : 57b64b6d421aa93a804bea26 26 | * createdAt : 2016-08-19T07:57:33.576Z 27 | * desc : 8-19 28 | * publishedAt : 2016-08-19T11:26:30.163Z 29 | * source : chrome 30 | * type : 福利 31 | * url : http://ww4.sinaimg.cn/large/610dc034jw1f6yq5xrdofj20u00u0aby.jpg 32 | * used : true 33 | * who : daimajia 34 | */ 35 | private String _id; 36 | private String createdAt; 37 | private String desc; 38 | private String publishedAt; 39 | private String source; 40 | private String type; 41 | private String url; 42 | private boolean used; 43 | private String who; 44 | private int height; 45 | 46 | public int getHeight() { 47 | return height; 48 | } 49 | 50 | public void setHeight(int height) { 51 | this.height = height; 52 | } 53 | 54 | public String get_id() { 55 | return _id; 56 | } 57 | 58 | public void set_id(String _id) { 59 | this._id = _id; 60 | } 61 | 62 | public String getCreatedAt() { 63 | return createdAt; 64 | } 65 | 66 | public void setCreatedAt(String createdAt) { 67 | this.createdAt = createdAt; 68 | } 69 | 70 | public String getDesc() { 71 | return desc; 72 | } 73 | 74 | public void setDesc(String desc) { 75 | this.desc = desc; 76 | } 77 | 78 | public String getPublishedAt() { 79 | return publishedAt; 80 | } 81 | 82 | public void setPublishedAt(String publishedAt) { 83 | this.publishedAt = publishedAt; 84 | } 85 | 86 | public String getSource() { 87 | return source; 88 | } 89 | 90 | public void setSource(String source) { 91 | this.source = source; 92 | } 93 | 94 | public String getType() { 95 | return type; 96 | } 97 | 98 | public void setType(String type) { 99 | this.type = type; 100 | } 101 | 102 | public String getUrl() { 103 | return url; 104 | } 105 | 106 | public void setUrl(String url) { 107 | this.url = url; 108 | } 109 | 110 | public boolean isUsed() { 111 | return used; 112 | } 113 | 114 | public void setUsed(boolean used) { 115 | this.used = used; 116 | } 117 | 118 | public String getWho() { 119 | return who; 120 | } 121 | 122 | public void setWho(String who) { 123 | this.who = who; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/mvp/model/service/GankService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.mvp.model.service; 17 | 18 | import com.vea.atoms.mvp.gank.mvp.model.entity.GankBaseResponse; 19 | import com.vea.atoms.mvp.gank.mvp.model.entity.GankItemBean; 20 | 21 | import java.util.List; 22 | 23 | import io.reactivex.Observable; 24 | import retrofit2.Retrofit; 25 | import retrofit2.http.GET; 26 | import retrofit2.http.Headers; 27 | import retrofit2.http.Path; 28 | 29 | import static me.jessyan.retrofiturlmanager.RetrofitUrlManager.DOMAIN_NAME_HEADER; 30 | 31 | /** 32 | * ================================================ 33 | * 展示 {@link Retrofit#create(Class)} 中需要传入的 ApiService 的使用方式 34 | * 存放关于 gank 的一些 API 35 | *

36 | * Created by Vea on 2016/11/30 37 | * ================================================ 38 | */ 39 | public interface GankService { 40 | 41 | String GANK_DOMAIN_NAME = "gank"; 42 | String GANK_DOMAIN = "http://gank.io"; 43 | 44 | /** 45 | * 福利 46 | */ 47 | @Headers({DOMAIN_NAME_HEADER + GANK_DOMAIN_NAME}) 48 | @GET("/api/data/福利/{num}/{page}") 49 | Observable>> getTechList(@Path("num") int num, @Path("page") int page); 50 | } 51 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/mvp/presenter/GirlPresenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.mvp.presenter; 17 | 18 | import com.vea.atoms.mvp.base.BasePresenter; 19 | import com.vea.atoms.mvp.commonsdk.adapter.ShowItemList; 20 | import com.vea.atoms.mvp.gank.mvp.contract.GirlContract; 21 | import com.vea.atoms.mvp.gank.mvp.model.entity.GankBaseResponse; 22 | import com.vea.atoms.mvp.gank.mvp.model.entity.GankItemBean; 23 | import com.vea.atoms.mvp.gank.mvp.model.service.GankService; 24 | import com.vea.atoms.mvp.gank.mvp.ui.fragment.GirlFragment; 25 | import com.vea.atoms.mvp.integration.IRepositoryManager; 26 | 27 | import java.util.List; 28 | 29 | import javax.inject.Inject; 30 | 31 | import io.reactivex.Observer; 32 | import io.reactivex.android.schedulers.AndroidSchedulers; 33 | import io.reactivex.disposables.Disposable; 34 | import io.reactivex.schedulers.Schedulers; 35 | import timber.log.Timber; 36 | 37 | /** 38 | * ================================================ 39 | * 40 | * @see GirlFragment 41 | * Created by Vea on 2016/11/24 42 | * ================================================ 43 | */ 44 | public class GirlPresenter extends BasePresenter implements GirlContract.Presenter { 45 | 46 | private int mCurrentPager = 1; 47 | 48 | private IRepositoryManager repositoryManager; 49 | 50 | @Inject 51 | public GirlPresenter(IRepositoryManager repositoryManager, GirlContract.View view) { 52 | super(view); 53 | this.repositoryManager = repositoryManager; 54 | } 55 | 56 | @Override 57 | public void getGankData(boolean isRefresh) { 58 | 59 | if (isRefresh) { 60 | mCurrentPager = 1; 61 | } else { 62 | mCurrentPager++; 63 | } 64 | 65 | repositoryManager.obtainRetrofitService(GankService.class) 66 | .getTechList(ShowItemList.NUM_OF_PAGE, mCurrentPager) 67 | .subscribeOn(Schedulers.io()) 68 | .doOnSubscribe(disposable -> { 69 | 70 | }).subscribeOn(AndroidSchedulers.mainThread()) 71 | .observeOn(AndroidSchedulers.mainThread()) 72 | .doFinally(() -> { 73 | 74 | }).subscribe(new Observer>>() { 75 | @Override 76 | public void onSubscribe(Disposable d) { 77 | addSubscription(d); 78 | } 79 | 80 | @Override 81 | public void onNext(GankBaseResponse> data) { 82 | if (!data.getError()) { 83 | getView().getGankDataSuccess(data.getResults(), isRefresh); 84 | } 85 | } 86 | 87 | @Override 88 | public void onError(Throwable e) { 89 | Timber.e(e); 90 | getView().getGankDataFailure(isRefresh); 91 | } 92 | 93 | @Override 94 | public void onComplete() { 95 | 96 | } 97 | }); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/mvp/ui/activity/GankMainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.mvp.ui.activity; 17 | 18 | import android.os.Bundle; 19 | import android.support.annotation.Nullable; 20 | import android.support.design.widget.TabLayout; 21 | import android.support.v4.view.ViewPager; 22 | 23 | import com.alibaba.android.arouter.facade.annotation.Autowired; 24 | import com.alibaba.android.arouter.facade.annotation.Route; 25 | import com.alibaba.android.arouter.launcher.ARouter; 26 | import com.vea.atoms.mvp.base.BaseActivity; 27 | import com.vea.atoms.mvp.commonsdk.adapter.ViewPagerAdapterFragment; 28 | import com.vea.atoms.mvp.commonsdk.core.RouterHub; 29 | import com.vea.atoms.mvp.gank.R; 30 | import com.vea.atoms.mvp.gank.R2; 31 | import com.vea.atoms.mvp.gank.mvp.ui.fragment.GirlFragment; 32 | 33 | import org.vea.atoms.mvp.commonservice.IUserService; 34 | 35 | import butterknife.BindView; 36 | import timber.log.Timber; 37 | 38 | /** 39 | * ================================================ 40 | * 承载{@link GirlFragment} 41 | *

42 | * Created by Vea on 2016/11/24 43 | * ================================================ 44 | */ 45 | @Route(path = RouterHub.GANK_MAIN_ACTIVITY) 46 | public class GankMainActivity extends BaseActivity { 47 | 48 | private ViewPagerAdapterFragment mAdapter; 49 | @BindView(R2.id.tab) 50 | TabLayout tablayout; 51 | @BindView(R2.id.viewpager) 52 | ViewPager viewpager; 53 | 54 | @Autowired 55 | IUserService obj; 56 | 57 | @Override 58 | protected int getLayoutId() { 59 | return R.layout.gank_activity_main; 60 | } 61 | 62 | @Override 63 | protected void initData(@Nullable Bundle savedInstanceState) { 64 | ARouter.getInstance().inject(this); 65 | 66 | mAdapter = new ViewPagerAdapterFragment(getSupportFragmentManager(), this); 67 | mAdapter.addTab("福利", "tag", GirlFragment.class, null); 68 | viewpager.setAdapter(mAdapter); 69 | tablayout.setupWithViewPager(viewpager); 70 | 71 | 72 | // 打印组件的数据传递 73 | if (obj != null) { 74 | Timber.d("--------id:" + obj.getId() + "----------AvatarUrl:" + obj.getAvatarUrl() + "----------Login:" + obj.getLogin()); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/mvp/ui/adapter/GirlListAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.mvp.ui.adapter; 17 | 18 | import android.content.Context; 19 | import android.support.v7.widget.RecyclerView; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | import android.widget.ImageView; 24 | 25 | import com.vea.atoms.mvp.commonsdk.adapter.BaseRecyclerAdapter; 26 | import com.vea.atoms.mvp.commonsdk.utils.ImageLoader; 27 | import com.vea.atoms.mvp.gank.R; 28 | import com.vea.atoms.mvp.gank.R2; 29 | import com.vea.atoms.mvp.gank.mvp.model.entity.GankItemBean; 30 | 31 | import butterknife.BindView; 32 | import butterknife.ButterKnife; 33 | 34 | 35 | /** 36 | * ================================================ 37 | * Created by Vea on 2016/11/24 38 | * ================================================ 39 | */ 40 | public class GirlListAdapter extends BaseRecyclerAdapter { 41 | 42 | public GirlListAdapter(Context context) { 43 | super(context, ONLY_FOOTER); 44 | } 45 | 46 | @Override 47 | protected RecyclerView.ViewHolder onCreateDefaultViewHolder(ViewGroup parent, int type) { 48 | return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.gank_item_girl, parent, false)); 49 | } 50 | 51 | @Override 52 | protected void onBindDefaultViewHolder(RecyclerView.ViewHolder holder, GankItemBean item, int position) { 53 | ViewHolder h = (ViewHolder) holder; 54 | ImageLoader.load(mContext, h.image, item.getUrl()); 55 | } 56 | 57 | public static class ViewHolder extends RecyclerView.ViewHolder { 58 | 59 | @BindView(R2.id.iv_girl) 60 | ImageView image; 61 | 62 | public ViewHolder(View itemView) { 63 | super(itemView); 64 | ButterKnife.bind(this, itemView); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Module-gank/src/main/java/com/vea/atoms/mvp/gank/mvp/ui/fragment/GirlFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.gank.mvp.ui.fragment; 17 | 18 | import android.app.Activity; 19 | import android.os.Bundle; 20 | import android.support.annotation.Nullable; 21 | import android.support.v7.widget.GridLayoutManager; 22 | import android.support.v7.widget.RecyclerView; 23 | 24 | import com.vea.atoms.mvp.base.BaseFragment; 25 | import com.vea.atoms.mvp.commonsdk.adapter.BaseRecyclerAdapter; 26 | import com.vea.atoms.mvp.commonsdk.adapter.IBaseShowItemList; 27 | import com.vea.atoms.mvp.commonsdk.adapter.ListFactory; 28 | import com.vea.atoms.mvp.commonsdk.adapter.RecyclerRefreshLayout; 29 | import com.vea.atoms.mvp.di.component.AppComponent; 30 | import com.vea.atoms.mvp.gank.R; 31 | import com.vea.atoms.mvp.gank.R2; 32 | import com.vea.atoms.mvp.gank.di.component.DaggerGankComponent; 33 | import com.vea.atoms.mvp.gank.mvp.contract.GirlContract; 34 | import com.vea.atoms.mvp.gank.mvp.model.entity.GankItemBean; 35 | import com.vea.atoms.mvp.gank.mvp.presenter.GirlPresenter; 36 | import com.vea.atoms.mvp.gank.mvp.ui.adapter.GirlListAdapter; 37 | import com.vea.atoms.mvp.utils.AtomsUtils; 38 | 39 | import java.util.List; 40 | 41 | import javax.inject.Inject; 42 | 43 | import butterknife.BindView; 44 | 45 | /** 46 | * ================================================ 47 | * 福利图片 48 | *

49 | * Created by Vea on 2016/11/24 50 | * ================================================ 51 | */ 52 | public class GirlFragment extends BaseFragment implements GirlContract.View, RecyclerRefreshLayout.SuperRefreshLayoutListener { 53 | 54 | @Inject 55 | GirlListAdapter adapter; 56 | 57 | 58 | // 如果不是必须要使用还可以使用Lzay 59 | // @Inject 60 | // Lazy adapter; 61 | 62 | @BindView(R2.id.recycler_view) 63 | RecyclerView recyclerView; 64 | @BindView(R2.id.swipe_refresh) 65 | RecyclerRefreshLayout refreshLayout; 66 | 67 | private IBaseShowItemList baseShowItemList; 68 | 69 | @Override 70 | protected void setupFragmentComponent(AppComponent appComponent) { 71 | 72 | DaggerGankComponent 73 | .builder() 74 | .appComponent(appComponent) 75 | .view(this) 76 | .build() 77 | .inject(this); 78 | } 79 | 80 | @Override 81 | protected int getLayoutId() { 82 | return R.layout.gank_fragment_tech; 83 | } 84 | 85 | @Override 86 | protected void initData(@Nullable Bundle savedInstanceState) { 87 | 88 | initRecycleView(); 89 | initRefreshLayout(); 90 | } 91 | 92 | /** 93 | * 初始化RecyclerView 94 | */ 95 | private void initRecycleView() { 96 | 97 | AtomsUtils.configRecyclerView(recyclerView, new GridLayoutManager(getActivity(), 2)); 98 | recyclerView.setAdapter(adapter); 99 | } 100 | 101 | /** 102 | * 初始化下拉刷新加载更多 103 | */ 104 | private void initRefreshLayout() { 105 | refreshLayout.setSuperRefreshLayoutListener(this); 106 | refreshLayout.post(() -> { 107 | refreshLayout.setRefreshing(true); 108 | onRefreshing(); 109 | }); 110 | } 111 | 112 | @Override 113 | public void getGankDataSuccess(List mList, boolean isRefresh) { 114 | if (baseShowItemList == null) { 115 | baseShowItemList = new ListFactory().createShowItemList(adapter, refreshLayout); 116 | } 117 | baseShowItemList.showData(isRefresh, mList); 118 | } 119 | 120 | @Override 121 | public void getGankDataFailure(boolean isRefresh) { 122 | refreshLayout.setRefreshing(false); 123 | if (isRefresh) { 124 | AtomsUtils.makeText(getActivity(), "刷新失败"); 125 | } else { 126 | adapter.setState(BaseRecyclerAdapter.STATE_LOAD_ERROR, true); 127 | } 128 | } 129 | 130 | @Override 131 | public void onRefreshing() { 132 | mPresenter.getGankData(true); 133 | } 134 | 135 | @Override 136 | public void onLoadMore() { 137 | mPresenter.getGankData(false); 138 | } 139 | 140 | @Override 141 | public Activity getFragmentActivity() { 142 | return getActivity(); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /Module-gank/src/main/res/layout/gank_activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /Module-gank/src/main/res/layout/gank_fragment_tech.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Module-gank/src/main/res/layout/gank_item_girl.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Module-gank/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Module-gank 3 | 4 | -------------------------------------------------------------------------------- /Module-gank/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /Module-gank/src/test/java/com/vea/atoms/mvp/gank/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.gank; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](image/atoms_banner_v1.0.jpg) 2 | 3 | 4 | ### 公众号 5 | 6 | 7 | ## License 8 | ``` 9 | Copyright 2018, Vea 10 | 11 | Licensed under the Apache License, Version 2.0 (the "License"); 12 | you may not use this file except in compliance with the License. 13 | You may obtain a copy of the License at 14 | 15 | http://www.apache.org/licenses/LICENSE-2.0 16 | 17 | Unless required by applicable law or agreed to in writing, software 18 | distributed under the License is distributed on an "AS IS" BASIS, 19 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | See the License for the specific language governing permissions and 21 | limitations under the License. 22 | ``` 23 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | compileSdkVersion rootProject.ext.android["compileSdkVersion"] 6 | defaultConfig { 7 | applicationId "com.vea.atoms.mvp.demo" 8 | minSdkVersion rootProject.ext.android["minSdkVersion"] 9 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 10 | versionCode Integer.parseInt(APP_CODE) 11 | versionName APP_VERSION 12 | javaCompileOptions { 13 | annotationProcessorOptions { 14 | arguments = [moduleName: project.getName()] 15 | includeCompileClasspath true 16 | } 17 | } 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | lintOptions { 27 | disable 'InvalidPackage' 28 | disable "ResourceType" 29 | abortOnError false 30 | } 31 | 32 | compileOptions { 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | sourceCompatibility JavaVersion.VERSION_1_8 35 | } 36 | } 37 | 38 | dependencies { 39 | implementation fileTree(include: ['*.jar'], dir: 'libs') 40 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 41 | 42 | // 使用 runtimeOnly 依赖业务组件, 可实现业务组件的代码在编译时对宿主 App 不可见 43 | if (!isRunGankModule.toBoolean()) { 44 | runtimeOnly project(':Module-gank') 45 | } 46 | 47 | 48 | 49 | implementation project(':CommonSDK') 50 | implementation project(":CommonService") 51 | implementation rootProject.ext.dependencies["swipeback"] 52 | annotationProcessor rootProject.ext.dependencies["dagger2-compiler"] 53 | annotationProcessor rootProject.ext.dependencies["arouter-compiler"] 54 | annotationProcessor rootProject.ext.dependencies["butterknife-compiler"] 55 | 56 | debugImplementation rootProject.ext.dependencies["canary-debug"] 57 | releaseImplementation rootProject.ext.dependencies["canary-release"] 58 | 59 | } 60 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/org/vea/atoms/mvp/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package org.vea.atoms.mvp; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("org.vea.atoms.mvp", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 21 | 24 | 27 | 28 | 32 | 33 | 34 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/app/AppLifecyclesImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.demo.app; 17 | 18 | import android.app.Application; 19 | import android.content.Context; 20 | import android.support.annotation.NonNull; 21 | 22 | import com.from.view.swipeback.SwipeBackHelper; 23 | import com.squareup.leakcanary.LeakCanary; 24 | import com.vea.atoms.mvp.app.AppLifecycles; 25 | 26 | /** 27 | * ================================================ 28 | * 展示 {@link AppLifecycles} 的用法 29 | *

30 | * Created by Vea on 04/09/2017 17:12 31 | * ================================================ 32 | */ 33 | public class AppLifecyclesImpl implements AppLifecycles { 34 | 35 | @Override 36 | public void attachBaseContext(@NonNull Application application, @NonNull Context base) { 37 | // MultiDex.install(base); //这里比 onCreate 先执行,常用于 MultiDex 初始化,插件化框架的初始化 38 | } 39 | 40 | @Override 41 | public void onCreate(@NonNull Application application) { 42 | if (LeakCanary.isInAnalyzerProcess(application)) { 43 | // This process is dedicated to LeakCanary for heap analysis. 44 | // You should not init your app in this process. 45 | return; 46 | } 47 | 48 | LeakCanary.install(application); 49 | // 一键侧滑返回 50 | SwipeBackHelper.init(application); 51 | 52 | } 53 | 54 | @Override 55 | public void onTerminate(@NonNull Application application) { 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/app/GlobalConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.demo.app; 17 | 18 | import android.content.Context; 19 | 20 | import com.vea.atoms.mvp.app.AppDelegate; 21 | import com.vea.atoms.mvp.app.AppLifecycles; 22 | import com.vea.atoms.mvp.di.module.GlobalConfigModule; 23 | import com.vea.atoms.mvp.integration.ConfigModule; 24 | import com.vea.atoms.mvp.integration.ManifestParser; 25 | 26 | import java.util.List; 27 | 28 | 29 | /** 30 | * ================================================ 31 | * App 的全局配置信息在此配置, 需要将此实现类声明到 AndroidManifest 中 32 | * ConfigModule 的实现类可以有无数多个, 在 Application 中只是注册回调, 并不会影响性能 (多个 ConfigModule 在多 Module 环境下尤为受用) 33 | * 不过要注意 ConfigModule 接口的实现类对象是通过反射生成的, 这里会有些性能损耗 34 | * 35 | * @see AppDelegate 36 | * @see ManifestParser 37 | * Created by Vea on 12/04/2017 17:25 38 | * ================================================ 39 | */ 40 | public final class GlobalConfiguration implements ConfigModule { 41 | 42 | @Override 43 | public void applyOptions(Context context, GlobalConfigModule.Builder builder) { 44 | } 45 | 46 | @Override 47 | public void injectAppLifecycle(Context context, List lifecycles) { 48 | // AppLifecycles 的所有方法都会在基类 Application 的对应的生命周期中被调用,所以在对应的方法中可以扩展一些自己需要的逻辑 49 | // 可以根据不同的逻辑添加多个实现类 50 | lifecycles.add(new AppLifecyclesImpl()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/di/component/DemoComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.demo.di.component; 17 | 18 | import com.vea.atoms.mvp.demo.di.module.DemoModule; 19 | import com.vea.atoms.mvp.demo.mvp.ui.MainActivity; 20 | import com.vea.atoms.mvp.di.component.AppComponent; 21 | import com.vea.atoms.mvp.di.scope.ActivityScope; 22 | 23 | import dagger.Component; 24 | 25 | /** 26 | * ================================================ 27 | * 展示 Component 的用法 28 | *

29 | * Created by Vea on 09/04/2016 11:17 30 | * ================================================ 31 | */ 32 | @ActivityScope 33 | @Component(modules = DemoModule.class, dependencies = AppComponent.class) 34 | public interface DemoComponent { 35 | 36 | void inject(MainActivity activity); 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/di/module/DemoModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.demo.di.module; 17 | 18 | import dagger.Module; 19 | 20 | /** 21 | * ================================================ 22 | * 展示 Module 的用法 23 | *

24 | * Created by Vea on 09/04/2016 11:10 25 | * ================================================ 26 | * e呃呃呃呃呃 27 | */ 28 | @Module 29 | public class DemoModule { 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/mvp/adapter/ManListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.demo.mvp.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | 10 | import com.vea.atoms.mvp.commonsdk.adapter.BaseRecyclerAdapter; 11 | import com.vea.atoms.mvp.commonsdk.utils.ImageLoader; 12 | import com.vea.atoms.mvp.demo.R; 13 | import com.vea.atoms.mvp.demo.mvp.model.entity.User; 14 | 15 | import butterknife.BindView; 16 | import butterknife.ButterKnife; 17 | 18 | /** 19 | * ================================================ 20 | * Created by Vea on 2018/8/26 21 | * ================================================ 22 | */ 23 | public class ManListAdapter extends BaseRecyclerAdapter { 24 | 25 | public ManListAdapter(Context context) { 26 | super(context, ONLY_FOOTER); 27 | } 28 | 29 | @Override 30 | protected RecyclerView.ViewHolder onCreateDefaultViewHolder(ViewGroup parent, int type) { 31 | return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_man, parent, false)); 32 | } 33 | 34 | @Override 35 | protected void onBindDefaultViewHolder(RecyclerView.ViewHolder holder, User item, int position) { 36 | ViewHolder h = (ViewHolder) holder; 37 | ImageLoader.load(mContext, h.image, item.getAvatarUrl()); 38 | } 39 | 40 | public static class ViewHolder extends RecyclerView.ViewHolder { 41 | 42 | @BindView(R.id.iv_girl) 43 | ImageView image; 44 | 45 | public ViewHolder(View itemView) { 46 | super(itemView); 47 | ButterKnife.bind(this, itemView); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/mvp/contract/MainContract.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.demo.mvp.contract; 2 | 3 | import com.vea.atoms.mvp.base.IPresenter; 4 | import com.vea.atoms.mvp.base.IView; 5 | import com.vea.atoms.mvp.demo.mvp.model.entity.User; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by vea on 2018/8/24. 11 | */ 12 | 13 | public interface MainContract { 14 | 15 | 16 | interface View extends IView { 17 | 18 | void getUserSuccess(List users, boolean isRefresh); 19 | 20 | void getUserFailure(boolean isRefresh); 21 | } 22 | 23 | interface Presenter extends IPresenter { 24 | 25 | void getUser(int lastIdQueried, boolean isRefresh); 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/mvp/model/entity/BaseResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.demo.mvp.model.entity; 17 | 18 | import com.vea.atoms.mvp.demo.mvp.model.service.DemoService; 19 | 20 | import java.io.Serializable; 21 | 22 | /** 23 | * ================================================ 24 | * 如果你服务器返回的数据格式固定为这种方式(这里只提供思想,服务器返回的数据格式可能不一致,可根据自家服务器返回的格式作更改) 25 | * 指定范型即可改变 {@code data} 字段的类型, 达到重用 {@link BaseResponse}, 如果你实在看不懂, 请忽略 26 | *

27 | * Created by Vea on 26/09/2016 15:19 28 | * ================================================ 29 | */ 30 | public class BaseResponse implements Serializable { 31 | private T data; 32 | private String code; 33 | private String msg; 34 | 35 | public T getData() { 36 | return data; 37 | } 38 | 39 | public String getCode() { 40 | return code; 41 | } 42 | 43 | public String getMsg() { 44 | return msg; 45 | } 46 | 47 | /** 48 | * 请求是否成功 49 | * 50 | * @return 51 | */ 52 | public boolean isSuccess() { 53 | if (code.equals(DemoService.RequestSuccess)) { 54 | return true; 55 | } else { 56 | return false; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/mvp/model/entity/User.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.demo.mvp.model.entity; 17 | 18 | 19 | import org.vea.atoms.mvp.commonservice.IUserService; 20 | 21 | /** 22 | * ================================================ 23 | * User 实体类 24 | *

25 | * Created by Vea on 04/09/2016 17:14 26 | * ================================================ 27 | */ 28 | public class User implements IUserService { 29 | 30 | private int id; 31 | private String login; 32 | private String avatar_url; 33 | 34 | 35 | public void setId(int id) { 36 | this.id = id; 37 | } 38 | 39 | public void setLogin(String login) { 40 | this.login = login; 41 | } 42 | 43 | @Override 44 | public String getAvatarUrl() { 45 | return avatar_url; 46 | } 47 | 48 | @Override 49 | public int getId() { 50 | return id; 51 | } 52 | 53 | @Override 54 | public String getLogin() { 55 | return login; 56 | } 57 | 58 | @Override 59 | public void setAvatarUrl(String avatar_url) { 60 | this.avatar_url = avatar_url; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/mvp/model/service/DemoService.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.demo.mvp.model.service; 2 | 3 | import com.vea.atoms.mvp.demo.mvp.model.entity.User; 4 | 5 | import java.util.List; 6 | 7 | import io.reactivex.Observable; 8 | import retrofit2.http.GET; 9 | import retrofit2.http.Headers; 10 | import retrofit2.http.Query; 11 | 12 | 13 | /** 14 | * ================================================ 15 | * 服务端Api相关接口定义 16 | *

17 | * Created by Vea on 2018/8/23. 18 | * ================================================ 19 | */ 20 | public interface DemoService { 21 | 22 | String APP_DOMAIN = "https://api.github.com"; 23 | String RequestSuccess = "0"; 24 | 25 | 26 | String HEADER_API_VERSION = "Accept: application/vnd.github.v3+json"; 27 | 28 | @Headers({HEADER_API_VERSION}) 29 | @GET("/users") 30 | Observable> getUsers(@Query("since") int lastIdQueried, @Query("per_page") int perPage); 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/mvp/presenter/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.demo.mvp.presenter; 2 | 3 | import com.vea.atoms.mvp.base.BasePresenter; 4 | import com.vea.atoms.mvp.commonsdk.adapter.ShowItemList; 5 | import com.vea.atoms.mvp.demo.mvp.contract.MainContract; 6 | import com.vea.atoms.mvp.demo.mvp.model.entity.User; 7 | import com.vea.atoms.mvp.demo.mvp.model.service.DemoService; 8 | import com.vea.atoms.mvp.integration.IRepositoryManager; 9 | 10 | import java.util.List; 11 | 12 | import javax.inject.Inject; 13 | 14 | import io.reactivex.Observer; 15 | import io.reactivex.android.schedulers.AndroidSchedulers; 16 | import io.reactivex.disposables.Disposable; 17 | import io.reactivex.schedulers.Schedulers; 18 | import timber.log.Timber; 19 | 20 | /** 21 | * ================================================ 22 | * 首页 Presenter 23 | *

24 | * Created by Vea on 2018/8/23. 25 | * ================================================ 26 | */ 27 | public class MainPresenter extends BasePresenter implements MainContract.Presenter { 28 | 29 | private IRepositoryManager repositoryManager; 30 | 31 | @Inject 32 | public MainPresenter(IRepositoryManager repositoryManager) { 33 | this.repositoryManager = repositoryManager; 34 | } 35 | 36 | @Override 37 | public void getUser(int lastIdQueried, boolean isRefresh) { 38 | 39 | repositoryManager.obtainRetrofitService(DemoService.class) 40 | .getUsers(lastIdQueried, ShowItemList.NUM_OF_PAGE) 41 | .subscribeOn(Schedulers.io()) 42 | .doOnSubscribe(disposable -> { 43 | // 订阅之前常用于显示loading 44 | // TODO 45 | }).subscribeOn(AndroidSchedulers.mainThread()) 46 | .observeOn(AndroidSchedulers.mainThread()) // 在主线程中回调订阅事件 47 | .doFinally(() -> { 48 | // 结束之后隐藏LoadingView 49 | }) 50 | .subscribe(new Observer>() { 51 | @Override 52 | public void onSubscribe(Disposable d) { 53 | addSubscription(d); 54 | } 55 | 56 | @Override 57 | public void onNext(List users) { 58 | getView().getUserSuccess(users, isRefresh); 59 | } 60 | 61 | @Override 62 | public void onError(Throwable e) { 63 | Timber.d(e); 64 | getView().getUserFailure(isRefresh); 65 | } 66 | 67 | @Override 68 | public void onComplete() { 69 | 70 | } 71 | }); 72 | 73 | } 74 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/mvp/ui/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.demo.mvp.ui; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.widget.GridLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.view.View; 8 | import android.widget.ImageView; 9 | 10 | import com.alibaba.android.arouter.facade.annotation.Route; 11 | import com.alibaba.android.arouter.launcher.ARouter; 12 | import com.vea.atoms.mvp.base.BaseActivity; 13 | import com.vea.atoms.mvp.commonsdk.adapter.BaseRecyclerAdapter; 14 | import com.vea.atoms.mvp.commonsdk.adapter.IBaseShowItemList; 15 | import com.vea.atoms.mvp.commonsdk.adapter.ListFactory; 16 | import com.vea.atoms.mvp.commonsdk.adapter.RecyclerRefreshLayout; 17 | import com.vea.atoms.mvp.commonsdk.core.RouterHub; 18 | import com.vea.atoms.mvp.demo.R; 19 | import com.vea.atoms.mvp.demo.di.component.DaggerDemoComponent; 20 | import com.vea.atoms.mvp.demo.mvp.adapter.ManListAdapter; 21 | import com.vea.atoms.mvp.demo.mvp.contract.MainContract; 22 | import com.vea.atoms.mvp.demo.mvp.model.entity.User; 23 | import com.vea.atoms.mvp.demo.mvp.presenter.MainPresenter; 24 | import com.vea.atoms.mvp.di.component.AppComponent; 25 | import com.vea.atoms.mvp.utils.AtomsUtils; 26 | 27 | import java.util.List; 28 | 29 | import butterknife.BindView; 30 | import butterknife.OnClick; 31 | 32 | /** 33 | * ================================================ 34 | * 首页Activity,展示图片 35 | *

36 | * Created by Vea on 2018/8/23. 37 | * ================================================ 38 | */ 39 | @Route(path = RouterHub.APP_MAIN_ACTIVITY) 40 | public class MainActivity extends BaseActivity implements MainContract.View, RecyclerRefreshLayout.SuperRefreshLayoutListener { 41 | 42 | private ManListAdapter adapter; 43 | 44 | private IBaseShowItemList baseShowItemList; 45 | 46 | @BindView(R.id.recycler_view) 47 | RecyclerView recyclerView; 48 | @BindView(R.id.swipe_refresh) 49 | RecyclerRefreshLayout refreshLayout; 50 | 51 | @BindView(R.id.image_mouth) 52 | ImageView imageMouth; 53 | 54 | @Override 55 | protected void setupActivityComponent(AppComponent appComponent) { 56 | DaggerDemoComponent 57 | .builder() 58 | .appComponent(appComponent) 59 | .build() 60 | .inject(this); 61 | } 62 | 63 | @Override 64 | protected int getLayoutId() { 65 | return R.layout.activity_main; 66 | } 67 | 68 | @Override 69 | protected void initData(@Nullable Bundle savedInstanceState) { 70 | ARouter.getInstance().inject(this); 71 | 72 | initRecycleView(); 73 | initRefreshLayout(); 74 | } 75 | 76 | /** 77 | * 初始化下拉刷新加载更多 78 | */ 79 | private void initRefreshLayout() { 80 | refreshLayout.setSuperRefreshLayoutListener(this); 81 | refreshLayout.post(() -> { 82 | refreshLayout.setRefreshing(true); 83 | onRefreshing(); 84 | }); 85 | } 86 | 87 | /** 88 | * 初始化RecyclerView 89 | */ 90 | private void initRecycleView() { 91 | adapter = new ManListAdapter(this); 92 | adapter.setState(BaseRecyclerAdapter.STATE_HIDE, false); 93 | 94 | AtomsUtils.configRecyclerView(recyclerView, new GridLayoutManager(this, 2)); 95 | recyclerView.setAdapter(adapter); 96 | } 97 | 98 | @Override 99 | public void getUserSuccess(List users, boolean isRefresh) { 100 | if (users != null && users.size() > 0) { 101 | if (baseShowItemList == null) { 102 | baseShowItemList = new ListFactory().createShowItemList(adapter, refreshLayout); 103 | } 104 | baseShowItemList.showData(isRefresh, users); 105 | } 106 | } 107 | 108 | @Override 109 | public void getUserFailure(boolean isRefresh) { 110 | refreshLayout.setRefreshing(false); 111 | if (isRefresh) { 112 | AtomsUtils.makeText(this, "刷新失败"); 113 | } else { 114 | adapter.setState(BaseRecyclerAdapter.STATE_LOAD_ERROR, true); 115 | } 116 | } 117 | 118 | @Override 119 | public void onRefreshing() { 120 | mPresenter.getUser(1, true); 121 | } 122 | 123 | @Override 124 | public void onLoadMore() { 125 | // 总size-1 再减去底布局-1 126 | int id = adapter.getItem(adapter.getItemCount() - 1 - 1).getId(); 127 | mPresenter.getUser(id, false); 128 | } 129 | 130 | @OnClick({R.id.image_mouth}) 131 | public void onViewClicked(View view) { 132 | switch (view.getId()) { 133 | case R.id.image_mouth: 134 | if (adapter.getItems() != null && adapter.getItems().size() > 10) { 135 | 136 | /** 137 | * 展示组件之间数据传递 138 | * 一般情况下并不需要传递整个user对象,如果只需要某个key,name 139 | * 只需设置withString(k,v)即可。 传递对象可使用withObject 140 | */ 141 | User item = adapter.getItem(0); 142 | ARouter.getInstance() 143 | .build(RouterHub.GANK_MAIN_ACTIVITY) 144 | .withObject("obj", item) 145 | .navigation(); 146 | } 147 | break; 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/mvp/ui/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.demo.mvp.ui; 2 | 3 | import android.os.Bundle; 4 | import android.os.Handler; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import com.alibaba.android.arouter.launcher.ARouter; 8 | import com.vea.atoms.mvp.commonsdk.core.RouterHub; 9 | 10 | public class SplashActivity extends AppCompatActivity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | // setContentView(R.layout.activity_splash); 16 | 17 | new Handler().postDelayed(new Runnable() { 18 | @Override 19 | public void run() { 20 | ARouter.getInstance().build(RouterHub.APP_MAIN_ACTIVITY).navigation(); 21 | finish(); 22 | } 23 | }, 1000); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/vea/atoms/mvp/demo/utils/JsonServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.demo.utils; 2 | 3 | import android.content.Context; 4 | 5 | import com.alibaba.android.arouter.facade.annotation.Route; 6 | import com.alibaba.android.arouter.facade.service.SerializationService; 7 | import com.alibaba.fastjson.JSON; 8 | 9 | import java.lang.reflect.Type; 10 | 11 | /** 12 | * Used for json converter 13 | * 14 | * @author zhilong Contact me. 15 | * @version 1.0 16 | * @since 2017/4/10 下午2:10 17 | */ 18 | @Route(path = "/service/json") 19 | public class JsonServiceImpl implements SerializationService { 20 | @Override 21 | public void init(Context context) { 22 | 23 | } 24 | 25 | @Override 26 | public T json2Object(String text, Class clazz) { 27 | return JSON.parseObject(text, clazz); 28 | } 29 | 30 | @Override 31 | public String object2Json(Object instance) { 32 | return JSON.toJSONString(instance); 33 | } 34 | 35 | @Override 36 | public T parseObject(String input, Type clazz) { 37 | return JSON.parseObject(input, clazz); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/layer_splash_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 12 | 13 | 20 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 39 | 40 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_man.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-xhdpi/ic_girl.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/splash_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/app/src/main/res/mipmap-xxxhdpi/splash_logo.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #663366 4 | #663366 5 | #FF4081 6 | #333333 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MVPAtoms 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/org/vea/atoms/mvp/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package org.vea.atoms.mvp; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /atoms/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /atoms/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | compileSdkVersion rootProject.ext.android["compileSdkVersion"] 6 | 7 | defaultConfig { 8 | minSdkVersion rootProject.ext.android["minSdkVersion"] 9 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 10 | versionCode 1 11 | versionName APP_VERSION 12 | } 13 | 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | 21 | compileOptions { 22 | targetCompatibility JavaVersion.VERSION_1_8 23 | sourceCompatibility JavaVersion.VERSION_1_8 24 | } 25 | 26 | } 27 | 28 | dependencies { 29 | 30 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 31 | def appDependencies = rootProject.ext.dependencies 32 | 33 | api rootProject.ext.dependencies["appcompat-v7"] 34 | api rootProject.ext.dependencies["design"] 35 | api rootProject.ext.dependencies["support-v4"] 36 | api rootProject.ext.dependencies["recyclerview-v7"] 37 | api rootProject.ext.dependencies["cardview-v7"] 38 | api rootProject.ext.dependencies["constraintLayout"] 39 | 40 | api rootProject.ext.dependencies["rxjava2"] 41 | api rootProject.ext.dependencies["rxandroid2"] 42 | api rootProject.ext.dependencies["retrofit"] 43 | api rootProject.ext.dependencies["retrofit-converter-gson"] 44 | api rootProject.ext.dependencies["retrofit-adapter-rxjava2"] 45 | 46 | api rootProject.ext.dependencies["butterknife"] 47 | 48 | api rootProject.ext.dependencies["dagger2"] 49 | annotationProcessor rootProject.ext.dependencies["dagger2-compiler"] 50 | 51 | api rootProject.ext.dependencies["timber"] 52 | api rootProject.ext.dependencies["multidex"] 53 | api appDependencies["androideventbus"] 54 | api appDependencies["avi_loading"] 55 | } 56 | -------------------------------------------------------------------------------- /atoms/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /atoms/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/app/ActivityManager.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.app; 2 | 3 | import android.app.Activity; 4 | 5 | import java.util.Stack; 6 | 7 | /** 8 | * activity堆栈式管理 9 | */ 10 | public class ActivityManager { 11 | private static Stack activityStack; 12 | private static ActivityManager instance; 13 | 14 | private ActivityManager() { 15 | } 16 | 17 | /** 18 | * 单一实例 19 | */ 20 | public static ActivityManager getAppManager() { 21 | if (instance == null) { 22 | instance = new ActivityManager(); 23 | } 24 | 25 | if (activityStack == null) { 26 | activityStack = new Stack(); 27 | } 28 | 29 | return instance; 30 | } 31 | 32 | /** 33 | * 获取指定的Activity 34 | * 35 | * @author kymjs 36 | */ 37 | public static Activity getActivity(Class cls) { 38 | if (activityStack != null) 39 | for (Activity activity : activityStack) { 40 | if (activity.getClass().equals(cls)) { 41 | return activity; 42 | } 43 | } 44 | return null; 45 | } 46 | 47 | /** 48 | * 添加Activity到堆栈 49 | */ 50 | public void addActivity(Activity activity) { 51 | activityStack.add(activity); 52 | } 53 | 54 | /** 55 | * 获取当前Activity(堆栈中最后一个压入的) 56 | */ 57 | public Activity currentActivity() { 58 | Activity activity = activityStack.lastElement(); 59 | return activity; 60 | } 61 | 62 | /** 63 | * 结束当前Activity(堆栈中最后一个压入的) 64 | */ 65 | public void finishActivity() { 66 | Activity activity = activityStack.lastElement(); 67 | finishActivity(activity); 68 | } 69 | 70 | /** 71 | * 结束指定的Activity 72 | */ 73 | public void finishActivity(Activity activity) { 74 | if (activity != null && activityStack.contains(activity)) { 75 | activity.finish(); 76 | } 77 | } 78 | 79 | /** 80 | * 结束指定的Activity 81 | */ 82 | public void removeActivity(Activity activity) { 83 | if (activity != null && activityStack.contains(activity)) { 84 | activityStack.remove(activity); 85 | } 86 | } 87 | 88 | /** 89 | * 结束指定类名的Activity 90 | */ 91 | public void finishActivity(Class cls) { 92 | for (Activity activity : activityStack) { 93 | if (activity.getClass().equals(cls)) { 94 | finishActivity(activity); 95 | break; 96 | } 97 | } 98 | } 99 | 100 | /** 101 | * 结束所有Activity 102 | */ 103 | public void finishAllActivity() { 104 | for (int i = 0; i < activityStack.size(); i++) { 105 | if (null != activityStack.get(i)) { 106 | finishActivity(activityStack.get(i)); 107 | } 108 | } 109 | activityStack.clear(); 110 | } 111 | 112 | /** 113 | * 退出应用程序 114 | */ 115 | public void AppExit() { 116 | try { 117 | finishAllActivity(); 118 | // System.exit(0); 119 | } catch (Exception e) { 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/app/AppDelegate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.app; 17 | 18 | import android.app.Application; 19 | import android.content.Context; 20 | import android.support.annotation.NonNull; 21 | 22 | import com.vea.atoms.mvp.di.component.AppComponent; 23 | import com.vea.atoms.mvp.di.component.DaggerAppComponent; 24 | import com.vea.atoms.mvp.di.module.GlobalConfigModule; 25 | import com.vea.atoms.mvp.integration.ConfigModule; 26 | import com.vea.atoms.mvp.integration.ManifestParser; 27 | import com.vea.atoms.mvp.utils.AtomsUtils; 28 | import com.vea.atoms.mvp.utils.Preconditions; 29 | 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | 33 | /** 34 | * ================================================ 35 | * AppDelegate 可以代理 Application 的生命周期,在对应的生命周期,执行对应的逻辑,因为 Java 只能单继承 36 | * 所以当遇到某些三方库需要继承于它的 Application 的时候,就只有自定义 Application 并继承于三方库的 Application 37 | * 这时就不用再继承 BaseApplication,只用在自定义Application中对应的生命周期调用AppDelegate对应的方法 38 | * (Application一定要实现APP接口),框架就能照常运行 39 | * 40 | * @see BaseApplication 41 | * Created by Vea on 24/04/2017 09:44 42 | * ================================================ 43 | */ 44 | public class AppDelegate implements IApp, AppLifecycles { 45 | 46 | private Application mApplication; 47 | private AppComponent mAppComponent; 48 | 49 | private List mAppLifecycles = new ArrayList<>(); 50 | 51 | private List mModules; 52 | 53 | public AppDelegate(@NonNull Context context) { 54 | 55 | //用反射, 将 AndroidManifest.xml 中带有 ConfigModule 标签的 class 转成对象集合(List) 56 | this.mModules = new ManifestParser(context).parse(); 57 | 58 | //遍历之前获得的集合, 执行每一个 ConfigModule 实现类的某些方法 59 | for (ConfigModule module : mModules) { 60 | 61 | //将框架外部, 开发者实现的 Application 的生命周期回调 (AppLifecycles) 存入 mAppLifecycles 集合 (此时还未注册回调) 62 | module.injectAppLifecycle(context, mAppLifecycles); 63 | } 64 | } 65 | 66 | @Override 67 | public void attachBaseContext(@NonNull Application application, @NonNull Context base) { 68 | 69 | //遍历 mAppLifecycles, 执行所有已注册的 AppLifecycles 的 attachBaseContext() 方法 (框架外部, 开发者扩展的逻辑) 70 | for (AppLifecycles lifecycle : mAppLifecycles) { 71 | lifecycle.attachBaseContext(application, base); 72 | } 73 | } 74 | 75 | @Override 76 | public void onCreate(@NonNull Application application) { 77 | this.mApplication = application; 78 | mAppComponent = DaggerAppComponent 79 | .builder() 80 | .application(mApplication)//提供application 81 | .globalConfigModule(getGlobalConfigModule(mApplication, mModules))//全局配置 82 | .build(); 83 | mAppComponent.injectDelegate(this); 84 | 85 | 86 | //执行框架外部, 开发者扩展的 App onCreate 逻辑 87 | for (AppLifecycles lifecycle : mAppLifecycles) { 88 | lifecycle.onCreate(mApplication); 89 | } 90 | } 91 | 92 | @Override 93 | public void onTerminate(@NonNull Application application) { 94 | 95 | if (mAppLifecycles != null && mAppLifecycles.size() > 0) { 96 | for (AppLifecycles lifecycle : mAppLifecycles) { 97 | lifecycle.onTerminate(mApplication); 98 | } 99 | } 100 | this.mAppComponent = null; 101 | this.mAppLifecycles = null; 102 | this.mApplication = null; 103 | } 104 | 105 | /** 106 | * 将app的全局配置信息封装进module(使用Dagger注入到需要配置信息的地方) 107 | * 需要在AndroidManifest中声明{@link ConfigModule}的实现类,和Glide的配置方式相似 108 | * 109 | * @return GlobalConfigModule 110 | */ 111 | private GlobalConfigModule getGlobalConfigModule(Context context, List modules) { 112 | 113 | GlobalConfigModule.Builder builder = GlobalConfigModule 114 | .builder(); 115 | 116 | //遍历 ConfigModule 集合, 给全局配置 GlobalConfigModule 添加参数 117 | for (ConfigModule module : modules) { 118 | module.applyOptions(context, builder); 119 | } 120 | 121 | return builder.build(); 122 | } 123 | 124 | /** 125 | * 将 {@link AppComponent} 返回出去, 供其它地方使用, {@link AppComponent} 接口中声明的方法返回的实例, 在 {@link #getAppComponent()} 拿到对象后都可以直接使用 126 | * 127 | * @return AppComponent 128 | * @see AtomsUtils#obtainAppComponentFromContext(Context) 可直接获取 {@link AppComponent} 129 | */ 130 | @NonNull 131 | @Override 132 | public AppComponent getAppComponent() { 133 | Preconditions.checkNotNull(mAppComponent, 134 | "%s cannot be null,first call %s#onCreate(Application) in %s#onCreate()", 135 | AppComponent.class.getName(), getClass().getName(), Application.class.getName()); 136 | return mAppComponent; 137 | } 138 | } 139 | 140 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/app/AppLifecycles.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.app; 17 | 18 | import android.app.Application; 19 | import android.content.Context; 20 | import android.support.annotation.NonNull; 21 | 22 | /** 23 | * ================================================ 24 | * 用于代理 {@link Application} 的生命周期 25 | * 26 | * @see AppDelegate 27 | * Created by Vea on 2018/8/20 28 | * ================================================ 29 | */ 30 | public interface AppLifecycles { 31 | 32 | /** 33 | * @param application 最初设计上没有这个参数,为了给插件化调用。如何插件化可参考360RePlugin 34 | * @param base Context 35 | */ 36 | void attachBaseContext(@NonNull Application application, @NonNull Context base); 37 | 38 | void onCreate(@NonNull Application application); 39 | 40 | void onTerminate(@NonNull Application application); 41 | } -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/app/AppManager.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.app; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * AppManager 11 | * 12 | * @author lishide 13 | * @date 2018/12/12 14 | */ 15 | public class AppManager { 16 | 17 | private Application mApplication; 18 | 19 | private List mLogouts; 20 | 21 | public static class AppManagerHolder { 22 | private static AppManager sAppManager = new AppManager(); 23 | } 24 | 25 | public static AppManager getInstance() { 26 | return AppManagerHolder.sAppManager; 27 | } 28 | 29 | private AppManager() { 30 | mApplication = initApplication(); 31 | } 32 | 33 | public Application getApplication() { 34 | return mApplication; 35 | } 36 | 37 | static Application initApplication() { 38 | try { 39 | //通过反射的方式来获取当前进程的application对象 40 | Application app = (Application) Class.forName("android.app.ActivityThread") 41 | .getMethod("currentApplication").invoke(null); 42 | if (app != null) { 43 | return app; 44 | } 45 | } catch (Exception e) { 46 | e.printStackTrace(); 47 | } 48 | try { 49 | Application app = (Application) Class.forName("android.app.AppGlobals") 50 | .getMethod("getInitialApplication").invoke(null); 51 | if (app != null) { 52 | return app; 53 | } 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | } 57 | return null; 58 | } 59 | 60 | public void addLogout(ILogout logout) { 61 | if (mLogouts == null) { 62 | mLogouts = new ArrayList<>(); 63 | } 64 | 65 | mLogouts.add(logout); 66 | } 67 | 68 | public void logout(Context context) { 69 | if (mLogouts != null) { 70 | for (ILogout info : mLogouts) { 71 | info.logout(context); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/app/BaseApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.app; 17 | 18 | import android.app.Activity; 19 | import android.app.Application; 20 | import android.content.Context; 21 | import android.os.Bundle; 22 | import android.support.annotation.NonNull; 23 | import android.support.multidex.MultiDex; 24 | 25 | import com.vea.atoms.mvp.di.component.AppComponent; 26 | import com.vea.atoms.mvp.utils.AtomsUtils; 27 | import com.vea.atoms.mvp.utils.Preconditions; 28 | 29 | import timber.log.Timber; 30 | 31 | /** 32 | * ================================================ 33 | * BaseApplication每个模块的Application都使用B 34 | *

35 | * Created by Vea on 2018/8/20 36 | * ================================================ 37 | */ 38 | public class BaseApplication extends Application implements IApp { 39 | 40 | private AppLifecycles mAppDelegate; 41 | 42 | private ActivityLifecycleCallbacks mActivityLifecycleCallbacks; 43 | 44 | private static BaseApplication mApplication; 45 | 46 | public static BaseApplication getInstance() { 47 | return mApplication; 48 | } 49 | 50 | public static void setApplication(BaseApplication mApplication) { 51 | BaseApplication.mApplication = mApplication; 52 | } 53 | 54 | @Override 55 | protected void attachBaseContext(Context base) { 56 | super.attachBaseContext(base); 57 | MultiDex.install(base); 58 | 59 | if (mAppDelegate == null) { 60 | this.mAppDelegate = new AppDelegate(base); 61 | } 62 | this.mAppDelegate.attachBaseContext(this, base); 63 | } 64 | 65 | @Override 66 | public void onCreate() { 67 | super.onCreate(); 68 | setApplication(this); 69 | if (mAppDelegate != null) { 70 | this.mAppDelegate.onCreate(this); 71 | } 72 | 73 | Timber.d("BaseApplication#onCreate"); 74 | 75 | mActivityLifecycleCallbacks = new ActivityLifecycleCallbacks() { 76 | @Override 77 | public void onActivityCreated(Activity activity, Bundle bundle) { 78 | ActivityManager.getAppManager().addActivity(activity); 79 | } 80 | 81 | @Override 82 | public void onActivityStarted(Activity activity) { 83 | 84 | } 85 | 86 | @Override 87 | public void onActivityResumed(Activity activity) { 88 | 89 | } 90 | 91 | @Override 92 | public void onActivityPaused(Activity activity) { 93 | 94 | } 95 | 96 | @Override 97 | public void onActivityStopped(Activity activity) { 98 | 99 | } 100 | 101 | @Override 102 | public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { 103 | 104 | } 105 | 106 | @Override 107 | public void onActivityDestroyed(Activity activity) { 108 | ActivityManager.getAppManager().removeActivity(activity); 109 | } 110 | }; 111 | 112 | registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks); 113 | } 114 | 115 | /** 116 | * 在模拟环境中程序终止时会被调用 117 | */ 118 | @Override 119 | public void onTerminate() { 120 | super.onTerminate(); 121 | if (mAppDelegate != null) 122 | this.mAppDelegate.onTerminate(this); 123 | unregisterActivityLifecycleCallbacks(mActivityLifecycleCallbacks); 124 | } 125 | 126 | /** 127 | * 将 {@link AppComponent} 返回出去, 供其它地方使用, {@link AppComponent} 接口中声明的方法所返回的实例, 在 {@link #getAppComponent()} 拿到对象后都可以直接使用 128 | * 129 | * @return AppComponent 130 | * @see AtomsUtils#obtainAppComponentFromContext(Context) 可直接获取 {@link AppComponent} 131 | */ 132 | @NonNull 133 | @Override 134 | public AppComponent getAppComponent() { 135 | Preconditions.checkNotNull(mAppDelegate, "%s cannot be null", AppDelegate.class.getName()); 136 | Preconditions.checkState(mAppDelegate instanceof IApp, "%s must be implements %s", AppDelegate.class.getName(), IApp.class.getName()); 137 | return ((IApp) mAppDelegate).getAppComponent(); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/app/IApp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.app; 17 | 18 | import android.support.annotation.NonNull; 19 | 20 | import com.vea.atoms.mvp.di.component.AppComponent; 21 | 22 | 23 | /** 24 | * ================================================ 25 | * 框架要求框架中的每个 {@link android.app.Application} 都需要实现此类, 以满足规范 26 | * 27 | * @see BaseApplication 28 | * Created by Vea on 2018/8/20 29 | * ================================================ 30 | */ 31 | public interface IApp { 32 | 33 | @NonNull 34 | AppComponent getAppComponent(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/app/ILogout.java: -------------------------------------------------------------------------------- 1 | package com.vea.atoms.mvp.app; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * ILogout 7 | * 8 | * @author lishide 9 | * @date 2018/12/31 10 | */ 11 | public interface ILogout { 12 | 13 | 14 | void logout(Context context); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.base; 17 | 18 | import android.os.Bundle; 19 | import android.support.annotation.Nullable; 20 | import android.support.v7.app.AppCompatActivity; 21 | import android.view.LayoutInflater; 22 | import android.view.View; 23 | import android.widget.FrameLayout; 24 | import android.widget.Toast; 25 | 26 | import com.vea.atoms.mvp.di.component.AppComponent; 27 | import com.vea.atoms.mvp.utils.AtomsUtils; 28 | import com.wang.avi.AVLoadingIndicatorView; 29 | 30 | import javax.inject.Inject; 31 | 32 | import butterknife.ButterKnife; 33 | import butterknife.Unbinder; 34 | 35 | /** 36 | * ================================================ 37 | * MVP activity基类 38 | *

39 | * Created by Vea on 2016/11/24. 40 | * ================================================ 41 | */ 42 | public abstract class BaseActivity extends AppCompatActivity implements IView { 43 | 44 | @Inject 45 | protected T mPresenter; 46 | 47 | private Unbinder mUnBinder; 48 | protected View mLoadingView; 49 | private AVLoadingIndicatorView mAVLoadingIndicatorView; 50 | 51 | @Override 52 | protected void onCreate(@Nullable Bundle savedInstanceState) { 53 | super.onCreate(savedInstanceState); 54 | 55 | 56 | int layoutResID = getLayoutId(); 57 | //如果initView返回0,框架则不会调用setContentView(),当然也不会 Bind ButterKnife 58 | if (layoutResID != 0) { 59 | setContentView(layoutResID); 60 | //绑定到butterknife 61 | mUnBinder = ButterKnife.bind(this); 62 | } 63 | setupActivityComponent(AtomsUtils.obtainAppComponentFromContext(this)); 64 | if (mPresenter != null) { 65 | mPresenter.attachView(this); 66 | } 67 | initData(savedInstanceState); 68 | } 69 | 70 | @Override 71 | protected void onDestroy() { 72 | super.onDestroy(); 73 | if (mPresenter != null) { 74 | mPresenter.detachView(); 75 | mPresenter = null; 76 | } 77 | mUnBinder.unbind(); 78 | } 79 | 80 | protected void setupActivityComponent(AppComponent appComponent) { 81 | 82 | } 83 | 84 | @Override 85 | public void showLoading() { 86 | if (mLoadingView == null) { 87 | if (getLoadingLayoutId() != 0 && getLoadingViewId() != 0) { 88 | initLoadingView(); 89 | } 90 | } 91 | 92 | if (mLoadingView != null) { 93 | mLoadingView.bringToFront(); 94 | mLoadingView.setVisibility(View.VISIBLE); 95 | mAVLoadingIndicatorView.setVisibility(View.VISIBLE); 96 | } 97 | } 98 | 99 | @Override 100 | public void hideLoading() { 101 | if (mLoadingView != null) { 102 | mLoadingView.setVisibility(View.GONE); 103 | mAVLoadingIndicatorView.setVisibility(View.GONE); 104 | } 105 | } 106 | 107 | protected int getLoadingLayoutId() { 108 | return 0; 109 | } 110 | 111 | protected int getLoadingViewId() { 112 | return 0; 113 | } 114 | 115 | private void initLoadingView() { 116 | mLoadingView = LayoutInflater.from(this).inflate( 117 | getLoadingLayoutId(), null); 118 | mAVLoadingIndicatorView = mLoadingView.findViewById(getLoadingViewId()); 119 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, 120 | FrameLayout.LayoutParams.MATCH_PARENT); 121 | mLoadingView.setOnTouchListener((view, motionEvent) -> true); 122 | mAVLoadingIndicatorView.show(); 123 | addContentView(mLoadingView, params); 124 | } 125 | 126 | protected abstract int getLayoutId(); 127 | 128 | protected abstract void initData(@Nullable Bundle savedInstanceState); 129 | 130 | @Override 131 | public void closePage() { 132 | finish(); 133 | } 134 | 135 | @Override 136 | public void showMessage(String msg) { 137 | Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.base; 17 | 18 | import android.content.Context; 19 | import android.os.Bundle; 20 | import android.support.annotation.NonNull; 21 | import android.support.annotation.Nullable; 22 | import android.support.v4.app.Fragment; 23 | import android.view.LayoutInflater; 24 | import android.view.View; 25 | import android.view.ViewGroup; 26 | import android.widget.Toast; 27 | 28 | import com.vea.atoms.mvp.di.component.AppComponent; 29 | import com.vea.atoms.mvp.utils.AtomsUtils; 30 | 31 | import org.simple.eventbus.EventBus; 32 | 33 | import javax.inject.Inject; 34 | 35 | import butterknife.ButterKnife; 36 | import butterknife.Unbinder; 37 | 38 | /** 39 | * ================================================ 40 | * MVP Fragment基类 41 | *

42 | * Created by Vea on 2016/11/24. 43 | * ================================================ 44 | */ 45 | public abstract class BaseFragment extends Fragment implements IView { 46 | 47 | @Inject 48 | protected T mPresenter; 49 | 50 | private Unbinder mUnBinder; 51 | 52 | private BaseActivity mBaseActivity; 53 | 54 | public BaseActivity getBaseActivity() { 55 | return mBaseActivity; 56 | } 57 | 58 | @Override 59 | public void onAttach(Context context) { 60 | super.onAttach(context); 61 | mBaseActivity = (BaseActivity) context; 62 | } 63 | 64 | @Nullable 65 | @Override 66 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 67 | return inflater.inflate(getLayoutId(), null); 68 | } 69 | 70 | @Override 71 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 72 | super.onViewCreated(view, savedInstanceState); 73 | 74 | setupFragmentComponent(AtomsUtils.obtainAppComponentFromContext(getActivity())); 75 | if (mPresenter != null) { 76 | mPresenter.attachView(this); 77 | } 78 | mUnBinder = ButterKnife.bind(this, view); 79 | if (useEventBus()) { 80 | EventBus.getDefault().register(this); 81 | } 82 | initData(savedInstanceState); 83 | } 84 | 85 | @Override 86 | public void onDestroyView() { 87 | if (useEventBus()) { 88 | EventBus.getDefault().unregister(this); 89 | } 90 | super.onDestroyView(); 91 | mUnBinder.unbind(); 92 | } 93 | 94 | @Override 95 | public void onDestroy() { 96 | super.onDestroy(); 97 | if (mPresenter != null) { 98 | mPresenter.detachView(); 99 | mPresenter = null; 100 | } 101 | } 102 | 103 | protected void setupFragmentComponent(AppComponent appComponent) { 104 | 105 | } 106 | 107 | protected boolean useEventBus() { 108 | return true; 109 | } 110 | 111 | protected abstract int getLayoutId(); 112 | 113 | protected abstract void initData(@Nullable Bundle savedInstanceState); 114 | 115 | @Override 116 | public void showMessage(String msg) { 117 | if (getActivity() != null) { 118 | Toast.makeText(getActivity().getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); 119 | } 120 | } 121 | 122 | @Override 123 | public void showLoading() { 124 | mBaseActivity.showLoading(); 125 | } 126 | 127 | @Override 128 | public void hideLoading() { 129 | mBaseActivity.hideLoading(); 130 | } 131 | 132 | @Override 133 | public void closePage() { 134 | 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/base/BaseLazyFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.base; 17 | 18 | import android.os.Bundle; 19 | import android.support.annotation.NonNull; 20 | import android.support.annotation.Nullable; 21 | import android.view.View; 22 | 23 | /** 24 | * ================================================ 25 | * MVP 懒加载 Fragment基类 26 | *

27 | * Created by Vea on 2016/11/24. 28 | * ================================================ 29 | */ 30 | public abstract class BaseLazyFragment extends BaseFragment { 31 | 32 | /** 33 | * 控件是否已经初始化 34 | */ 35 | private boolean isCreateView; 36 | 37 | @Override 38 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 39 | super.onViewCreated(view, savedInstanceState); 40 | 41 | isCreateView = true; 42 | if (getUserVisibleHint()) { 43 | initPrepare(); 44 | } 45 | } 46 | 47 | /** 48 | * 此方法在控件初始化前调用,所以不能在此方法中直接操作控件会出现空指针 49 | * 50 | * @param isVisibleToUser 51 | */ 52 | @Override 53 | public void setUserVisibleHint(boolean isVisibleToUser) { 54 | super.setUserVisibleHint(isVisibleToUser); 55 | if (isVisibleToUser) { 56 | initPrepare(); 57 | } 58 | } 59 | 60 | private synchronized void initPrepare() { 61 | if (!isCreateView) { 62 | return; 63 | } 64 | onUserVisible(); 65 | } 66 | 67 | /** 68 | * 当视图初始化,并且对用户可见的时候去真正的加载数据 69 | */ 70 | protected abstract void onUserVisible(); 71 | } 72 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/base/BasePresenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.base; 17 | 18 | import com.vea.atoms.mvp.utils.Preconditions; 19 | 20 | import java.lang.ref.WeakReference; 21 | 22 | import io.reactivex.disposables.CompositeDisposable; 23 | import io.reactivex.disposables.Disposable; 24 | 25 | /** 26 | * ================================================ 27 | * Presenter基类 28 | *

29 | * Created by Vea on 2016/11/24. 30 | * ================================================ 31 | */ 32 | public class BasePresenter implements IPresenter { 33 | 34 | protected WeakReference mView; 35 | 36 | CompositeDisposable mDisposables; 37 | 38 | 39 | /** 40 | * 如果当前页面不需要操作数据,只需要 View 层,则使用此构造函数 41 | * 42 | * @param rootView 43 | */ 44 | public BasePresenter(T rootView) { 45 | Preconditions.checkNotNull(rootView, "%s cannot be null", IView.class.getName()); 46 | this.mView = new WeakReference(rootView); 47 | } 48 | 49 | public BasePresenter() { 50 | 51 | } 52 | 53 | 54 | @Override 55 | public void attachView(T view) { 56 | if (mView == null) { 57 | mView = new WeakReference(view); 58 | } 59 | } 60 | 61 | @Override 62 | public void detachView() { 63 | mView.clear(); 64 | mView = null; 65 | dispose(); 66 | } 67 | 68 | public T getView() { 69 | if (mView != null) { 70 | return mView.get(); 71 | } 72 | return null; 73 | } 74 | 75 | //取消所有的订阅 76 | public void dispose() { 77 | if (mDisposables != null) { 78 | mDisposables.clear(); 79 | } 80 | } 81 | 82 | protected void addSubscription(Disposable disposable) { 83 | if (disposable == null) return; 84 | if (mDisposables == null) { 85 | mDisposables = new CompositeDisposable(); 86 | } 87 | mDisposables.add(disposable); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/base/IPresenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.base; 17 | 18 | 19 | /** 20 | * ================================================ 21 | * 框架要求框架中的每个 Presenter 都需要实现此类,以满足规范 22 | * 23 | * @see BasePresenter 24 | * Created by Vea on 2016/11/24. 25 | * ================================================ 26 | */ 27 | public interface IPresenter { 28 | 29 | void attachView(T view); 30 | 31 | void detachView(); 32 | 33 | } -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/base/IView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.base; 17 | 18 | /** 19 | * ================================================ 20 | * 框架要求框架中的每个 View 都需要实现此类, 以满足规范 21 | *

22 | * Created by Vea on 2016/11/24. 23 | * ================================================ 24 | */ 25 | public interface IView { 26 | 27 | void showMessage(String msg); 28 | 29 | /** 30 | * 显示加载 31 | */ 32 | void showLoading(); 33 | 34 | /** 35 | * 隐藏加载 36 | */ 37 | void hideLoading(); 38 | 39 | /** 40 | * 关闭页面 41 | */ 42 | void closePage(); 43 | 44 | } -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/di/component/AppComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.di.component; 17 | 18 | import android.app.Application; 19 | import android.content.Context; 20 | 21 | import com.vea.atoms.mvp.app.AppDelegate; 22 | import com.vea.atoms.mvp.di.module.AppModule; 23 | import com.vea.atoms.mvp.di.module.ClientModule; 24 | import com.vea.atoms.mvp.di.module.GlobalConfigModule; 25 | import com.vea.atoms.mvp.integration.IRepositoryManager; 26 | import com.vea.atoms.mvp.integration.cache.Cache; 27 | import com.vea.atoms.mvp.utils.AtomsUtils; 28 | 29 | import javax.inject.Singleton; 30 | 31 | import dagger.BindsInstance; 32 | import dagger.Component; 33 | import okhttp3.OkHttpClient; 34 | 35 | /** 36 | * ================================================ 37 | * 可通过 {@link AtomsUtils#obtainAppComponentFromContext(Context)} 拿到此接口的实现类 38 | * 拥有此接口的实现类即可调用对应的方法拿到 Dagger 提供的对应实例 39 | *

40 | * Created by Vea on 2016/11/24. 41 | * ================================================ 42 | */ 43 | @Singleton 44 | @Component(modules = { 45 | AppModule.class, 46 | ClientModule.class, 47 | GlobalConfigModule.class, 48 | }) 49 | public interface AppComponent { 50 | 51 | Application application(); 52 | 53 | //用于管理网络请求层,以及数据缓存层 54 | IRepositoryManager repositoryManager(); 55 | 56 | OkHttpClient okHttpClient(); 57 | 58 | //用来存取一些整个App公用的数据,切勿大量存放大容量数据 59 | Cache extras(); 60 | 61 | //用于创建框架所需缓存对象的工厂 62 | Cache.Factory cacheFactory(); 63 | 64 | void injectDelegate(AppDelegate delegate); 65 | 66 | @Component.Builder 67 | interface Builder { 68 | @BindsInstance 69 | Builder application(Application application); 70 | 71 | Builder globalConfigModule(GlobalConfigModule globalConfigModule); 72 | 73 | AppComponent build(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/di/module/AppModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.di.module; 17 | 18 | 19 | import com.vea.atoms.mvp.integration.IRepositoryManager; 20 | import com.vea.atoms.mvp.integration.RepositoryManager; 21 | import com.vea.atoms.mvp.integration.cache.Cache; 22 | import com.vea.atoms.mvp.integration.cache.CacheType; 23 | 24 | import javax.inject.Singleton; 25 | 26 | import dagger.Binds; 27 | import dagger.Module; 28 | import dagger.Provides; 29 | 30 | /** 31 | * ================================================ 32 | * 提供一些框架必须的实例的 {@link Module} 33 | *

34 | * Created by Vea on 2016/11/24. 35 | * ================================================ 36 | */ 37 | @Module 38 | public abstract class AppModule { 39 | 40 | @Binds 41 | abstract IRepositoryManager bindRepositoryManager(RepositoryManager repositoryManager); 42 | 43 | 44 | @Singleton 45 | @Provides 46 | static Cache provideExtras(Cache.Factory cacheFactory) { 47 | return cacheFactory.build(CacheType.EXTRAS); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/di/module/ClientModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.di.module; 17 | 18 | import android.app.Application; 19 | import android.content.Context; 20 | import android.support.annotation.Nullable; 21 | 22 | import com.vea.atoms.mvp.http.GlobalHttpHandler; 23 | import com.vea.atoms.mvp.http.log.RequestInterceptor; 24 | 25 | import java.io.IOException; 26 | import java.util.List; 27 | import java.util.concurrent.TimeUnit; 28 | 29 | import javax.inject.Singleton; 30 | 31 | import dagger.Binds; 32 | import dagger.Module; 33 | import dagger.Provides; 34 | import okhttp3.HttpUrl; 35 | import okhttp3.Interceptor; 36 | import okhttp3.OkHttpClient; 37 | import okhttp3.Response; 38 | import retrofit2.Retrofit; 39 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; 40 | import retrofit2.converter.gson.GsonConverterFactory; 41 | 42 | /** 43 | * ================================================ 44 | * 提供一些三方库客户端实例的 {@link Module} 45 | *

46 | * Created by Vea on 2018/8/24. 47 | * ================================================ 48 | */ 49 | @Module 50 | public abstract class ClientModule { 51 | private static final int TIME_OUT = 10; 52 | 53 | /** 54 | * 提供 {@link Retrofit} 55 | * 56 | * @param application 57 | * @param configuration 58 | * @param builder 59 | * @param client 60 | * @param httpUrl 61 | * @param gson 62 | * @return {@link Retrofit} 63 | */ 64 | @Singleton 65 | @Provides 66 | static Retrofit provideRetrofit(Application application, @Nullable RetrofitConfiguration configuration, Retrofit.Builder builder, OkHttpClient client 67 | , HttpUrl httpUrl) { 68 | builder 69 | .baseUrl(httpUrl)//域名 70 | .client(client);//设置okhttp 71 | 72 | if (configuration != null) 73 | configuration.configRetrofit(application, builder); 74 | 75 | builder 76 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//使用 Rxjava 77 | .addConverterFactory(GsonConverterFactory.create());//使用 Gson 78 | return builder.build(); 79 | } 80 | 81 | /** 82 | * 提供 {@link OkHttpClient} 83 | * 84 | * @param application 85 | * @param configuration 86 | * @param builder 87 | * @param intercept 88 | * @param interceptors 89 | * @param handler 90 | * @return {@link OkHttpClient} 91 | */ 92 | @Singleton 93 | @Provides 94 | static OkHttpClient provideClient(Application application, @Nullable OkhttpConfiguration configuration, OkHttpClient.Builder builder, Interceptor intercept 95 | , @Nullable List interceptors, @Nullable GlobalHttpHandler handler) { 96 | builder 97 | .connectTimeout(TIME_OUT, TimeUnit.SECONDS) 98 | .readTimeout(TIME_OUT, TimeUnit.SECONDS) 99 | .addNetworkInterceptor(intercept); 100 | 101 | if (handler != null) 102 | builder.addInterceptor(new Interceptor() { 103 | @Override 104 | public Response intercept(Chain chain) throws IOException { 105 | return chain.proceed(handler.onHttpRequestBefore(chain, chain.request())); 106 | } 107 | }); 108 | 109 | if (interceptors != null) {//如果外部提供了interceptor的集合则遍历添加 110 | for (Interceptor interceptor : interceptors) { 111 | builder.addInterceptor(interceptor); 112 | } 113 | } 114 | 115 | if (configuration != null) 116 | configuration.configOkhttp(application, builder); 117 | return builder.build(); 118 | } 119 | 120 | @Singleton 121 | @Provides 122 | static Retrofit.Builder provideRetrofitBuilder() { 123 | return new Retrofit.Builder(); 124 | } 125 | 126 | @Singleton 127 | @Provides 128 | static OkHttpClient.Builder provideClientBuilder() { 129 | return new OkHttpClient.Builder(); 130 | } 131 | 132 | @Binds 133 | abstract Interceptor bindInterceptor(RequestInterceptor interceptor); 134 | 135 | 136 | public interface RetrofitConfiguration { 137 | void configRetrofit(Context context, Retrofit.Builder builder); 138 | } 139 | 140 | public interface OkhttpConfiguration { 141 | void configOkhttp(Context context, OkHttpClient.Builder builder); 142 | } 143 | 144 | 145 | } 146 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/di/scope/ActivityScope.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.di.scope; 17 | 18 | import java.lang.annotation.Retention; 19 | 20 | import javax.inject.Scope; 21 | 22 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 23 | 24 | @Scope 25 | @Retention(RUNTIME) 26 | public @interface ActivityScope { 27 | 28 | } -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/di/scope/FragmentScope.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.di.scope; 17 | 18 | import java.lang.annotation.Retention; 19 | 20 | import javax.inject.Scope; 21 | 22 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 23 | 24 | @Scope 25 | @Retention(RUNTIME) 26 | public @interface FragmentScope { 27 | } -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/http/BaseUrl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.http; 17 | 18 | import okhttp3.HttpUrl; 19 | 20 | /** 21 | * ================================================ 22 | * 针对于 BaseUrl 在 App 启动时不能确定,需要请求服务器接口动态获取的应用场景 23 | *

24 | * Created by Vea on 11/07/2017 14:58 25 | * ================================================ 26 | */ 27 | public interface BaseUrl { 28 | /** 29 | * 在调用 Retrofit API 接口之前,使用 Okhttp 或其他方式,请求到正确的 BaseUrl 并通过此方法返回 30 | * 31 | * @return 32 | */ 33 | HttpUrl url(); 34 | } 35 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/http/GlobalHttpHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.http; 17 | 18 | 19 | import com.vea.atoms.mvp.di.module.GlobalConfigModule; 20 | 21 | import okhttp3.Interceptor; 22 | import okhttp3.Request; 23 | import okhttp3.Response; 24 | 25 | /** 26 | * ================================================ 27 | * 处理 Http 请求和响应结果的处理类 28 | * 使用 {@link GlobalConfigModule.Builder#globalHttpHandler(GlobalHttpHandler)} 方法配置 29 | *

30 | * Created by Vea on 8/30/16 17:47 31 | * ================================================ 32 | */ 33 | public interface GlobalHttpHandler { 34 | Response onHttpResultResponse(String httpResult, Interceptor.Chain chain, Response response); 35 | 36 | Request onHttpRequestBefore(Interceptor.Chain chain, Request request); 37 | 38 | //空实现 39 | GlobalHttpHandler EMPTY = new GlobalHttpHandler() { 40 | @Override 41 | public Response onHttpResultResponse(String httpResult, Interceptor.Chain chain, Response response) { 42 | //不管是否处理,都必须将response返回出去 43 | return response; 44 | } 45 | 46 | @Override 47 | public Request onHttpRequestBefore(Interceptor.Chain chain, Request request) { 48 | //不管是否处理,都必须将request返回出去 49 | return request; 50 | } 51 | }; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/http/log/FormatPrinter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.http.log; 17 | 18 | 19 | import com.vea.atoms.mvp.di.module.GlobalConfigModule; 20 | 21 | import java.util.List; 22 | 23 | import okhttp3.MediaType; 24 | import okhttp3.Request; 25 | 26 | /** 27 | * ================================================ 28 | * 对 OkHttp 的请求和响应信息进行更规范和清晰的打印, 开发者可更根据自己的需求自行扩展打印格式 29 | * 30 | * @see DefaultFormatPrinter 31 | * @see GlobalConfigModule.Builder#formatPrinter(FormatPrinter) 32 | * Created by Vea on 31/01/2018 17:36 33 | * ================================================ 34 | */ 35 | 36 | public interface FormatPrinter { 37 | 38 | /** 39 | * 打印网络请求信息, 当网络请求时 {{@link okhttp3.RequestBody}} 可以解析的情况 40 | * 41 | * @param request 42 | * @param bodyString 发送给服务器的请求体中的数据(已解析) 43 | */ 44 | void printJsonRequest(Request request, String bodyString); 45 | 46 | /** 47 | * 打印网络请求信息, 当网络请求时 {{@link okhttp3.RequestBody}} 为 {@code null} 或不可解析的情况 48 | * 49 | * @param request 50 | */ 51 | void printFileRequest(Request request); 52 | 53 | /** 54 | * 打印网络响应信息, 当网络响应时 {{@link okhttp3.ResponseBody}} 可以解析的情况 55 | * 56 | * @param chainMs 服务器响应耗时(单位毫秒) 57 | * @param isSuccessful 请求是否成功 58 | * @param code 响应码 59 | * @param headers 请求头 60 | * @param contentType 服务器返回数据的数据类型 61 | * @param bodyString 服务器返回的数据(已解析) 62 | * @param segments 域名后面的资源地址 63 | * @param message 响应信息 64 | * @param responseUrl 请求地址 65 | */ 66 | void printJsonResponse(long chainMs, boolean isSuccessful, int code, String headers, MediaType contentType, 67 | String bodyString, List segments, String message, String responseUrl); 68 | 69 | /** 70 | * 打印网络响应信息, 当网络响应时 {{@link okhttp3.ResponseBody}} 为 {@code null} 或不可解析的情况 71 | * 72 | * @param chainMs 服务器响应耗时(单位毫秒) 73 | * @param isSuccessful 请求是否成功 74 | * @param code 响应码 75 | * @param headers 请求头 76 | * @param segments 域名后面的资源地址 77 | * @param message 响应信息 78 | * @param responseUrl 请求地址 79 | */ 80 | void printFileResponse(long chainMs, boolean isSuccessful, int code, String headers, 81 | List segments, String message, String responseUrl); 82 | } 83 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/integration/ConfigModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.integration; 17 | 18 | import android.content.Context; 19 | 20 | import com.vea.atoms.mvp.app.AppLifecycles; 21 | import com.vea.atoms.mvp.di.module.GlobalConfigModule; 22 | 23 | import java.util.List; 24 | 25 | /** 26 | * ================================================ 27 | * {@link ConfigModule} 可以给框架配置一些参数,需要实现 {@link ConfigModule} 后,在 AndroidManifest 中声明该实现类 28 | *

29 | * Created by Vea on 12/04/2017 11:37 30 | * ================================================ 31 | */ 32 | public interface ConfigModule { 33 | 34 | /** 35 | * 使用{@link GlobalConfigModule.Builder}给框架配置一些配置参数 36 | * 37 | * @param context 38 | * @param builder 39 | */ 40 | void applyOptions(Context context, GlobalConfigModule.Builder builder); 41 | 42 | /** 43 | * 使用{@link AppLifecycles}在Application的生命周期中注入一些操作 44 | * 45 | * @param context 46 | * @param lifecycles 47 | */ 48 | void injectAppLifecycle(Context context, List lifecycles); 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/integration/IRepositoryManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.integration; 17 | 18 | 19 | /** 20 | * ================================================ 21 | * 用来管理网络请求层 22 | *

23 | * Created by Vea on 17/03/2017 11:15 24 | * ================================================ 25 | */ 26 | public interface IRepositoryManager { 27 | 28 | /** 29 | * 根据传入的 Class 获取对应的 Retrofit service 30 | * 31 | * @param service 32 | * @param 33 | * @return 34 | */ 35 | T obtainRetrofitService(Class service); 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/integration/ManifestParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.integration; 17 | 18 | import android.content.Context; 19 | import android.content.pm.ApplicationInfo; 20 | import android.content.pm.PackageManager; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | /** 26 | * ================================================ 27 | * 用于解析 AndroidManifest 中的 Meta 属性 28 | * 配合 {@link ConfigModule} 使用 29 | *

30 | * Created by Vea on 12/04/2017 14:41 31 | * ================================================ 32 | */ 33 | public final class ManifestParser { 34 | private static final String MODULE_VALUE = "ConfigModule"; 35 | 36 | private final Context context; 37 | 38 | public ManifestParser(Context context) { 39 | this.context = context; 40 | } 41 | 42 | public List parse() { 43 | List modules = new ArrayList(); 44 | try { 45 | ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo( 46 | context.getPackageName(), PackageManager.GET_META_DATA); 47 | if (appInfo.metaData != null) { 48 | for (String key : appInfo.metaData.keySet()) { 49 | if (MODULE_VALUE.equals(appInfo.metaData.get(key))) { 50 | 51 | try { 52 | Class clazz = Class.forName(key); 53 | modules.add(parseModule(key)); 54 | } catch (ClassNotFoundException e) { 55 | } 56 | } 57 | } 58 | } 59 | } catch (PackageManager.NameNotFoundException e) { 60 | throw new RuntimeException("Unable to find metadata to parse ConfigModule", e); 61 | } 62 | 63 | return modules; 64 | } 65 | 66 | private static ConfigModule parseModule(String className) { 67 | Class clazz; 68 | try { 69 | clazz = Class.forName(className); 70 | } catch (ClassNotFoundException e) { 71 | throw new IllegalArgumentException("Unable to find ConfigModule implementation", e); 72 | } 73 | 74 | Object module; 75 | try { 76 | module = clazz.newInstance(); 77 | } catch (InstantiationException e) { 78 | throw new RuntimeException("Unable to instantiate ConfigModule implementation for " + clazz, e); 79 | } catch (IllegalAccessException e) { 80 | throw new RuntimeException("Unable to instantiate ConfigModule implementation for " + clazz, e); 81 | } 82 | 83 | if (!(module instanceof ConfigModule)) { 84 | throw new RuntimeException("Expected instanceof ConfigModule, but found: " + module); 85 | } 86 | return (ConfigModule) module; 87 | } 88 | } -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/integration/RepositoryManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.integration; 17 | 18 | 19 | import com.vea.atoms.mvp.integration.cache.Cache; 20 | import com.vea.atoms.mvp.integration.cache.CacheType; 21 | import com.vea.atoms.mvp.utils.Preconditions; 22 | 23 | import javax.inject.Inject; 24 | import javax.inject.Singleton; 25 | 26 | import dagger.Lazy; 27 | import retrofit2.Retrofit; 28 | 29 | /** 30 | * ================================================ 31 | * IRepositoryManager实现类用来管理网络请求层 32 | *

33 | * Created by Vea on 13/04/2017 09:52 34 | * ================================================ 35 | */ 36 | @Singleton 37 | public class RepositoryManager implements IRepositoryManager { 38 | @Inject 39 | Lazy mRetrofit; 40 | 41 | @Inject 42 | Cache.Factory mCachefactory; 43 | 44 | private Cache mRetrofitServiceCache; 45 | 46 | @Inject 47 | public RepositoryManager() { 48 | } 49 | 50 | /** 51 | * 根据传入的 Class 获取对应的 Retrofit service 52 | * 53 | * @param service 54 | * @param 55 | * @return 56 | */ 57 | @Override 58 | public synchronized T obtainRetrofitService(Class service) { 59 | if (mRetrofitServiceCache == null) 60 | mRetrofitServiceCache = mCachefactory.build(CacheType.RETROFIT_SERVICE_CACHE); 61 | Preconditions.checkNotNull(mRetrofitServiceCache, "Cannot return null from a Cache.Factory#build(int) method"); 62 | T retrofitService = (T) mRetrofitServiceCache.get(service.getCanonicalName()); 63 | if (retrofitService == null) { 64 | retrofitService = mRetrofit.get().create(service); 65 | mRetrofitServiceCache.put(service.getCanonicalName(), retrofitService); 66 | } 67 | return retrofitService; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/integration/cache/Cache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.integration.cache; 17 | 18 | import android.app.Application; 19 | import android.support.annotation.NonNull; 20 | import android.support.annotation.Nullable; 21 | 22 | import com.vea.atoms.mvp.di.module.GlobalConfigModule; 23 | 24 | import java.util.Set; 25 | 26 | /** 27 | * ================================================ 28 | * 用于缓存框架中所必需的组件,开发者可通过 {@link GlobalConfigModule.Builder#cacheFactory(Factory)} 为框架提供缓存策略 29 | * 开发者也可以用于自己日常中的使用 30 | * 31 | * @see GlobalConfigModule#provideCacheFactory(Application) 32 | * @see LruCache 33 | * Created by Vea on 25/09/2017 16:36 34 | * ================================================ 35 | */ 36 | public interface Cache { 37 | interface Factory { 38 | 39 | /** 40 | * Returns a new cache 41 | * 42 | * @param type 框架中需要缓存的模块类型 43 | * @return {@link Cache} 44 | */ 45 | @NonNull 46 | Cache build(CacheType type); 47 | } 48 | 49 | /** 50 | * 返回当前缓存已占用的总 size 51 | * 52 | * @return {@code size} 53 | */ 54 | int size(); 55 | 56 | /** 57 | * 返回当前缓存所能允许的最大 size 58 | * 59 | * @return {@code maxSize} 60 | */ 61 | int getMaxSize(); 62 | 63 | /** 64 | * 返回这个 {@code key} 在缓存中对应的 {@code value}, 如果返回 {@code null} 说明这个 {@code key} 没有对应的 {@code value} 65 | * 66 | * @param key {@code key} 67 | * @return {@code value} 68 | */ 69 | @Nullable 70 | V get(K key); 71 | 72 | /** 73 | * 将 {@code key} 和 {@code value} 以条目的形式加入缓存,如果这个 {@code key} 在缓存中已经有对应的 {@code value} 74 | * 则此 {@code value} 被新的 {@code value} 替换并返回,如果为 {@code null} 说明是一个新条目 75 | * 76 | * @param key {@code key} 77 | * @param value {@code value} 78 | * @return 如果这个 {@code key} 在容器中已经储存有 {@code value}, 则返回之前的 {@code value} 否则返回 {@code null} 79 | */ 80 | @Nullable 81 | V put(K key, V value); 82 | 83 | /** 84 | * 移除缓存中这个 {@code key} 所对应的条目,并返回所移除条目的 value 85 | * 如果返回为 {@code null} 则有可能时因为这个 {@code key} 对应的 value 为 {@code null} 或条目不存在 86 | * 87 | * @param key {@code key} 88 | * @return 如果这个 {@code key} 在容器中已经储存有 {@code value} 并且删除成功则返回删除的 {@code value}, 否则返回 {@code null} 89 | */ 90 | @Nullable 91 | V remove(K key); 92 | 93 | /** 94 | * 如果这个 {@code key} 在缓存中有对应的 value 并且不为 {@code null}, 则返回 {@code true} 95 | * 96 | * @param key {@code key} 97 | * @return {@code true} 为在容器中含有这个 {@code key}, 否则为 {@code false} 98 | */ 99 | boolean containsKey(K key); 100 | 101 | /** 102 | * 返回当前缓存中含有的所有 {@code key} 103 | * 104 | * @return {@code keySet} 105 | */ 106 | Set keySet(); 107 | 108 | /** 109 | * 清除缓存中所有的内容 110 | */ 111 | void clear(); 112 | } 113 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/integration/cache/CacheType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.integration.cache; 17 | 18 | import android.app.Activity; 19 | import android.app.ActivityManager; 20 | import android.content.Context; 21 | import android.support.v4.app.Fragment; 22 | 23 | import com.vea.atoms.mvp.di.component.AppComponent; 24 | import com.vea.atoms.mvp.integration.RepositoryManager; 25 | 26 | /** 27 | * ================================================ 28 | * 构建 {@link Cache} 时,使用 {@link CacheType} 中声明的类型,来区分不同的模块 29 | * 从而为不同的模块构建不同的缓存策略 30 | * 31 | * @see Cache.Factory#build(CacheType) 32 | * Created by Vea on 25/09/2017 18:05 33 | * ================================================ 34 | */ 35 | public interface CacheType { 36 | int RETROFIT_SERVICE_CACHE_TYPE_ID = 0; 37 | int CACHE_SERVICE_CACHE_TYPE_ID = 1; 38 | int EXTRAS_TYPE_ID = 2; 39 | int ACTIVITY_CACHE_TYPE_ID = 3; 40 | int FRAGMENT_CACHE_TYPE_ID = 4; 41 | /** 42 | * {@link RepositoryManager}中存储 Retrofit Service 的容器 43 | */ 44 | CacheType RETROFIT_SERVICE_CACHE = new CacheType() { 45 | private static final int MAX_SIZE = 150; 46 | private static final float MAX_SIZE_MULTIPLIER = 0.002f; 47 | 48 | @Override 49 | public int getCacheTypeId() { 50 | return RETROFIT_SERVICE_CACHE_TYPE_ID; 51 | } 52 | 53 | @Override 54 | public int calculateCacheSize(Context context) { 55 | ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 56 | int targetMemoryCacheSize = (int) (activityManager.getMemoryClass() * MAX_SIZE_MULTIPLIER * 1024); 57 | if (targetMemoryCacheSize >= MAX_SIZE) { 58 | return MAX_SIZE; 59 | } 60 | return targetMemoryCacheSize; 61 | } 62 | }; 63 | 64 | /** 65 | * {@link RepositoryManager} 中储存 Cache Service 的容器 66 | */ 67 | CacheType CACHE_SERVICE_CACHE = new CacheType() { 68 | private static final int MAX_SIZE = 150; 69 | private static final float MAX_SIZE_MULTIPLIER = 0.002f; 70 | 71 | @Override 72 | public int getCacheTypeId() { 73 | return CACHE_SERVICE_CACHE_TYPE_ID; 74 | } 75 | 76 | @Override 77 | public int calculateCacheSize(Context context) { 78 | ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 79 | int targetMemoryCacheSize = (int) (activityManager.getMemoryClass() * MAX_SIZE_MULTIPLIER * 1024); 80 | if (targetMemoryCacheSize >= MAX_SIZE) { 81 | return MAX_SIZE; 82 | } 83 | return targetMemoryCacheSize; 84 | } 85 | }; 86 | 87 | /** 88 | * {@link AppComponent} 中的 extras 89 | */ 90 | CacheType EXTRAS = new CacheType() { 91 | private static final int MAX_SIZE = 500; 92 | private static final float MAX_SIZE_MULTIPLIER = 0.005f; 93 | 94 | @Override 95 | public int getCacheTypeId() { 96 | return EXTRAS_TYPE_ID; 97 | } 98 | 99 | @Override 100 | public int calculateCacheSize(Context context) { 101 | ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 102 | int targetMemoryCacheSize = (int) (activityManager.getMemoryClass() * MAX_SIZE_MULTIPLIER * 1024); 103 | if (targetMemoryCacheSize >= MAX_SIZE) { 104 | return MAX_SIZE; 105 | } 106 | return targetMemoryCacheSize; 107 | } 108 | }; 109 | 110 | /** 111 | * {@link Activity} 中存储数据的容器 112 | */ 113 | CacheType ACTIVITY_CACHE = new CacheType() { 114 | private static final int MAX_SIZE = 80; 115 | private static final float MAX_SIZE_MULTIPLIER = 0.0008f; 116 | 117 | @Override 118 | public int getCacheTypeId() { 119 | return ACTIVITY_CACHE_TYPE_ID; 120 | } 121 | 122 | @Override 123 | public int calculateCacheSize(Context context) { 124 | ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 125 | int targetMemoryCacheSize = (int) (activityManager.getMemoryClass() * MAX_SIZE_MULTIPLIER * 1024); 126 | if (targetMemoryCacheSize >= MAX_SIZE) { 127 | return MAX_SIZE; 128 | } 129 | return targetMemoryCacheSize; 130 | } 131 | }; 132 | 133 | /** 134 | * {@link Fragment} 中存储数据的容器 135 | */ 136 | CacheType FRAGMENT_CACHE = new CacheType() { 137 | private static final int MAX_SIZE = 80; 138 | private static final float MAX_SIZE_MULTIPLIER = 0.0008f; 139 | 140 | @Override 141 | public int getCacheTypeId() { 142 | return FRAGMENT_CACHE_TYPE_ID; 143 | } 144 | 145 | @Override 146 | public int calculateCacheSize(Context context) { 147 | ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 148 | int targetMemoryCacheSize = (int) (activityManager.getMemoryClass() * MAX_SIZE_MULTIPLIER * 1024); 149 | if (targetMemoryCacheSize >= MAX_SIZE) { 150 | return MAX_SIZE; 151 | } 152 | return targetMemoryCacheSize; 153 | } 154 | }; 155 | 156 | /** 157 | * 返回框架内需要缓存的模块对应的 {@code id} 158 | * 159 | * @return 160 | */ 161 | int getCacheTypeId(); 162 | 163 | /** 164 | * 计算对应模块需要的缓存大小 165 | * 166 | * @return 167 | */ 168 | int calculateCacheSize(Context context); 169 | } 170 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/integration/cache/IntelligentCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.integration.cache; 17 | 18 | import android.support.annotation.Nullable; 19 | 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | import java.util.Set; 23 | 24 | /** 25 | * ================================================ 26 | * {@link IntelligentCache} 含有可将数据永久存储至内存中的存储容器 {@link #mMap}, 和当达到最大容量时可根据 LRU 27 | * 算法抛弃不合规数据的存储容器 {@link #mCache} 28 | *

29 | * {@link IntelligentCache} 可根据您传入的 {@code key} 智能的判断您需要将数据存储至哪个存储容器, 从而针对数据 30 | * 的不同特性进行不同的存储优化 31 | *

32 | * 调用 {@link IntelligentCache#put(Object, Object)} 方法, 使用 {@link #KEY_KEEP} + {@code key} 作为 key 传入的 33 | * {@code value} 可存储至 {@link #mMap} (数据永久存储至内存中, 适合比较重要的数据) 中, 否则储存至 {@link #mCache} 34 | *

35 | * Created by Vea on 12/04/2018 16:06 36 | * ================================================ 37 | */ 38 | public class IntelligentCache implements Cache { 39 | private final Map mMap;//可将数据永久存储至内存中的存储容器 40 | private final Cache mCache;//当达到最大容量时可根据 LRU 算法抛弃不合规数据的存储容器 41 | public static final String KEY_KEEP = "Keep="; 42 | 43 | public IntelligentCache(int size) { 44 | this.mMap = new HashMap<>(); 45 | this.mCache = new LruCache<>(size); 46 | } 47 | 48 | /** 49 | * 将 {@link #mMap} 和 {@link #mCache} 的 {@code size} 相加后返回 50 | * 51 | * @return 相加后的 {@code size} 52 | */ 53 | @Override 54 | public synchronized int size() { 55 | return mMap.size() + mCache.size(); 56 | } 57 | 58 | /** 59 | * 将 {@link #mMap} 和 {@link #mCache} 的 {@code maxSize} 相加后返回 60 | * 61 | * @return 相加后的 {@code maxSize} 62 | */ 63 | @Override 64 | public synchronized int getMaxSize() { 65 | return mMap.size() + mCache.getMaxSize(); 66 | } 67 | 68 | /** 69 | * 如果在 {@code key} 中使用 {@link #KEY_KEEP} 作为其前缀, 则操作 {@link #mMap}, 否则操作 {@link #mCache} 70 | * 71 | * @param key {@code key} 72 | * @return {@code value} 73 | */ 74 | @Nullable 75 | @Override 76 | public synchronized V get(String key) { 77 | if (key.startsWith(KEY_KEEP)) { 78 | return mMap.get(key); 79 | } 80 | return mCache.get(key); 81 | } 82 | 83 | /** 84 | * 如果在 {@code key} 中使用 {@link #KEY_KEEP} 作为其前缀, 则操作 {@link #mMap}, 否则操作 {@link #mCache} 85 | * 86 | * @param key {@code key} 87 | * @param value {@code value} 88 | * @return 如果这个 {@code key} 在容器中已经储存有 {@code value}, 则返回之前的 {@code value} 否则返回 {@code null} 89 | */ 90 | @Nullable 91 | @Override 92 | public synchronized V put(String key, V value) { 93 | if (key.startsWith(KEY_KEEP)) { 94 | return mMap.put(key, value); 95 | } 96 | return mCache.put(key, value); 97 | } 98 | 99 | /** 100 | * 如果在 {@code key} 中使用 {@link #KEY_KEEP} 作为其前缀, 则操作 {@link #mMap}, 否则操作 {@link #mCache} 101 | * 102 | * @param key {@code key} 103 | * @return 如果这个 {@code key} 在容器中已经储存有 {@code value} 并且删除成功则返回删除的 {@code value}, 否则返回 {@code null} 104 | */ 105 | @Nullable 106 | @Override 107 | public synchronized V remove(String key) { 108 | if (key.startsWith(KEY_KEEP)) { 109 | return mMap.remove(key); 110 | } 111 | return mCache.remove(key); 112 | } 113 | 114 | /** 115 | * 如果在 {@code key} 中使用 {@link #KEY_KEEP} 作为其前缀, 则操作 {@link #mMap}, 否则操作 {@link #mCache} 116 | * 117 | * @param key {@code key} 118 | * @return {@code true} 为在容器中含有这个 {@code key}, 否则为 {@code false} 119 | */ 120 | @Override 121 | public synchronized boolean containsKey(String key) { 122 | if (key.startsWith(KEY_KEEP)) { 123 | return mMap.containsKey(key); 124 | } 125 | return mCache.containsKey(key); 126 | } 127 | 128 | /** 129 | * 将 {@link #mMap} 和 {@link #mCache} 的 {@code keySet} 合并返回 130 | * 131 | * @return 合并后的 {@code keySet} 132 | */ 133 | @Override 134 | public synchronized Set keySet() { 135 | Set set = mCache.keySet(); 136 | set.addAll(mMap.keySet()); 137 | return set; 138 | } 139 | 140 | /** 141 | * 清空 {@link #mMap} 和 {@link #mCache} 容器 142 | */ 143 | @Override 144 | public void clear() { 145 | mCache.clear(); 146 | mMap.clear(); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/utils/CharacterHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Vea 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.utils; 17 | 18 | import android.text.InputFilter; 19 | import android.text.Spanned; 20 | import android.text.TextUtils; 21 | 22 | import org.json.JSONArray; 23 | import org.json.JSONException; 24 | import org.json.JSONObject; 25 | 26 | import java.io.StringReader; 27 | import java.io.StringWriter; 28 | import java.util.regex.Matcher; 29 | import java.util.regex.Pattern; 30 | 31 | import javax.xml.transform.OutputKeys; 32 | import javax.xml.transform.Source; 33 | import javax.xml.transform.Transformer; 34 | import javax.xml.transform.TransformerException; 35 | import javax.xml.transform.TransformerFactory; 36 | import javax.xml.transform.stream.StreamResult; 37 | import javax.xml.transform.stream.StreamSource; 38 | 39 | /** 40 | * ================================================ 41 | * 处理字符串的工具类 42 | *

43 | * Created by Vea on 2016/3/16 44 | * ================================================ 45 | */ 46 | public class CharacterHandler { 47 | 48 | private CharacterHandler() { 49 | throw new IllegalStateException("you can't instantiate me!"); 50 | } 51 | 52 | public static final InputFilter emojiFilter = new InputFilter() {//emoji过滤器 53 | 54 | Pattern emoji = Pattern.compile( 55 | "[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]", 56 | Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE); 57 | 58 | @Override 59 | public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, 60 | int dend) { 61 | 62 | Matcher emojiMatcher = emoji.matcher(source); 63 | if (emojiMatcher.find()) { 64 | return ""; 65 | } 66 | 67 | return null; 68 | } 69 | }; 70 | 71 | 72 | /** 73 | * 字符串转换成十六进制字符串 74 | * 75 | * @return String 每个Byte之间空格分隔,如: [61 6C 6B] 76 | */ 77 | public static String str2HexStr(String str) { 78 | 79 | char[] chars = "0123456789ABCDEF".toCharArray(); 80 | StringBuilder sb = new StringBuilder(""); 81 | byte[] bs = str.getBytes(); 82 | int bit; 83 | 84 | for (int i = 0; i < bs.length; i++) { 85 | bit = (bs[i] & 0x0f0) >> 4; 86 | sb.append(chars[bit]); 87 | bit = bs[i] & 0x0f; 88 | sb.append(chars[bit]); 89 | } 90 | return sb.toString().trim(); 91 | } 92 | 93 | 94 | /** 95 | * json 格式化 96 | * 97 | * @param json 98 | * @return 99 | */ 100 | public static String jsonFormat(String json) { 101 | if (TextUtils.isEmpty(json)) { 102 | return "Empty/Null json content"; 103 | } 104 | String message; 105 | try { 106 | json = json.trim(); 107 | if (json.startsWith("{")) { 108 | JSONObject jsonObject = new JSONObject(json); 109 | message = jsonObject.toString(4); 110 | } else if (json.startsWith("[")) { 111 | JSONArray jsonArray = new JSONArray(json); 112 | message = jsonArray.toString(4); 113 | } else { 114 | message = json; 115 | } 116 | } catch (JSONException e) { 117 | message = json; 118 | } 119 | return message; 120 | } 121 | 122 | 123 | /** 124 | * xml 格式化 125 | * 126 | * @param xml 127 | * @return 128 | */ 129 | public static String xmlFormat(String xml) { 130 | if (TextUtils.isEmpty(xml)) { 131 | return "Empty/Null xml content"; 132 | } 133 | String message; 134 | try { 135 | Source xmlInput = new StreamSource(new StringReader(xml)); 136 | StreamResult xmlOutput = new StreamResult(new StringWriter()); 137 | Transformer transformer = TransformerFactory.newInstance().newTransformer(); 138 | transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 139 | transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); 140 | transformer.transform(xmlInput, xmlOutput); 141 | message = xmlOutput.getWriter().toString().replaceFirst(">", ">\n"); 142 | } catch (TransformerException e) { 143 | message = xml; 144 | } 145 | return message; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /atoms/src/main/java/com/vea/atoms/mvp/utils/UrlEncoderUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 JessYan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.vea.atoms.mvp.utils; 17 | 18 | /** 19 | * ================================================ 20 | * Created by JessYan on 2018/9/14 14:10 21 | * Contact me 22 | * Follow me 23 | * ================================================ 24 | */ 25 | public class UrlEncoderUtils { 26 | 27 | private UrlEncoderUtils() { 28 | throw new IllegalStateException("you can't instantiate me!"); 29 | } 30 | 31 | /** 32 | * 判断 str 是否已经 URLEncoder.encode() 过 33 | * 经常遇到这样的情况, 拿到一个 URL, 但是搞不清楚到底要不要 URLEncoder.encode() 34 | * 不做 URLEncoder.encode() 吧, 担心出错, 做 URLEncoder.encode() 吧, 又怕重复了 35 | * 36 | * @param str 需要判断的内容 37 | * @return 返回 {@code true} 为被 URLEncoder.encode() 过 38 | */ 39 | public static boolean hasUrlEncoded(String str) { 40 | boolean encode = false; 41 | for (int i = 0; i < str.length(); i++) { 42 | char c = str.charAt(i); 43 | if (c == '%' && (i + 2) < str.length()) { 44 | // 判断是否符合urlEncode规范 45 | char c1 = str.charAt(i + 1); 46 | char c2 = str.charAt(i + 2); 47 | if (isValidHexChar(c1) && isValidHexChar(c2)) { 48 | encode = true; 49 | break; 50 | } else { 51 | break; 52 | } 53 | } 54 | } 55 | return encode; 56 | } 57 | 58 | /** 59 | * 判断 c 是否是 16 进制的字符 60 | * 61 | * @param c 需要判断的字符 62 | * @return 返回 {@code true} 为 16 进制的字符 63 | */ 64 | private static boolean isValidHexChar(char c) { 65 | return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /atoms/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | atoms 3 | 4 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | apply from: "config.gradle" 3 | 4 | buildscript { 5 | ext.kotlin_version = '1.3.11' 6 | repositories { 7 | google() 8 | jcenter() 9 | maven { url "https://oss.sonatype.org/content/repositories/snapshots" } 10 | } 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:3.2.1' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | classpath 'com.jakewharton:butterknife-gradle-plugin:9.0.0-SNAPSHOT' 15 | //如果 ButterKnife 插件和其他插件发生冲突而报错请试试 v8.4.0 版本的 ButterKnife 插件, 注意 v8.4.0 最高只能支持 com.android.tools.build:gradle:3.0.1 16 | // classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0' 17 | // NOTE: Do not place your application dependencies here; they belong 18 | // in the individual module build.gradle files 19 | classpath 'com.alibaba:arouter-register:1.0.2' 20 | } 21 | } 22 | 23 | allprojects { 24 | repositories { 25 | google() 26 | jcenter() 27 | maven { url "https://jitpack.io" } 28 | } 29 | 30 | subprojects { 31 | project.configurations.all { 32 | resolutionStrategy.eachDependency { details -> 33 | if (details.requested.group == 'com.android.support' 34 | && !details.requested.name.contains('multidex')) { 35 | details.useVersion rootProject.ext.version["androidSupportSdkVersion"] 36 | } 37 | } 38 | } 39 | 40 | } 41 | } 42 | 43 | task clean(type: Delete) { 44 | delete rootProject.buildDir 45 | } 46 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/gradle.properties -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Sep 07 13:54:39 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /image/atoms_banner_v1.0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/image/atoms_banner_v1.0.jpg -------------------------------------------------------------------------------- /qrcode_for_gh_e708d5b47c85_258.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XWC95/Atoms-mvp/5a4f0626eab0c9789a579139f18f908d59885a1f/qrcode_for_gh_e708d5b47c85_258.jpg -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':atoms', ':CommonSDK', ':Module-gank', ':CommonService' 2 | --------------------------------------------------------------------------------