Repository: senonwx/WanAndroid
Branch: master
Commit: 548831d6c068
Files: 230
Total size: 550.5 KB
Directory structure:
gitextract_lw_97uwb/
├── .gitignore
├── .idea/
│ └── encodings.xml
├── README.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── senon/
│ │ └── xfhmoudel/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── senon/
│ │ │ └── xfhmoudel/
│ │ │ ├── App.java
│ │ │ ├── FragmentHomeActivity.java
│ │ │ ├── SplashActivity.java
│ │ │ └── TestActivity.java
│ │ └── res/
│ │ ├── drawable/
│ │ │ ├── ic_launcher_background.xml
│ │ │ └── shape_splash_timer.xml
│ │ ├── layout/
│ │ │ ├── activity_fragment_home.xml
│ │ │ ├── activity_splash.xml
│ │ │ └── activity_test.xml
│ │ └── values/
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test/
│ └── java/
│ └── com/
│ └── senon/
│ └── xfhmoudel/
│ └── ExampleUnitTest.java
├── build.gradle
├── dependencies.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── lib_common/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── senon/
│ │ └── lib_common/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── senon/
│ │ │ └── lib_common/
│ │ │ ├── AppConfig.java
│ │ │ ├── ComUtil.java
│ │ │ ├── ConstantArouter.java
│ │ │ ├── ConstantLoginArouter.java
│ │ │ ├── adapter/
│ │ │ │ ├── CommonAdapter.java
│ │ │ │ ├── CommonHolder.java
│ │ │ │ ├── RecycleHolder.java
│ │ │ │ └── RecyclerAdapter.java
│ │ │ ├── api/
│ │ │ │ └── BaseApi.java
│ │ │ ├── base/
│ │ │ │ ├── BaseActivity.java
│ │ │ │ ├── BaseAppDeletage.java
│ │ │ │ ├── BaseApplication.java
│ │ │ │ ├── BaseFragment.java
│ │ │ │ ├── BaseLazyFragment.java
│ │ │ │ ├── BaseNestingLazyFragment.java
│ │ │ │ ├── BasePresenter.java
│ │ │ │ ├── BaseResponse.java
│ │ │ │ └── BaseViewImp.java
│ │ │ ├── bean/
│ │ │ │ ├── Banner.java
│ │ │ │ ├── CollectionArticle.java
│ │ │ │ ├── HomeArticle.java
│ │ │ │ ├── KnowledgeSysArticle.java
│ │ │ │ ├── KnowledgeSystem.java
│ │ │ │ ├── Login.java
│ │ │ │ ├── ProjectArticle.java
│ │ │ │ ├── WXarticle.java
│ │ │ │ └── WXchapters.java
│ │ │ ├── common/
│ │ │ │ ├── contract/
│ │ │ │ │ ├── LoginContract.java
│ │ │ │ │ └── WebviewContract.java
│ │ │ │ ├── presenter/
│ │ │ │ │ ├── LoginPresenter.java
│ │ │ │ │ └── WebviewPresenter.java
│ │ │ │ └── ui/
│ │ │ │ ├── Common_LoginActivity.java
│ │ │ │ ├── Common_RegisterActivity.java
│ │ │ │ └── Common_WebviewActivity.java
│ │ │ ├── net/
│ │ │ │ ├── RequestInterceptor.java
│ │ │ │ ├── ServerUtils.java
│ │ │ │ ├── callback/
│ │ │ │ │ ├── ErrorListener.java
│ │ │ │ │ ├── RequestCallback.java
│ │ │ │ │ └── RxErrorHandler.java
│ │ │ │ ├── cookies/
│ │ │ │ │ ├── CookiesManager.java
│ │ │ │ │ ├── OkHttpCookies.java
│ │ │ │ │ └── PersistentCookieStore.java
│ │ │ │ └── progress/
│ │ │ │ ├── ProgressCancelListener.java
│ │ │ │ └── ProgressDialogHandler.java
│ │ │ ├── service/
│ │ │ │ └── InitializeService.java
│ │ │ └── utils/
│ │ │ ├── ACache.java
│ │ │ ├── BaseEvent.java
│ │ │ ├── ConstantUtils.java
│ │ │ ├── LogUtils.java
│ │ │ ├── MD5Utils.java
│ │ │ ├── PreferenceTool.java
│ │ │ ├── RetryWithDelay.java
│ │ │ ├── RxUtils.java
│ │ │ ├── StatusBarUtils.java
│ │ │ └── ToastUtil.java
│ │ └── res/
│ │ ├── drawable/
│ │ │ ├── register_border.xml
│ │ │ ├── register_border_2.xml
│ │ │ ├── register_border_9.xml
│ │ │ ├── shape_gradient.xml
│ │ │ ├── style_progress_bar.xml
│ │ │ └── toast_shape.xml
│ │ ├── layout/
│ │ │ ├── activity_common__login.xml
│ │ │ ├── activity_common__register.xml
│ │ │ ├── activity_common__webview.xml
│ │ │ ├── layout_fragmhome_tab.xml
│ │ │ ├── layout_toolbar.xml
│ │ │ └── toast_layout.xml
│ │ └── values/
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test/
│ └── java/
│ └── com/
│ └── senon/
│ └── lib_common/
│ └── ExampleUnitTest.java
├── lib_opensource/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── senon/
│ │ └── lib_opensource/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ └── AndroidManifest.xml
│ └── test/
│ └── java/
│ └── com/
│ └── senon/
│ └── lib_opensource/
│ └── ExampleUnitTest.java
├── module_art/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── senon/
│ │ └── module_art/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── debug/
│ │ │ └── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── senon/
│ │ │ └── module_art/
│ │ │ ├── App_Art.java
│ │ │ ├── MainActivity.java
│ │ │ ├── SplashActivity.java
│ │ │ ├── adapter/
│ │ │ │ └── ArtMainAdapter.java
│ │ │ ├── contract/
│ │ │ │ └── ArtMainFragmentCon.java
│ │ │ ├── fragment/
│ │ │ │ └── ArtMainFragment.java
│ │ │ └── presenter/
│ │ │ └── ArtMainFragmentPre.java
│ │ ├── release/
│ │ │ └── AndroidManifest.xml
│ │ └── res/
│ │ ├── drawable/
│ │ │ ├── art_launcher_background.xml
│ │ │ ├── art_shape_transp_con20.xml
│ │ │ ├── art_shape_white_con30.xml
│ │ │ └── art_shape_yellow_con20.xml
│ │ ├── layout/
│ │ │ ├── art_activity_main.xml
│ │ │ ├── art_activity_splash.xml
│ │ │ ├── art_adapter_artmain_fragment_article.xml
│ │ │ ├── art_adapter_artmain_fragment_head.xml
│ │ │ ├── art_adapter_artmain_fragment_head_item.xml
│ │ │ └── art_fragment_main.xml
│ │ └── values/
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test/
│ └── java/
│ └── com/
│ └── senon/
│ └── module_art/
│ └── ExampleUnitTest.java
├── module_home/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── senon/
│ │ └── module_home/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── debug/
│ │ │ └── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── senon/
│ │ │ └── module_home/
│ │ │ ├── App_Home.java
│ │ │ ├── MainActivity.java
│ │ │ ├── SplashActivity.java
│ │ │ ├── activity/
│ │ │ │ ├── HomeArticleActivity.java
│ │ │ │ └── HomeProjectActivity.java
│ │ │ ├── adapter/
│ │ │ │ └── HomeMainAdapter.java
│ │ │ ├── contract/
│ │ │ │ ├── HomeArticleActivityCon.java
│ │ │ │ ├── HomeMainFragmentCon.java
│ │ │ │ └── HomeProjectActivityCon.java
│ │ │ ├── fragment/
│ │ │ │ └── HomeMainFragment.java
│ │ │ └── presenter/
│ │ │ ├── HomeArticleActivityPre.java
│ │ │ ├── HomeMainFragmentPre.java
│ │ │ └── HomeProjectActivityPre.java
│ │ ├── release/
│ │ │ └── AndroidManifest.xml
│ │ └── res/
│ │ ├── drawable/
│ │ │ ├── home_ic_launcher_background.xml
│ │ │ ├── home_shape_stro_red_con30.xml
│ │ │ └── home_shape_white_con30.xml
│ │ ├── layout/
│ │ │ ├── home_activity_home_article.xml
│ │ │ ├── home_activity_home_project.xml
│ │ │ ├── home_activity_main.xml
│ │ │ ├── home_activity_splash.xml
│ │ │ ├── home_adapter_homemain_fragment_article.xml
│ │ │ ├── home_adapter_homemain_fragment_banneritem.xml
│ │ │ ├── home_adapter_homemain_fragment_head.xml
│ │ │ ├── home_adapter_homemain_fragment_project.xml
│ │ │ └── home_fragment_main.xml
│ │ └── values/
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test/
│ └── java/
│ └── com/
│ └── senon/
│ └── module_home/
│ └── ExampleUnitTest.java
├── module_life/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── senon/
│ │ └── module_life/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── debug/
│ │ │ └── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── senon/
│ │ │ └── module_life/
│ │ │ ├── App_Life.java
│ │ │ ├── MainActivity.java
│ │ │ ├── SplashActivity.java
│ │ │ ├── activity/
│ │ │ │ └── KnowledgeSystemActivity.java
│ │ │ ├── contract/
│ │ │ │ ├── KnowledgeSysActivityCon.java
│ │ │ │ └── LifeMainFragmentCon.java
│ │ │ ├── fragment/
│ │ │ │ └── LifeMainFragment.java
│ │ │ └── presenter/
│ │ │ ├── KnowledgeSysActivityPre.java
│ │ │ └── LifeMainFragmentPre.java
│ │ ├── release/
│ │ │ └── AndroidManifest.xml
│ │ └── res/
│ │ ├── drawable/
│ │ │ ├── life_ic_launcher_background.xml
│ │ │ ├── life_shape_gray_10.xml
│ │ │ └── life_shape_white_con30.xml
│ │ ├── layout/
│ │ │ ├── life_activity_home_article.xml
│ │ │ ├── life_activity_main.xml
│ │ │ ├── life_activity_splash.xml
│ │ │ ├── life_adapter_knowledgesys_item.xml
│ │ │ ├── life_adapter_lifemain_flowlayout_item.xml
│ │ │ ├── life_adapter_lifemain_fragment.xml
│ │ │ └── life_fragment_main.xml
│ │ └── values/
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test/
│ └── java/
│ └── com/
│ └── senon/
│ └── module_life/
│ └── ExampleUnitTest.java
├── module_talent/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── senon/
│ │ └── module_talent/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── debug/
│ │ │ └── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── senon/
│ │ │ └── module_talent/
│ │ │ ├── App_Talent.java
│ │ │ ├── MainActivity.java
│ │ │ ├── activity/
│ │ │ │ ├── AboutActivity.java
│ │ │ │ └── CollectionActivity.java
│ │ │ ├── contract/
│ │ │ │ ├── CollectionActivityCon.java
│ │ │ │ └── TalentMainFragmentCon.java
│ │ │ ├── fragment/
│ │ │ │ └── TalentMainFragment.java
│ │ │ └── presenter/
│ │ │ ├── CollectionActivityPre.java
│ │ │ └── TalentMainFragmentPre.java
│ │ ├── release/
│ │ │ └── AndroidManifest.xml
│ │ └── res/
│ │ ├── drawable/
│ │ │ ├── talent_ic_launcher_background.xml
│ │ │ └── talent_shape_white_con30.xml
│ │ ├── layout/
│ │ │ ├── talent_activity_about.xml
│ │ │ ├── talent_activity_collection.xml
│ │ │ ├── talent_activity_main.xml
│ │ │ ├── talent_adapter_collection.xml
│ │ │ └── talent_fragment_main.xml
│ │ └── values/
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test/
│ └── java/
│ └── com/
│ └── senon/
│ └── module_talent/
│ └── ExampleUnitTest.java
├── senon.jks
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild
================================================
FILE: .idea/encodings.xml
================================================
================================================
FILE: README.md
================================================
# WanAndroid
玩安卓http://www.wanandroid.com/ 客户端模块化设计app,包含MVP+Retrofit+Rxjava+Rxlifecycle+Glide+Eventbus+ARouter.
构建一个平面化、简而美的玩安卓app客户端。
如果不清楚如何将Android工程模块化,请看Android模块化使用
# API
app采用玩安卓开放api
# 主要功能
首页:Banner
首页:最新博文(5条)、最新项目(5条)
体系:一级二级下面全部博文
公众号:所有公众号列表
公众号:某公众号下所有博文
个人中心:登录、退出、收藏、清除缓存
# 屏幕截图

![]()

![]()

![]()
# 子模块打包
工程采用的是模块化,如果想要单独跑或者打包各个子模块,那么请将gradle.properties改为
isBuildModule=true
如果需要整体打包app,则
isBuildModule=false
# 三方轮子
Rxjava
RxAndroid
Retrofit
Okhttp
ARouter
Glide
EventBus
FlowLayout
MZBannerView
AndroidAutoSize
HTextView
CircleImageView
LRecyclerView
Sweetalertdialog
Awesome-WanAndroid
# APK下载

![]()
因为图方便,apk资源是放在leancloud上的,微信扫码下载不了,用手机浏览器扫码可下载。
# 版本
V 1.0.1
1.修复各模块清单文件合并问题
V 1.0.0
1.第一版
# Thanks
感谢以上所有开源框架。项目用于学习交流,如果你觉得本项目好,谢谢star哦!
================================================
FILE: app/.gitignore
================================================
/build
================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
android {
signingConfigs {
config {
keyAlias 'senon'
keyPassword '123456'
storeFile file('../senon.jks')
storePassword '123456'
}
}
compileSdkVersion rootProject.ext.android["compileSdkVersion"]
defaultConfig {
applicationId "com.senon.xfhmoudel"
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
versionCode rootProject.ext.android["versionCode"]
versionName rootProject.ext.android["versionName"]
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
includeCompileClasspath = true
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
}
}
aaptOptions {
cruncherEnabled = false
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
testImplementation rootProject.ext.dependencies["junit"]
if (isBuildModule.toBoolean()) {
implementation project(':lib_common')
} else {
implementation project(':module_home')
implementation project(':module_life')
implementation project(':module_art')
implementation project(':module_talent')
}
annotationProcessor rootProject.ext.dependencies["butterknife-compiler"]
annotationProcessor rootProject.ext.dependencies["router-compiler"]
api rootProject.ext.dependencies["htextview-base"]
api rootProject.ext.dependencies["htextview-fall"]
}
================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: app/src/androidTest/java/com/senon/xfhmoudel/ExampleInstrumentedTest.java
================================================
package com.senon.xfhmoudel;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see Testing documentation
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.senon.xfhmoudel", appContext.getPackageName());
}
}
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
================================================
FILE: app/src/main/java/com/senon/xfhmoudel/App.java
================================================
package com.senon.xfhmoudel;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.base.BaseApplication;
import com.senon.lib_common.utils.ConstantUtils;
/**
* 工程Application
*/
public class App extends BaseApplication {
@Override
public void onCreate() {
super.onCreate();
initARouter();
}
private void initARouter() {
if (ConstantUtils.isAppDebug()) {
//开启InstantRun之后,一定要在ARouter.init之前调用openDebug
ARouter.openDebug();
ARouter.openLog();
}
ARouter.init(this);
}
}
================================================
FILE: app/src/main/java/com/senon/xfhmoudel/FragmentHomeActivity.java
================================================
package com.senon.xfhmoudel;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.utils.StatusBarUtils;
import com.senon.lib_common.utils.ToastUtil;
import com.senon.module_art.fragment.ArtMainFragment;
import com.senon.module_home.fragment.HomeMainFragment;
import com.senon.module_life.fragment.LifeMainFragment;
import com.senon.module_talent.fragment.TalentMainFragment;
import java.util.ArrayList;
import java.util.List;
/**
* App主页
*/
@Route(path = ConstantArouter.PATH_APP_FRAGMENTHOMEACTIVITY)
public class FragmentHomeActivity extends AppCompatActivity {
private ViewPager viewPager;
private TabLayout tabs;
private FragmentManager fragmentManager;//声明fragment管理
private List fragmentList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StatusBarUtils.with(this).init();
setContentView(R.layout.activity_fragment_home);
ComUtil.changeStatusBarTextColor(this,true);
viewPager = findViewById(R.id.vp);
tabs = findViewById(R.id.tabs);
initVp$Tab();
}
private void initVp$Tab() {
fragmentList.add(new HomeMainFragment());
fragmentList.add(new LifeMainFragment());
fragmentList.add(new ArtMainFragment());
fragmentList.add(new TalentMainFragment());
fragmentManager = getSupportFragmentManager();
FragmentPagerAdapter pagerAdapter = new MyFragmentPagerAdapter(fragmentManager);
viewPager.setAdapter(pagerAdapter);
viewPager.setOffscreenPageLimit(fragmentList.size());
tabs.setupWithViewPager(viewPager);//将TabLayout和ViewPager关联起来。
tabs.setTabsFromPagerAdapter(pagerAdapter);//给Tabs设置适配器
for (int i = 0; i < tabs.getTabCount(); i++) {
TabLayout.Tab tab = tabs.getTabAt(i);
if (tab != null) {
tab.setCustomView(getTabView(i));
View view = tab.getCustomView();
if(i == 0){
setTextColor(view,0,true);
}
}
}
tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
//在这里可以设置选中状态下 tab字体显示样式
View view = tab.getCustomView();
setTextColor(view,tab.getPosition(),true);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
View view = tab.getCustomView();
setTextColor(view,tab.getPosition(),false);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private String[] titles = {"首页","体系","公众号","我的"};
private int[] colors = {R.color.login_bg_end_1,R.color.tablayout_tv_gray};
private int[] mipmaps = {R.mipmap.ic_tabbar_discover,R.mipmap.ic_tabbar_mainframe,R.mipmap.ic_tabbar_order,R.mipmap.ic_tabbar_me};
private int[] mipmaphls = {R.mipmap.ic_tabbar_discoverhl,R.mipmap.ic_tabbar_mainframehl,R.mipmap.ic_tabbar_orderhl,R.mipmap.ic_tabbar_mehl};
private View getTabView(int curPos) {
View view = LayoutInflater.from(this).inflate(R.layout.layout_fragmhome_tab, null);
ImageView igv = (ImageView) view.findViewById(R.id.tab_item_igv);
TextView tv = (TextView) view.findViewById(R.id.tab_item_tv);
tv.setText(titles[curPos]);
igv.setImageResource(mipmaps[curPos]);
setTextColor(tv,curPos,false);
return view;
}
private void setTextColor(View view,int position,boolean select){
if (null != view && view instanceof RelativeLayout) {
TextView tv = (TextView) view.findViewById(R.id.tab_item_tv);
ImageView igv = (ImageView) view.findViewById(R.id.tab_item_igv);
tv.setTextSize(TypedValue.COMPLEX_UNIT_MM,22);
tv.setTextColor(ContextCompat.getColor(this,select ? colors[0] : colors[1]));
igv.setImageResource(select ? mipmaphls[position] : mipmaps[position]);
}
}
//记录用户首次点击返回键的时间
private long firstTime=0;
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
long secondTime = System.currentTimeMillis();
if (secondTime - firstTime > 2000) {
ToastUtil.initToast("再按一次返回键退出程序");
firstTime = secondTime;
return true;
} else {
System.exit(0);
}
break;
}
return super.onKeyUp(keyCode, event);
}
//FragmentPagerAdapter
class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList.size();
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return super.getPageTitle(position);
}
}
}
================================================
FILE: app/src/main/java/com/senon/xfhmoudel/SplashActivity.java
================================================
package com.senon.xfhmoudel;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.hanks.htextview.base.HTextView;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.utils.LogUtils;
import com.senon.lib_common.utils.StatusBarUtils;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
/**
* app 闪屏页
*/
@Route(path = ConstantArouter.PATH_APP_SPLASHACTIVITY)
public class SplashActivity extends AppCompatActivity {
private final int count = 5;//count秒后跳过
private TextView version_tv,timmer_tv;
private Disposable disposable;
private HTextView anim_tv1, anim_tv2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StatusBarUtils.with(this).init();
setContentView(R.layout.activity_splash);
ComUtil.changeStatusBarTextColor(this,true);
version_tv = findViewById(R.id.version_tv);
timmer_tv = findViewById(R.id.timmer_tv);
anim_tv1 = findViewById(R.id.anim_tv1);
anim_tv2 = findViewById(R.id.anim_tv2);
try {
version_tv.setText("版本 V" + getPackageManager().getPackageInfo(this.getPackageName(), 0).versionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
version_tv.setText("");
}
timmer_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(disposable != null){
disposable.dispose();
}
gotoMainAct();
}
});
initTimer();
}
private void initTimer() {
Observable.interval(0, 1, TimeUnit.SECONDS)//设置0延迟,每隔一秒发送一条数据
.take(count+1) //设置发送count+1次 因为是count~0秒
.map(new Function() {
@Override
public Long apply(Long aLong) throws Exception {
LogUtils.d("apply"+(count-aLong));
return count-aLong; //发送倒计时
}
})
.doOnSubscribe(new Consumer() {// 观察者订阅时调用
@Override
public void accept(Disposable disposable){
timmer_tv.setEnabled(true);//在发送数据的时候设置为可以跳过
timmer_tv.setVisibility(View.VISIBLE);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())//操作UI要在UI线程
.subscribe(new Observer() {
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onComplete() {
LogUtils.d("onCompleted: "+System.currentTimeMillis());
timmer_tv.setEnabled(false);
gotoMainAct();
}
@Override
public void onSubscribe(Disposable d) {
timmer_tv.setText(count + " 跳过");
disposable = d;
}
@Override
public void onNext(Long aLong) { //接受到一条就是会操作一次UI
LogUtils.d("onNext: "+aLong);
timmer_tv.setText(aLong + " 跳过");
initHTextView(aLong);
}
});
}
private void initHTextView(Long aLong) {
if(aLong == (2 * count / 3) + 1){//显示第一排文字的时间
anim_tv1.animateText("Talk is cheap.");
}else if(aLong == count / 2 +1){//显示第二排文字的时间
anim_tv2.animateText("Show me the code!");
}
}
private void gotoMainAct(){
ARouter.getInstance().build(ConstantArouter.PATH_APP_FRAGMENTHOMEACTIVITY)//指定跳到那个页面
.navigation();
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
if(disposable != null){
disposable.dispose();
}
}
}
================================================
FILE: app/src/main/java/com/senon/xfhmoudel/TestActivity.java
================================================
package com.senon.xfhmoudel;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.ConstantLoginArouter;
import com.senon.lib_common.utils.StatusBarUtils;
/**
* app 模块主页面
*/
@Route(path = ConstantLoginArouter.PATH_APP_MAINACTIVITY)
public class TestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StatusBarUtils.with(this).init();
setContentView(R.layout.activity_test);
ComUtil.changeStatusBarTextColor(this,true);
}
public void toA(View view){
// 1. 应用内简单的跳转(通过URL跳转在'进阶用法'中)
// ARouter.getInstance().build(ConstantLoginArouter.PATH_FIRST_MAINACTIVITY).navigation();
// String curUrl = ConstantLoginArouter.getCurRouter(this.getClass().getSimpleName());
String curUrl = ConstantLoginArouter.getCurRouter(ConstantLoginArouter.PATH_HOME_MAINACTIVITY);
ARouter.getInstance().build(ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)//指定跳到那个页面
.withString("targetUrl",ConstantArouter.PATH_APP_FRAGMENTHOMEACTIVITY)//传入目标页面路由地址 可以在指定页面跳入到目标页面
.navigation();
// Uri testUriMix = Uri.parse("router://com.senon.firstmoduel/firstmoduel/firstmainactivity");
// ARouter.getInstance().build(testUriMix)
// .withString("key1", "value1")
// .navigation();
}
public void toB(View view){
ARouter.getInstance().build(ConstantArouter.PATH_APP_FRAGMENTHOMEACTIVITY)
.navigation();
}
}
================================================
FILE: app/src/main/res/drawable/ic_launcher_background.xml
================================================
================================================
FILE: app/src/main/res/drawable/shape_splash_timer.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_fragment_home.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_splash.xml
================================================
================================================
FILE: app/src/main/res/layout/activity_test.xml
================================================
================================================
FILE: app/src/main/res/values/colors.xml
================================================
#3F51B5
#303F9F
#FF4081
================================================
FILE: app/src/main/res/values/strings.xml
================================================
玩安卓
================================================
FILE: app/src/main/res/values/styles.xml
================================================
================================================
FILE: app/src/test/java/com/senon/xfhmoudel/ExampleUnitTest.java
================================================
package com.senon.xfhmoudel;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see Testing documentation
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "dependencies.gradle"
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
================================================
FILE: dependencies.gradle
================================================
def supportVersion = "27.1.1"
def rxBindingVersion = "3.0.0-alpha1"
def retrofitVersion = "2.4.0"
def okHttpVersion = "3.11.0"
def stethoVersion = "1.5.0"
def butterKnifeVersion = "8.5.1"
def daggerVersion = "2.8"
def routerVersion = "0.2.3"
def htextviewVersion = "0.1.6"
project.ext {
android = [
compileSdkVersion: 27,
minSdkVersion : 19,
targetSdkVersion : 27,
versionCode : 2,
versionName : "1.0.1"
]
dependencies = [
//android-support
"support-v4" : "com.android.support:support-v4:${supportVersion}",
"appcompat-v7" : "com.android.support:appcompat-v7:${supportVersion}",
"design" : "com.android.support:design:${supportVersion}",
"recyclerview-v7" : "com.android.support:recyclerview-v7:${supportVersion}",
"cardview-v7" : "com.android.support:cardview-v7:${supportVersion}",
"constraint-layout" : "com.android.support.constraint:constraint-layout:1.1.3",
//java8-support
"stream" : "com.annimon:stream:1.0.8",
//rx
"rxjava" : "io.reactivex.rxjava2:rxjava:2.2.3",
"rxandroid" : "io.reactivex.rxjava2:rxandroid:2.1.0",
"rxlifecycle" : "com.trello.rxlifecycle2:rxlifecycle:2.2.1",
"rxlifecycle-components" : "com.trello.rxlifecycle2:rxlifecycle-components:2.2.1",
"rxbinding" : "com.jakewharton.rxbinding3:rxbinding-core:${rxBindingVersion}",
"rxbinding-appcompat-v7" : "com.jakewharton.rxbinding3:rxbinding-appcompat:${rxBindingVersion}",
"rxbinding-recyclerview-v7" : "com.jakewharton.rxbinding3:rxbinding-recyclerview:${rxBindingVersion}",
//retrofit
"retrofit" : "com.squareup.retrofit2:retrofit:${retrofitVersion}",
"adapter-rxjava" : "com.squareup.retrofit2:adapter-rxjava2:${retrofitVersion}",
"retrofit-converter" : "com.squareup.retrofit2:converter-scalars:${retrofitVersion}",
"retrofit-converter-gson" : "com.squareup.retrofit2:converter-gson:${retrofitVersion}",
//dagger
"dagger" : "com.google.dagger:dagger:${daggerVersion}",
"dagger-compiler" : "com.google.dagger:dagger-compiler:${daggerVersion}",
//router
// 替换成最新版本, 需要注意的是api
// 要与compiler匹配使用,均使用最新版可以保证兼容
"router" : "com.alibaba:arouter-api:1.4.1",
"router-compiler" : "com.alibaba:arouter-compiler:1.2.2",
//butterKnife 子模块的libary与application转化 R 与R2文件转化(所以最好不用)
//https://www.jianshu.com/p/1fa69ad55b0e
"butterknife" : "com.jakewharton:butterknife:${butterKnifeVersion}",
"butterknife-compiler" : "com.jakewharton:butterknife-compiler:${butterKnifeVersion}",
//facebook
"stetho" : "com.facebook.stetho:stetho:${stethoVersion}",
"stetho-okhttp3" : "com.facebook.stetho:stetho-okhttp3:${stethoVersion}",
//okHttp3
"okhttp3" : "com.squareup.okhttp3:okhttp:${okHttpVersion}",
"okhttp3-logging-interceptor" : "com.squareup.okhttp3:logging-interceptor:${okHttpVersion}",
//others
"ormlite-android" : "com.j256.ormlite:ormlite-android:5.0",
//test
"junit" : "junit:junit:4.12",
//sweet alert dialog
"sweetalert" : "com.github.f0ris.sweetalert:library:1.5.1",
// "sweetalert" : "cn.pedant.sweetalert:library:1.3",
//autosize
"autosize" : "me.jessyan:autosize:1.0.6",
"lrecyclerview" : "com.github.jdsjlzx:LRecyclerView:1.4.3",
"glide" : "com.github.bumptech.glide:glide:3.7.0",
"eventbus" : "org.greenrobot:eventbus:3.1.1",
"smartrefreshlayout" : "com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-20",
"bannerview" : "com.github.pinguo-zhouwei:MZBannerView:v2.0.2",
"flowlayout" : "com.hyman:flowlayout-lib:1.1.2",
"circleimageview" : "de.hdodenhof:circleimageview:2.2.0",
//好看的字体动画
"htextview-base" : "com.hanks:htextview-base:${htextviewVersion}",
"htextview-fall" : "com.hanks:htextview-fall:${htextviewVersion}",
]
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Sat Nov 17 20:54:41 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.enableAapt2 = false;
#release
isBuildModule=false
#ģ
#isBuildModule=true
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: lib_common/.gitignore
================================================
/build
================================================
FILE: lib_common/build.gradle
================================================
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.android["compileSdkVersion"]
defaultConfig {
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
versionCode rootProject.ext.android["versionCode"]
versionName rootProject.ext.android["versionName"]
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
testImplementation rootProject.ext.dependencies["junit"]
api project(':lib_opensource')
annotationProcessor rootProject.ext.dependencies["router-compiler"]
}
================================================
FILE: lib_common/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: lib_common/src/androidTest/java/com/senon/lib_common/ExampleInstrumentedTest.java
================================================
package com.senon.lib_common;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see Testing documentation
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.senon.lib_common", appContext.getPackageName());
}
}
================================================
FILE: lib_common/src/main/AndroidManifest.xml
================================================
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/AppConfig.java
================================================
package com.senon.lib_common;
import com.senon.lib_common.utils.ConstantUtils;
/**
* APP配置参数
*/
public class AppConfig {
public static final String BASE_URL = "https://www.wanandroid.com/";
public static final String PATH_DATA = ConstantUtils.getAPPContext().getCacheDir().getAbsolutePath()+"/"+"data";
public static final String PATH_CACHE = PATH_DATA+"/"+"Cache";
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/ComUtil.java
================================================
package com.senon.lib_common;
import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.os.Build;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.EditText;
import com.senon.lib_common.utils.ConstantUtils;
import com.senon.lib_common.utils.MD5Utils;
import com.senon.lib_common.utils.ToastUtil;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* ComUtil
*/
public class ComUtil {
public static void changeStatusBarTextColor(Context context,boolean isBlack) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (isBlack) {
//设置状态栏黑色字体
((Activity)context).getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
//恢复状态栏白色字体
((Activity)context).getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
}
}
public static boolean isNumeric(String str) {
Pattern pattern = Pattern.compile("^1[3|4|5|7|8|9][0-9]{9}$");
Matcher isNum = pattern.matcher(str);
if (!isNum.matches()) {
return false;
}
return true;
}
public static boolean isChinese(String str) {
Pattern pattern = Pattern.compile("^[\\u4E00-\\u9FA5]+$");
Matcher isNum = pattern.matcher(str);
if (!isNum.matches()) {
return false;
}
return true;
}
//long型时间转换为字符串时间类型
public static String longToString(Object longTime, String timeFormat) {
SimpleDateFormat formatter = new SimpleDateFormat(timeFormat == null ? "yyyy-MM-dd" : timeFormat);
long time = 0;
if (longTime instanceof Integer || longTime instanceof Long) {
return formatter.format(longTime);
} else if (longTime instanceof String) {
return formatter.format(Long.valueOf((String) longTime));
}
return "时间获取错误";
}
//检查是否有可用网络
public static boolean isNetworkConnected() {
ConnectivityManager connectivityManager = (ConnectivityManager) ConstantUtils.getAPPContext().
getSystemService(Context.CONNECTIVITY_SERVICE);
assert connectivityManager != null;
return connectivityManager.getActiveNetworkInfo() != null;
}
// 屏幕宽度(像素)
public static int getScreenWidth(Context context) {
DisplayMetrics metric = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metric);
return metric.widthPixels;
}
public static int getScreenHeight(Context context) {
DisplayMetrics metric = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metric);
return metric.heightPixels;
}
public static String getMd5Str(HashMap map) {
StringBuffer sb = new StringBuffer();
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
sb.append(entry.getValue().toString());
}
return MD5Utils.getMd5(sb.toString() );
}
public static HashMap getMd5Str(String[] keyArray, String[] valueArray) {
HashMap map = new HashMap<>();
StringBuffer sb = new StringBuffer();
if (keyArray.length != valueArray.length) {
ToastUtil.initToast("key value长度不对应");
} else {
for (int i = 0; i < keyArray.length; i++) {
map.put(keyArray[i], valueArray[i]);
}
for (int i = 0; i < valueArray.length; i++) {
sb.append(valueArray[i]);
}
map.put("secret", MD5Utils.getMd5(sb.toString()));
return map;
}
return null;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/ConstantArouter.java
================================================
package com.senon.lib_common;
/**
* 所有模块均依赖commonmoduel 所以路由跳转均写入本Constant方便调用
* 常量类
* 其中: 路由跳转命名统一用:path+模块名+Activity名
*/
public class ConstantArouter {
/**
* App
*/
public static final String PATH_APP_SPLASHACTIVITY = "/app/SplashActivity";
public static final String PATH_APP_FRAGMENTHOMEACTIVITY = "/app/FragmentHomeActivity";
/**
* home 主页
*/
public static final String PATH_HOME_MAINACTIVITY = "/home/MainActivity";
public static final String PATH_HOME_HOMEARTICLEACTIVITY = "/home/HomeArticleActivity";
public static final String PATH_HOME_HOMEPROJECTACTIVITY = "/home/HomeProjectActivity";
/**
* life 知识体系
*/
public static final String PATH_LIFE_KNOWLEDGESYSTEMACTIVITY = "/life/KnowledgeSystemActivity";
/**
* common
*/
public static final String PATH_COMMON_REGISTERACTIVITY = "/lib_common/CommonRegisterActivity";
public static final String PATH_COMMON_WEBVIEWCTIVITY = "/lib_common/CommonWebviewActivity";
/**
* talent 个人中心
*/
public static final String PATH_TALENT_COLLECTIONACTIVITY = "/talent/CollectionActivity";
public static final String PATH_TALENT_ABOUTACTIVITY = "/talent/AboutActivity";
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/ConstantLoginArouter.java
================================================
package com.senon.lib_common;
import java.util.HashMap;
import java.util.Map;
/**
* 判断是某个模块登录的
*/
public class ConstantLoginArouter {
public static Map activityRouterMap = new HashMap<>();
//app主页
public static final String PATH_APP_MAINACTIVITY = "/app/MainActivity";
//home主页
public static final String PATH_HOME_MAINACTIVITY = "/home/HomeMainActivity";
//Life首页
public static final String PATH_LIFE_MAINACTIVITY = "/life/LifeMainActivity";
//Art首页
public static final String PATH_ART_MAINACTIVITY = "/art/ArtMainActivity";
//Talent首页
public static final String PATH_TALENT_MAINACTIVITY = "/talent/TalentMainActivity";
//登录 注册
public static final String PATH_COMMON_LOGINACTIVITY = "/lib_common/CommonLoginActivity";
static {
activityRouterMap.put(getActivityName(PATH_APP_MAINACTIVITY), PATH_APP_MAINACTIVITY);
activityRouterMap.put(getActivityName(PATH_HOME_MAINACTIVITY), PATH_HOME_MAINACTIVITY);
activityRouterMap.put(getActivityName(PATH_LIFE_MAINACTIVITY), PATH_LIFE_MAINACTIVITY);
activityRouterMap.put(getActivityName(PATH_ART_MAINACTIVITY), PATH_ART_MAINACTIVITY);
activityRouterMap.put(getActivityName(PATH_TALENT_MAINACTIVITY), PATH_TALENT_MAINACTIVITY);
activityRouterMap.put(getActivityName(PATH_COMMON_LOGINACTIVITY), PATH_COMMON_LOGINACTIVITY);
}
private static String getActivityName(String routerUrl) {
int pos = routerUrl.lastIndexOf("/");
return routerUrl.substring(pos + 1);
}
public static String getCurRouter(String activityName) {
return activityRouterMap.get(activityName);
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/adapter/CommonAdapter.java
================================================
package com.senon.lib_common.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.List;
public abstract class CommonAdapter extends BaseAdapter {
protected LayoutInflater mInflater;
protected Context mContext;
protected List mDatas;
protected final int mItemLayoutId;
public CommonAdapter(Context context, List mDatas, int itemLayoutId) {
mInflater = LayoutInflater.from(context);
this.mContext = context;
this.mDatas = mDatas;
this.mItemLayoutId = itemLayoutId;
}
@Override
public int getCount() {
return mDatas.size();
}
@Override
public T getItem(int position) {
return mDatas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final CommonHolder viewHolder = getViewHolder(position, convertView, parent);
convert(viewHolder, getItem(position),position);
return viewHolder.getConvertView();
}
public abstract void convert(CommonHolder helper, T item,int position);
private CommonHolder getViewHolder(int position, View convertView, ViewGroup parent) {
return CommonHolder.get(mContext, convertView, parent, mItemLayoutId, position);
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/adapter/CommonHolder.java
================================================
package com.senon.lib_common.adapter;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.util.Linkify;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.widget.Checkable;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
public class CommonHolder {
private final SparseArray mViews;
private int mPosition;
private View mConvertView;
private Context mContext;
private int mLayoutId;
private CommonHolder(Context context, ViewGroup parent, int layoutId, int position) {
this.mLayoutId = layoutId;
this.mContext = context;
this.mPosition = position;
this.mViews = new SparseArray();
mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
//setTag
mConvertView.setTag(this);
}
/**
* 拿到一个CommonHolder对象
*
* @param context
* @param convertView
* @param parent
* @param layoutId
* @param position
* @return
*/
public static CommonHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position) {
if (convertView == null) {
return new CommonHolder(context, parent, layoutId, position);
}
return (CommonHolder) convertView.getTag();
}
/**
* 通过控件的Id获取对于的控件,如果没有则加入views
*
* @param viewId
* @return
*/
public T getView(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
public View getConvertView() {
return mConvertView;
}
/**
* 为TextView设置字符串
*
* @param viewId
* @param text
* @return
*/
public CommonHolder setText(int viewId, String text) {
TextView view = getView(viewId);
view.setText(text);
return this;
}
public String getText(int viewId) {
TextView view = getView(viewId);
return view.getText().toString().trim();
}
public CommonHolder setEnabled(int viewId, boolean enabled) {
View view = getView(viewId);
view.setEnabled(enabled);
return this;
}
public CommonHolder setSelected(int viewId, boolean selected) {
View view = getView(viewId);
view.setSelected(selected);
return this;
}
/**
* 为ImageView设置图片
*
* @param viewId
* @param drawableId
* @return
*/
public CommonHolder setImageResource(int viewId, int drawableId) {
ImageView view = getView(viewId);
view.setImageResource(drawableId);
return this;
}
/**
* 为ImageView设置图片
*
* @param viewId
* @param bm
* @return
*/
public CommonHolder setImageBitmap(int viewId, Bitmap bm) {
ImageView view = getView(viewId);
view.setImageBitmap(bm);
return this;
}
public CommonHolder setColorFilter(int viewId, Integer colorFilter) {
ImageView imageView = getView(viewId);
if (colorFilter == null) imageView.setColorFilter(null);
else imageView.setColorFilter(colorFilter);
return this;
}
public CommonHolder setImageDrawable(int viewId, Drawable drawable) {
ImageView view = getView(viewId);
view.setImageDrawable(drawable);
return this;
}
public CommonHolder setBackgroundColor(int viewId, int color) {
View view = getView(viewId);
view.setBackgroundColor(color);
return this;
}
public CommonHolder setBackgroundRes(int viewId, int backgroundRes) {
View view = getView(viewId);
view.setBackgroundResource(backgroundRes);
return this;
}
public CommonHolder setTextColor(int viewId, int textColor) {
TextView view = getView(viewId);
view.setTextColor(textColor);
return this;
}
public CommonHolder setTextColorRes(int viewId, int textColorRes) {
TextView view = getView(viewId);
view.setTextColor(mContext.getResources().getColor(textColorRes));
return this;
}
@SuppressLint("NewApi")
public CommonHolder setAlpha(int viewId, float value) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getView(viewId).setAlpha(value);
} else {
// Pre-honeycomb hack to set Alpha value
AlphaAnimation alpha = new AlphaAnimation(value, value);
alpha.setDuration(0);
alpha.setFillAfter(true);
getView(viewId).startAnimation(alpha);
}
return this;
}
public CommonHolder setVisible(int viewId, int visible) {
View view = getView(viewId);
view.setVisibility(visible);
return this;
}
public CommonHolder linkify(int viewId) {
TextView view = getView(viewId);
Linkify.addLinks(view, Linkify.ALL);
return this;
}
public CommonHolder setTypeface(Typeface typeface, int... viewIds) {
for (int viewId : viewIds) {
TextView view = getView(viewId);
view.setTypeface(typeface);
view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
}
return this;
}
public CommonHolder setProgress(int viewId, int progress) {
ProgressBar view = getView(viewId);
view.setProgress(progress);
return this;
}
public CommonHolder setProgress(int viewId, int progress, int max) {
ProgressBar view = getView(viewId);
view.setMax(max);
view.setProgress(progress);
return this;
}
public CommonHolder setMax(int viewId, int max) {
ProgressBar view = getView(viewId);
view.setMax(max);
return this;
}
public CommonHolder setRating(int viewId, float rating) {
RatingBar view = getView(viewId);
view.setRating(rating);
return this;
}
public CommonHolder setRating(int viewId, float rating, int max) {
RatingBar view = getView(viewId);
view.setMax(max);
view.setRating(rating);
return this;
}
public CommonHolder setTag(int viewId, Object tag) {
View view = getView(viewId);
view.setTag(tag);
return this;
}
public CommonHolder setTag(int viewId, int key, Object tag) {
View view = getView(viewId);
view.setTag(key, tag);
return this;
}
public CommonHolder setChecked(int viewId, boolean checked) {
Checkable view = (Checkable) getView(viewId);
view.setChecked(checked);
return this;
}
/**
* 关于事件的
*/
public CommonHolder setOnClickListener(int viewId, View.OnClickListener listener) {
View view = getView(viewId);
view.setOnClickListener(listener);
return this;
}
public CommonHolder setOnTouchListener(int viewId, View.OnTouchListener listener) {
View view = getView(viewId);
view.setOnTouchListener(listener);
return this;
}
public CommonHolder setOnLongClickListener(int viewId, View.OnLongClickListener listener) {
View view = getView(viewId);
view.setOnLongClickListener(listener);
return this;
}
/**
* 设置中划线
*
* @return
*/
public void setStrikeThruText(int viewID) {
TextView view = (TextView) getView(viewID);
view.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
}
public int getPosition() {
return mPosition;
}
public GridView setData(int viewId) {
GridView gridView = getView(viewId);
return gridView;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/adapter/RecycleHolder.java
================================================
package com.senon.lib_common.adapter;
import android.app.Activity;
import android.graphics.Bitmap;
import android.support.v7.widget.RecyclerView;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.ForegroundColorSpan;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Checkable;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
public class RecycleHolder extends RecyclerView.ViewHolder {
/**
* 用于存储当前item当中的View
*/
private SparseArray mViews;
public RecycleHolder(View itemView) {
super(itemView);
mViews = new SparseArray();
}
public T findView(int ViewId) {
View view = mViews.get(ViewId);
//集合中没有,则从item当中获取,并存入集合当中
if (view == null) {
view = itemView.findViewById(ViewId);
mViews.put(ViewId, view);
}
return (T) view;
}
public RecycleHolder setOnClickListener(int viewId, View.OnClickListener listener) {
View view = findView(viewId);
view.setOnClickListener(listener);
return this;
}
public RecycleHolder setOnClickListener(int viewId,int viewId2 ,View.OnClickListener listener) {
View view = findView(viewId);
view.setOnClickListener(listener);
View view2 = findView(viewId2);
view2.setOnClickListener(listener);
return this;
}
public RecycleHolder setOnLongClickListener(int viewId, View.OnLongClickListener listener) {
View view = findView(viewId);
view.setOnLongClickListener(listener);
return this;
}
public RecycleHolder setOnLongClickListener(int viewId,int viewId2, View.OnLongClickListener listener) {
View view = findView(viewId);
view.setOnLongClickListener(listener);
View view2 = findView(viewId2);
view2.setOnLongClickListener(listener);
return this;
}
public RecycleHolder setText(int viewId, String text) {
TextView tv = findView(viewId);
tv.setText(text);
return this;
}
public RecycleHolder setText(int viewId, SpannableStringBuilder text) {
TextView tv = findView(viewId);
tv.setText(text);
return this;
}
public RecycleHolder setMaxLine(int viewId, int lineCount) {
TextView tv = findView(viewId);
tv.setMaxLines(lineCount);
return this;
}
public RecycleHolder setPadding(int viewId, int left, int top, int right, int bottom) {
View tv = findView(viewId);
tv.setPadding(left, top, right, bottom);
return this;
}
public RecycleHolder setAppendTextColor(int viewId, CharSequence str, int resColorId, int resDimen) {
TextView tv = findView(viewId);
SpannableString spannableString = new SpannableString(str);
spannableString.setSpan(new ForegroundColorSpan(tv.getContext().getResources().getColor(resColorId)), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new AbsoluteSizeSpan((int) tv.getContext().getResources().getDimension(resDimen)), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spannableString);
return this;
}
public RecycleHolder setSelected(int viewId, boolean selected) {
View tv = findView(viewId);
tv.setSelected(selected);
return this;
}
public RecycleHolder setEnabled(int viewId, boolean enabled) {
View tv = findView(viewId);
tv.setEnabled(enabled);
return this;
}
public RecycleHolder setEnabled_imgView(int viewId, boolean enabled) {
ImageView tv = findView(viewId);
tv.setEnabled(enabled);
return this;
}
public RecycleHolder setText(int viewId, int text) {
TextView tv = findView(viewId);
tv.setText(text);
return this;
}
public RecycleHolder setChecked(int viewId, boolean checked) {
Checkable view = findView(viewId);
view.setChecked(checked);
return this;
}
public RecycleHolder setTextColor(int viewId, int colorResId) {
TextView tv = findView(viewId);
tv.setTextColor(tv.getContext().getResources().getColor(colorResId));
return this;
}
public RecycleHolder setImageResource(int viewId, int ImageId) {
ImageView image = findView(viewId);
image.setImageResource(ImageId);
return this;
}
public RecycleHolder setLayoutParams(int viewId, ViewGroup.LayoutParams para) {
View view = findView(viewId);
view.setLayoutParams(para);
return this;
}
public RecycleHolder setImageBitmap(int viewId, Bitmap bitmap) {
ImageView image = findView(viewId);
image.setImageBitmap(bitmap);
return this;
}
public RecycleHolder setGlideImage(int viewId, String url,int placehodlerImg,Activity activity){
ImageView image = findView(viewId);
Glide.with(activity)
.load(url)
.error(placehodlerImg)
.placeholder(placehodlerImg)
.into(image);
return this;
}
public RecycleHolder setImageNet(int viewId, String url) {
ImageView image = findView(viewId);
//使用你所用的网络框架等
return this;
}
public RecycleHolder setBackgroundColor(int viewId, int color) {
View view = findView(viewId);
view.setBackgroundColor(color);
return this;
}
public RecycleHolder setBackgroundRes(int viewId, int backgroundRes) {
View view = findView(viewId);
view.setBackgroundResource(backgroundRes);
return this;
}
public RecycleHolder setVisible(int viewId, boolean visible) {
View image = findView(viewId);
image.setVisibility(visible ? View.VISIBLE : View.GONE);
//使用你所用的网络框架等
return this;
}
public RecycleHolder setVisible_invisible(int viewId, boolean visible) {
View image = findView(viewId);
image.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
//使用你所用的网络框架等
return this;
}
public RecycleHolder setProgesss(int viewId, int percent) {
ProgressBar progressBar = findView(viewId);
progressBar.setProgress(percent);
return this;
}
public boolean getVisible(int viewId) {
View view = findView(viewId);
return view.getVisibility() == View.VISIBLE;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/adapter/RecyclerAdapter.java
================================================
package com.senon.lib_common.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
public abstract class RecyclerAdapter extends RecyclerView.Adapter {
private Context mContext;
private List mDatas;
private int mLayoutId;
private LayoutInflater mInflater;
private OnItemClickListener onItemClickListener;
public RecyclerAdapter(Context mContext, List mDatas, int mLayoutId) {
this.mContext = mContext;
this.mDatas = mDatas;
this.mLayoutId = mLayoutId;
mInflater = LayoutInflater.from(mContext);
}
@Override
public RecycleHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new RecycleHolder(mInflater.inflate(mLayoutId, parent, false));
}
@Override
public void onBindViewHolder(final RecycleHolder holder, int position) {
convert(holder, mDatas.get(position), position);
if (onItemClickListener != null) {
//设置背景
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//注意,这里的position不要用上面参数中的position,会出现位置错乱\
onItemClickListener.OnItemClickListener(holder.itemView, holder.getLayoutPosition());
}
});
}
}
public abstract void convert(RecycleHolder holder, T data, int position);
@Override
public int getItemCount() {
return mDatas.size();
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public interface OnItemClickListener {
void OnItemClickListener(View view, int position);
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/api/BaseApi.java
================================================
package com.senon.lib_common.api;
import com.senon.lib_common.bean.Banner;
import com.senon.lib_common.bean.CollectionArticle;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.bean.KnowledgeSysArticle;
import com.senon.lib_common.bean.KnowledgeSystem;
import com.senon.lib_common.bean.Login;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.ProjectArticle;
import com.senon.lib_common.bean.WXarticle;
import com.senon.lib_common.bean.WXchapters;
import java.util.List;
import java.util.Map;
import io.reactivex.Observable;
import retrofit2.http.Field;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;
/**
* 网络请求接口
*/
public interface BaseApi {
//登录
@POST("user/login")
@FormUrlEncoded
Observable> login(@FieldMap Map map);
//登出
@GET("user/logout/json")
Observable logout();
//注册
@POST("user/register")
@FormUrlEncoded
Observable> register(@FieldMap Map map);
//首页banner
@GET("banner/json")
Observable>> banner();
//首页文章列表
@GET("article/list/{page}/json")
Observable> getHomeArticle(@Path("page") int page);
//首页最新项目
@GET("article/listproject/{page}/json")
Observable> getHomeProject(@Path("page") int page);
//项目列表数据
@GET("project/list/{page}/json")
Observable> getProjectList(@Path("page") int page, @Query("cid") int cid);
//体系数据
@GET("tree/json")
Observable>> getKnowledgeList();
//知识体系下的文章
@GET("article/list/{page}/json")
Observable> getKnowledgeArticle(@Path("page") int page, @Query("cid") int cid);
//获取公众号列表
@GET("wxarticle/chapters/json")
Observable>> getWXarticleChapters();
//查看某个公众号历史数据
@GET("wxarticle/list/{id}/{page}/json")
Observable> getWXarticleList(@Path("id") int id, @Path("page") int page);
//收藏站内文章
@POST("lg/collect/{id}/json")
Observable getCollect(@Path("id") int id);
//取消收藏-->文章列表
@POST("lg/uncollect_originId/{id}/json")
Observable getUncollectOriginId(@Path("id") int id);
//取消收藏-->我的收藏页面
@POST("lg/uncollect/{id}/json")
Observable getUncollect(@Path("id") int id,@Query("originId") int originId);
//收藏文章列表
@GET("lg/collect/list/{page}/json")
Observable> getCollectList(@Path("page") int page);
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/base/BaseActivity.java
================================================
package com.senon.lib_common.base;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.Window;
import com.alibaba.android.arouter.launcher.ARouter;
import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
/**
* 父类->基类->动态指定类型->泛型设计(通过泛型指定动态类型->由子类指定,父类只需要规定范围即可)
*/
public abstract class BaseActivity> extends RxAppCompatActivity {
//引用V层和P层
private P presenter;
private V view;
public P getPresenter(){
return presenter;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(getLayoutId());
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); // 禁止所有的activity横屏
ARouter.getInstance().inject(this);
if(presenter == null){
presenter = createPresenter();
}
if(view == null){
view = createView();
}
if(presenter != null && view != null){
presenter.attachView(view);
}
init();
}
//由子类指定具体类型
public abstract int getLayoutId();
public abstract P createPresenter();
public abstract V createView();
public abstract void init();
@Override
protected void onDestroy() {
super.onDestroy();
if(presenter != null){
presenter.detachView();
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/base/BaseAppDeletage.java
================================================
package com.senon.lib_common.base;
import android.app.Application;
import android.content.Context;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.DefaultRefreshFooterCreator;
import com.scwang.smartrefresh.layout.api.DefaultRefreshHeaderCreator;
import com.scwang.smartrefresh.layout.api.RefreshFooter;
import com.scwang.smartrefresh.layout.api.RefreshHeader;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.footer.ClassicsFooter;
import com.scwang.smartrefresh.layout.header.ClassicsHeader;
import com.senon.lib_common.R;
import com.senon.lib_common.net.cookies.PersistentCookieStore;
import com.senon.lib_common.service.InitializeService;
import com.senon.lib_common.utils.ConstantUtils;
import com.senon.lib_common.utils.LogUtils;
import com.senon.lib_common.utils.PreferenceTool;
import com.senon.lib_common.utils.ToastUtil;
import me.jessyan.autosize.AutoSizeConfig;
import me.jessyan.autosize.unit.Subunits;
public class BaseAppDeletage {
private Application mApplication;
//static 代码段可以防止内存泄露
static {
//设置全局的Header构建器
SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
@Override
public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
// 指定为经典Header,默认是 贝塞尔雷达Header
return new ClassicsHeader(context);
}
});
//设置全局的Footer构建器
SmartRefreshLayout.setDefaultRefreshFooterCreator(new DefaultRefreshFooterCreator() {
@Override
public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) {
//指定为经典Footer,默认是 BallPulseFooter
return new ClassicsFooter(context).setDrawableSize(20);
}
});
}
public BaseAppDeletage(Application application) {
mApplication = application;
}
public void onCreate() {
ConstantUtils.init(mApplication); //全局Utils
LogUtils.setLogEnable(ConstantUtils.isAppDebug()); //Log日志
PreferenceTool.init(mApplication); //Preference参数
PersistentCookieStore.init(mApplication); //Cookies持久化Preference参数
ToastUtil.init(mApplication); //吐司初始化
initAutoSizeUnits(); //配置全局 布局适配单位mm
InitializeService.start(mApplication); //初始化服务Service
}
private void initAutoSizeUnits() {
AutoSizeConfig.getInstance().getUnitsManager()
//支持dp适配 默认true
.setSupportDP(false)
//支持sp适配 默认true
.setSupportSP(false)
.setSupportSubunits(Subunits.MM);
AutoSizeConfig.getInstance()
//按照宽度适配 默认true
.setBaseOnWidth(true)
//是否让框架支持自定义 Fragment 的适配参数, 由于这个需求是比较少见的, 所以须要使用者手动开启
//如果没有这个需求建议不开启
.setCustomFragment(true);
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/base/BaseApplication.java
================================================
package com.senon.lib_common.base;
import android.app.Application;
/**
* 要想使用BaseApplication,必须在组件中实现自己的Application,并且继承BaseApplication;
* 组件模块中实现的Application必须在debug包中的AndroidManifest.xml中注册,否则无法使用;
* 组件模块的Application需置于java/debug文件夹中,不得放于主代码;
* 组件模块中获取Context的方法必须为:ConstantUtils.getAPPContext(),不允许其他写法;
*/
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
BaseAppDeletage baseAppDeletage = new BaseAppDeletage(this);
baseAppDeletage.onCreate();
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/base/BaseFragment.java
================================================
package com.senon.lib_common.base;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.trello.rxlifecycle2.components.support.RxFragment;
/**
* 父类->基类->动态指定类型->泛型设计(通过泛型指定动态类型->由子类指定,父类只需要规定范围即可)
*/
public abstract class BaseFragment> extends RxFragment {
//引用V层和P层
private P presenter;
private V view;
public Context mContext;
public P getPresenter() {
return presenter;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(getLayoutId(), container, false);
mContext = getActivity();
if (presenter == null) {
presenter = createPresenter();
}
if (this.view == null) {
this.view = createView();
}
if (presenter != null && view != null) {
presenter.attachView(this.view);
}
init();
return view;
}
//由子类指定具体类型
public abstract int getLayoutId();
public abstract P createPresenter();
public abstract V createView();
public abstract void init();
@Override
public void onDestroyView() {
super.onDestroyView();
if (presenter != null) {
presenter.detachView();
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/base/BaseLazyFragment.java
================================================
package com.senon.lib_common.base;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.senon.lib_common.utils.LogUtils;
import com.trello.rxlifecycle2.components.support.RxFragment;
/**
* https://juejin.im/post/5adcb0e36fb9a07aa7673fbc
* BaseLazyFragment 单fragment懒加载
*
* * 生命周期执行的方法 如下:
* 第一次生成页面-->可见
* setUserVisibleHint: ----->false
* setUserVisibleHint: ----->true
* onCreateView: -----> onCreateView
* onStart: -----> onStart
* onFragmentFirst: 首次可见
* onFragmentFirst: -----> 子fragment进行初始化操作
* onResume: -----> onResume
*
* 可见-->第一次隐藏:
* onPause: -----> onPause
* onFragmentInVisible: 不可见
*
* 未销毁且不可见-->重新可见:
* onStart: -----> onStart
* onFragmentVisble: 可见
* onFragmentVisble: -----> 子fragment每次可见时的操作
* onResume: -----> onResume
*
* 可见-->销毁:
* onPause: -----> onPause
* onFragmentInVisible: 不可见
* onDestroyView: -----> onDestroyView
*
* 我们可以更具以上生命周期来操作不同的业务逻辑,
* 请务必运行此module demo,观看打印日志来自定义逻辑。
*/
public abstract class BaseLazyFragment> extends RxFragment {
//引用V层和P层
private P presenter;
private V view;
public Context mContext;
private View rootView;
private boolean mIsFirstVisible = true;/*当前Fragment是否首次可见,默认是首次可见**/
private boolean isViewCreated = false;/*当前Fragment的View是否已经创建**/
private boolean currentVisibleState = false;/*当前Fragment的可见状态,一种当前可见,一种当前不可见**/
public P getPresenter() {
return presenter;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
LogUtils.e("-----> onCreateView");
if(rootView == null){
rootView = inflater.inflate(getLayoutId(), container, false);
mContext = getActivity();
if (presenter == null) {
presenter = createPresenter();
}
if (this.view == null) {
this.view = createView();
}
if (presenter != null && view != null) {
presenter.attachView(this.view);
}
init(rootView);
}
isViewCreated=true;//在onCreateView执行完毕,将isViewCreated改为true;
return rootView;
}
//由子类指定具体类型
public abstract int getLayoutId();
public abstract P createPresenter();
public abstract V createView();
public abstract void init(View rootView);
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
LogUtils.e("----->"+isVisibleToUser);
if (isViewCreated) {
//Fragment可见且状态不是可见(从一个Fragment切换到另外一个Fragment,后一个设置状态为可见)
if (isVisibleToUser && !currentVisibleState) {
disPatchFragment(true);
} else if (!isVisibleToUser && currentVisibleState) {
//Fragment不可见且状态是可见(从一个Fragment切换到另外一个Fragment,前一个更改状态为不可见)
disPatchFragment(false);
}
}
}
@Override
public void onStart() {
super.onStart();
LogUtils.e("-----> onStart");
//isHidden()是Fragment是否处于隐藏状态和isVisible()有区别
//getUserVisibleHint(),Fragement是否可见
if(!isHidden()&& getUserVisibleHint()){//如果Fragment没有隐藏且可见
//执行分发的方法,三种结果对应自Fragment的三个回调,对应的操作,Fragment首次加载,可见,不可见
disPatchFragment(true);
}
}
@Override
public void onResume() {
super.onResume();
LogUtils.e("-----> onResume");
if(!mIsFirstVisible){
//表示点击home键又返回操作,设置可见状态为ture
if(!isHidden()&& !getUserVisibleHint() && currentVisibleState){
disPatchFragment(true);
}
}
}
@Override
public void onPause() {
super.onPause();
LogUtils.e("-----> onPause");
//表示点击home键,原来可见的Fragment要走该方法,更改Fragment的状态为不可见
if(!isHidden()&& getUserVisibleHint()){
disPatchFragment(false);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
LogUtils.e("-----> onDestroyView");
//当 View 被销毁的时候我们需要重新设置 isViewCreated mIsFirstVisible 的状态
isViewCreated = false;
mIsFirstVisible = true;
if (presenter != null) {
presenter.detachView();
}
}
/**
* @param visible Fragment当前是否可见,然后调用相关方法
*/
public void disPatchFragment(boolean visible){
currentVisibleState=visible;
if(visible){//Fragment可见
if(mIsFirstVisible){//可见又是第一次
mIsFirstVisible=false;//改变首次可见的状态
onFragmentFirst();
}else{//可见但不是第一次
onFragmentVisble();
}
}else {//不可见
onFragmentInVisible();
}
}
//Fragemnet首次可见的方法
public void onFragmentFirst(){
LogUtils.e("首次可见");
}
//Fragemnet可见的方法
public void onFragmentVisble(){//子Fragment调用次方法,执行可见操作
LogUtils.e("可见");
}
//Fragemnet不可见的方法
public void onFragmentInVisible(){
LogUtils.e("不可见");
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/base/BaseNestingLazyFragment.java
================================================
package com.senon.lib_common.base;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.senon.lib_common.utils.LogUtils;
import com.trello.rxlifecycle2.components.support.RxFragment;
import java.util.List;
/**
* https://juejin.im/post/5adcb0e36fb9a07aa7673fbc
*
* BaseNestingLazyFragment fragment嵌套fragment的懒加载父类
*/
public abstract class BaseNestingLazyFragment> extends RxFragment {
//引用V层和P层
private P presenter;
private V view;
public Context mContext;
private View rootView;
private boolean mIsFirstVisible = true;/*当前Fragment是否首次可见,默认是首次可见**/
private boolean isViewCreated = false;/*当前Fragment的View是否已经创建**/
private boolean currentVisibleState = false;/*当前Fragment的可见状态,一种当前可见,一种当前不可见**/
public P getPresenter() {
return presenter;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
LogUtils.e("-----> onCreateView");
if (rootView == null) {
rootView = inflater.inflate(getLayoutId(), container, false);
mContext = getActivity();
if (presenter == null) {
presenter = createPresenter();
}
if (this.view == null) {
this.view = createView();
}
if (presenter != null && view != null) {
presenter.attachView(this.view);
}
init(rootView);
}
isViewCreated = true;//在onCreateView执行完毕,将isViewCreated改为true;
return rootView;
}
//由子类指定具体类型
public abstract int getLayoutId();
public abstract P createPresenter();
public abstract V createView();
public abstract void init(View rootView);
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
LogUtils.e("----->" + isVisibleToUser);
if (isViewCreated) {
//Fragment可见且状态不是可见(从一个Fragment切换到另外一个Fragment,后一个设置状态为可见)
if (isVisibleToUser && !currentVisibleState) {
disPatchFragment(true);
} else if (!isVisibleToUser && currentVisibleState) {
//Fragment不可见且状态是可见(从一个Fragment切换到另外一个Fragment,前一个更改状态为不可见)
disPatchFragment(false);
}
}
}
@Override
public void onStart() {
super.onStart();
LogUtils.e("-----> onStart");
//isHidden()是Fragment是否处于隐藏状态和isVisible()有区别
//getUserVisibleHint(),Fragement是否可见
if (!isHidden() && getUserVisibleHint()) {//如果Fragment没有隐藏且可见
//执行分发的方法,三种结果对应自Fragment的三个回调,对应的操作,Fragment首次加载,可见,不可见
disPatchFragment(true);
}
}
@Override
public void onResume() {
super.onResume();
LogUtils.e("-----> onResume");
if (!mIsFirstVisible) {
//表示点击home键又返回操作,设置可见状态为ture
if (!isHidden() && !getUserVisibleHint() && currentVisibleState) {
disPatchFragment(true);
}
}
}
@Override
public void onPause() {
super.onPause();
LogUtils.e("-----> onPause");
//表示点击home键,原来可见的Fragment要走该方法,更改Fragment的状态为不可见
if (!isHidden() && getUserVisibleHint()) {
disPatchFragment(false);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
LogUtils.e("-----> onDestroyView");
//当 View 被销毁的时候我们需要重新设置 isViewCreated mIsFirstVisible 的状态
isViewCreated = false;
mIsFirstVisible = true;
if (presenter != null) {
presenter.detachView();
}
}
/**
* @param visible Fragment当前是否可见,然后调用相关方法
*/
public void disPatchFragment(boolean visible) {
String aa = getClass().getSimpleName();
//如果父Fragment不可见,则不向下分发给子Fragment
if (visible && isParentFragmentVsible()) return;
// 如果当前的 Fragment 要分发的状态与 currentVisibleState 相同(都为false)我们就没有必要去做分发了。
if (currentVisibleState == visible) return;
currentVisibleState = visible;
if (visible) {//Fragment可见
if (mIsFirstVisible) {//可见又是第一次
mIsFirstVisible = false;//改变首次可见的状态
onFragmentFirst();
}else {//可见但不是第一次
onFragmentVisble();
}
//可见状态的时候内层 fragment 生命周期晚于外层 所以在 onFragmentResume 后分发
dispatchChildFragmentVisibleState(true);
} else {//不可见
onFragmentInVisible();
dispatchChildFragmentVisibleState(false);
}
}
/**
* 重新分发给子Fragment
*
* @param visible
*/
private void dispatchChildFragmentVisibleState(boolean visible) {
FragmentManager childFragmentManager = getChildFragmentManager();
@SuppressLint("RestrictedApi") List fragments = childFragmentManager.getFragments();
if (fragments != null) {
if (!fragments.isEmpty()) {
for (Fragment child : fragments) {
if (child instanceof BaseNestingLazyFragment && !child.isHidden() && child.getUserVisibleHint()) {
((BaseNestingLazyFragment) child).disPatchFragment(visible);
}
}
}
}
}
//Fragemnet首次可见的方法
public void onFragmentFirst() {
LogUtils.e("首次可见");
}
//Fragemnet可见的方法
public void onFragmentVisble() {//子Fragment调用次方法,执行可见操作
LogUtils.e("可见");
}
//Fragemnet不可见的方法
public void onFragmentInVisible() {
LogUtils.e("不可见");
}
/**
* 判断多层嵌套的父Fragment是否显示
*/
private boolean isParentFragmentVsible() {
BaseNestingLazyFragment fragment = (BaseNestingLazyFragment) getParentFragment();
return fragment != null && !fragment.getCurrentVisibleState();
}
private boolean getCurrentVisibleState() {
return currentVisibleState;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/base/BasePresenter.java
================================================
package com.senon.lib_common.base;
/**
* BasePresenter
*/
public abstract class BasePresenter{
private V mView;
public V getView(){
return mView;
}
public void attachView(V v){
mView = v;
}
public void detachView(){
mView = null;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/base/BaseResponse.java
================================================
package com.senon.lib_common.base;
import com.google.gson.annotations.SerializedName;
/**
* BaseResponse
*/
public class BaseResponse {
@SerializedName("errorMsg")
private String msg;
@SerializedName("errorCode")
private int code;
private T data;
public String getMsg() {
return msg;
}
public int getCode() {
return code;
}
public T getData() {
return data;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/base/BaseViewImp.java
================================================
package com.senon.lib_common.base;
/**
* View 父类接口
*/
public interface BaseViewImp {
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/bean/Banner.java
================================================
package com.senon.lib_common.bean;
/**
* 首页Banner
*/
public class Banner {
/**
* desc : 一起来做个App吧
* id : 10
* imagePath : http://www.wanandroid.com/blogimgs/50c115c2-cf6c-4802-aa7b-a4334de444cd.png
* isVisible : 1
* order : 3
* title : 一起来做个App吧
* type : 0
* url : http://www.wanandroid.com/blog/show/2
*/
private String desc;
private int id;
private String imagePath;
private int isVisible;
private int order;
private String title;
private int type;
private String url;
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getImagePath() {
return imagePath;
}
public void setImagePath(String imagePath) {
this.imagePath = imagePath;
}
public int getIsVisible() {
return isVisible;
}
public void setIsVisible(int isVisible) {
this.isVisible = isVisible;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/bean/CollectionArticle.java
================================================
package com.senon.lib_common.bean;
import java.util.List;
/**
* 收藏列表文章
*/
public class CollectionArticle {
/**
* curPage : 1
* datas : [{"author":"xiangcman","chapterId":314,"chapterName":"RV列表动效","courseId":13,"desc":"快速利用RecyclerView的LayoutManager搭建流式布局 ","envelopePic":"http://www.wanandroid.com/blogimgs/36badc79-fb1e-460e-8368-6898c16ba723.png","id":9977,"link":"http://www.wanandroid.com/blog/show/2112","niceDate":"2018-05-02","origin":"","originId":2829,"publishTime":1525237333000,"title":"快速利用RecyclerView的LayoutManager搭建流式布局 ","userId":1864,"visible":0,"zan":0}]
* offset : 0
* over : true
* pageCount : 1
* size : 20
* total : 5
*/
private int curPage;
private int offset;
private boolean over;
private int pageCount;
private int size;
private int total;
private List datas;
public int getCurPage() {
return curPage;
}
public void setCurPage(int curPage) {
this.curPage = curPage;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public boolean isOver() {
return over;
}
public void setOver(boolean over) {
this.over = over;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List getDatas() {
return datas;
}
public void setDatas(List datas) {
this.datas = datas;
}
public static class DatasBean {
/**
* author : xiangcman
* chapterId : 314
* chapterName : RV列表动效
* courseId : 13
* desc : 快速利用RecyclerView的LayoutManager搭建流式布局
* envelopePic : http://www.wanandroid.com/blogimgs/36badc79-fb1e-460e-8368-6898c16ba723.png
* id : 9977
* link : http://www.wanandroid.com/blog/show/2112
* niceDate : 2018-05-02
* origin :
* originId : 2829
* publishTime : 1525237333000
* title : 快速利用RecyclerView的LayoutManager搭建流式布局
* userId : 1864
* visible : 0
* zan : 0
*/
private String author;
private int chapterId;
private String chapterName;
private int courseId;
private String desc;
private String envelopePic;
private int id;
private String link;
private String niceDate;
private String origin;
private int originId;
private long publishTime;
private String title;
private int userId;
private int visible;
private int zan;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getChapterId() {
return chapterId;
}
public void setChapterId(int chapterId) {
this.chapterId = chapterId;
}
public String getChapterName() {
return chapterName;
}
public void setChapterName(String chapterName) {
this.chapterName = chapterName;
}
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getEnvelopePic() {
return envelopePic;
}
public void setEnvelopePic(String envelopePic) {
this.envelopePic = envelopePic;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getNiceDate() {
return niceDate;
}
public void setNiceDate(String niceDate) {
this.niceDate = niceDate;
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public int getOriginId() {
return originId;
}
public void setOriginId(int originId) {
this.originId = originId;
}
public long getPublishTime() {
return publishTime;
}
public void setPublishTime(long publishTime) {
this.publishTime = publishTime;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getVisible() {
return visible;
}
public void setVisible(int visible) {
this.visible = visible;
}
public int getZan() {
return zan;
}
public void setZan(int zan) {
this.zan = zan;
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/bean/HomeArticle.java
================================================
package com.senon.lib_common.bean;
import java.util.List;
/**
* 首页文章
*/
public class HomeArticle {
/**
* curPage : 1
* datas : [{"apkLink":"","author":"tinycoder","chapterId":191,"chapterName":"数据采集与埋点",
* "collect":false,"courseId":13,"desc":"","envelopePic":"","fresh":true,"id":7656,
* "link":"https://juejin.im/post/5c0e4117518825369c566f07","niceDate":"15小时前","origin":"",
* "projectLink":"","publishTime":1544631512000,"superChapterId":79,"superChapterName":"热门专题",
* "tags":[],"title":"无埋点统计SDK实践","type":0,"userId":-1,"visible":1,"zan":0}]
* offset : 0
* over : false
* pageCount : 290
* size : 20
* total : 5798
*/
private int curPage;
private int offset;
private boolean over;
private int pageCount;
private int size;
private int total;
private List datas;
public int getCurPage() {
return curPage;
}
public void setCurPage(int curPage) {
this.curPage = curPage;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public boolean isOver() {
return over;
}
public void setOver(boolean over) {
this.over = over;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List getDatas() {
return datas;
}
public void setDatas(List datas) {
this.datas = datas;
}
public static class DatasBean {
/**
* apkLink :
* author : tinycoder
* chapterId : 191
* chapterName : 数据采集与埋点
* collect : false
* courseId : 13
* desc :
* envelopePic :
* fresh : true
* id : 7656
* link : https://juejin.im/post/5c0e4117518825369c566f07
* niceDate : 15小时前
* origin :
* projectLink :
* publishTime : 1544631512000
* superChapterId : 79
* superChapterName : 热门专题
* tags : []
* title : 无埋点统计SDK实践
* type : 0
* userId : -1
* visible : 1
* zan : 0
*/
private String apkLink;
private String author;
private int chapterId;
private String chapterName;
private boolean collect;
private int courseId;
private String desc;
private String envelopePic;
private boolean fresh;
private int id;
private String link;
private String niceDate;
private String origin;
private String projectLink;
private long publishTime;
private int superChapterId;
private String superChapterName;
private String title;
private int type;
private int userId;
private int visible;
private int zan;
private List> tags;
public String getApkLink() {
return apkLink;
}
public void setApkLink(String apkLink) {
this.apkLink = apkLink;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getChapterId() {
return chapterId;
}
public void setChapterId(int chapterId) {
this.chapterId = chapterId;
}
public String getChapterName() {
return chapterName;
}
public void setChapterName(String chapterName) {
this.chapterName = chapterName;
}
public boolean isCollect() {
return collect;
}
public void setCollect(boolean collect) {
this.collect = collect;
}
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getEnvelopePic() {
return envelopePic;
}
public void setEnvelopePic(String envelopePic) {
this.envelopePic = envelopePic;
}
public boolean isFresh() {
return fresh;
}
public void setFresh(boolean fresh) {
this.fresh = fresh;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getNiceDate() {
return niceDate;
}
public void setNiceDate(String niceDate) {
this.niceDate = niceDate;
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public String getProjectLink() {
return projectLink;
}
public void setProjectLink(String projectLink) {
this.projectLink = projectLink;
}
public long getPublishTime() {
return publishTime;
}
public void setPublishTime(long publishTime) {
this.publishTime = publishTime;
}
public int getSuperChapterId() {
return superChapterId;
}
public void setSuperChapterId(int superChapterId) {
this.superChapterId = superChapterId;
}
public String getSuperChapterName() {
return superChapterName;
}
public void setSuperChapterName(String superChapterName) {
this.superChapterName = superChapterName;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getVisible() {
return visible;
}
public void setVisible(int visible) {
this.visible = visible;
}
public int getZan() {
return zan;
}
public void setZan(int zan) {
this.zan = zan;
}
public List> getTags() {
return tags;
}
public void setTags(List> tags) {
this.tags = tags;
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/bean/KnowledgeSysArticle.java
================================================
package com.senon.lib_common.bean;
import java.util.List;
/**
* 知识体系文章
*/
public class KnowledgeSysArticle {
/**
* curPage : 1
* datas : [{"apkLink":"","author":"littledavid-tech","chapterId":294,"chapterName":"完整项目","collect":false,"courseId":13,"desc":"这个算是对Android学习总结,MVP架构+好多轮子","envelopePic":"http://wanandroid.com/blogimgs/9be242c9-e53e-4a54-9f49-d69b04b463b9.png","fresh":false,"id":7641,"link":"http://www.wanandroid.com/blog/show/2449","niceDate":"2天前","origin":"","projectLink":"https://github.com/littledavid-tech/WanAndroidApp","publishTime":1544499146000,"superChapterId":294,"superChapterName":"开源项目主Tab","tags":[{"name":"项目","url":"/project/list/1?cid=294"}],"title":"我的涂鸦之作WanAndroid第三方客户端","type":0,"userId":-1,"visible":1,"zan":0}]
* offset : 0
* over : false
* pageCount : 7
* size : 15
* total : 102
*/
private int curPage;
private int offset;
private boolean over;
private int pageCount;
private int size;
private int total;
private List datas;
public int getCurPage() {
return curPage;
}
public void setCurPage(int curPage) {
this.curPage = curPage;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public boolean isOver() {
return over;
}
public void setOver(boolean over) {
this.over = over;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List getDatas() {
return datas;
}
public void setDatas(List datas) {
this.datas = datas;
}
public static class DatasBean {
/**
* apkLink :
* author : littledavid-tech
* chapterId : 294
* chapterName : 完整项目
* collect : false
* courseId : 13
* desc : 这个算是对Android学习总结,MVP架构+好多轮子
* envelopePic : http://wanandroid.com/blogimgs/9be242c9-e53e-4a54-9f49-d69b04b463b9.png
* fresh : false
* id : 7641
* link : http://www.wanandroid.com/blog/show/2449
* niceDate : 2天前
* origin :
* projectLink : https://github.com/littledavid-tech/WanAndroidApp
* publishTime : 1544499146000
* superChapterId : 294
* superChapterName : 开源项目主Tab
* tags : [{"name":"项目","url":"/project/list/1?cid=294"}]
* title : 我的涂鸦之作WanAndroid第三方客户端
* type : 0
* userId : -1
* visible : 1
* zan : 0
*/
private String apkLink;
private String author;
private int chapterId;
private String chapterName;
private boolean collect;
private int courseId;
private String desc;
private String envelopePic;
private boolean fresh;
private int id;
private String link;
private String niceDate;
private String origin;
private String projectLink;
private long publishTime;
private int superChapterId;
private String superChapterName;
private String title;
private int type;
private int userId;
private int visible;
private int zan;
private List tags;
public String getApkLink() {
return apkLink;
}
public void setApkLink(String apkLink) {
this.apkLink = apkLink;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getChapterId() {
return chapterId;
}
public void setChapterId(int chapterId) {
this.chapterId = chapterId;
}
public String getChapterName() {
return chapterName;
}
public void setChapterName(String chapterName) {
this.chapterName = chapterName;
}
public boolean isCollect() {
return collect;
}
public void setCollect(boolean collect) {
this.collect = collect;
}
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getEnvelopePic() {
return envelopePic;
}
public void setEnvelopePic(String envelopePic) {
this.envelopePic = envelopePic;
}
public boolean isFresh() {
return fresh;
}
public void setFresh(boolean fresh) {
this.fresh = fresh;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getNiceDate() {
return niceDate;
}
public void setNiceDate(String niceDate) {
this.niceDate = niceDate;
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public String getProjectLink() {
return projectLink;
}
public void setProjectLink(String projectLink) {
this.projectLink = projectLink;
}
public long getPublishTime() {
return publishTime;
}
public void setPublishTime(long publishTime) {
this.publishTime = publishTime;
}
public int getSuperChapterId() {
return superChapterId;
}
public void setSuperChapterId(int superChapterId) {
this.superChapterId = superChapterId;
}
public String getSuperChapterName() {
return superChapterName;
}
public void setSuperChapterName(String superChapterName) {
this.superChapterName = superChapterName;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getVisible() {
return visible;
}
public void setVisible(int visible) {
this.visible = visible;
}
public int getZan() {
return zan;
}
public void setZan(int zan) {
this.zan = zan;
}
public List getTags() {
return tags;
}
public void setTags(List tags) {
this.tags = tags;
}
public static class TagsBean {
/**
* name : 项目
* url : /project/list/1?cid=294
*/
private String name;
private String url;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/bean/KnowledgeSystem.java
================================================
package com.senon.lib_common.bean;
import java.util.List;
/**
* 知识体系
*/
public class KnowledgeSystem {
/**
* children : [{"children":[],"courseId":13,"id":60,"name":"Android Studio相关","order":1000,"parentChapterId":150,"userControlSetTop":false,"visible":1},{"children":[],"courseId":13,"id":169,"name":"gradle","order":1001,"parentChapterId":150,"userControlSetTop":false,"visible":1},{"children":[],"courseId":13,"id":269,"name":"官方发布","order":1002,"parentChapterId":150,"userControlSetTop":false,"visible":1}]
* courseId : 13
* id : 150
* name : 开发环境
* order : 1
* parentChapterId : 0
* userControlSetTop : false
* visible : 1
*/
private int courseId;
private int id;
private String name;
private int order;
private int parentChapterId;
private boolean userControlSetTop;
private int visible;
private List children;
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public int getParentChapterId() {
return parentChapterId;
}
public void setParentChapterId(int parentChapterId) {
this.parentChapterId = parentChapterId;
}
public boolean isUserControlSetTop() {
return userControlSetTop;
}
public void setUserControlSetTop(boolean userControlSetTop) {
this.userControlSetTop = userControlSetTop;
}
public int getVisible() {
return visible;
}
public void setVisible(int visible) {
this.visible = visible;
}
public List getChildren() {
return children;
}
public void setChildren(List children) {
this.children = children;
}
public static class ChildrenBean {
/**
* children : []
* courseId : 13
* id : 60
* name : Android Studio相关
* order : 1000
* parentChapterId : 150
* userControlSetTop : false
* visible : 1
*/
private int courseId;
private int id;
private String name;
private int order;
private int parentChapterId;
private boolean userControlSetTop;
private int visible;
private List> children;
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public int getParentChapterId() {
return parentChapterId;
}
public void setParentChapterId(int parentChapterId) {
this.parentChapterId = parentChapterId;
}
public boolean isUserControlSetTop() {
return userControlSetTop;
}
public void setUserControlSetTop(boolean userControlSetTop) {
this.userControlSetTop = userControlSetTop;
}
public int getVisible() {
return visible;
}
public void setVisible(int visible) {
this.visible = visible;
}
public List> getChildren() {
return children;
}
public void setChildren(List> children) {
this.children = children;
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/bean/Login.java
================================================
package com.senon.lib_common.bean;
import java.util.List;
/**
* 登录--实体
*/
public class Login {
/**
* chapterTops : []
* collectIds : [2683,2880,2875,2868,2831,2829,2807]
* email :
* icon :
* id : 1864
* password :
* token :
* type : 0
* username : senonwx
*/
private String email;
private String icon;
private int id;
private String password;
private String token;
private int type;
private String username;
private List> chapterTops;
private List collectIds;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public List> getChapterTops() {
return chapterTops;
}
public void setChapterTops(List> chapterTops) {
this.chapterTops = chapterTops;
}
public List getCollectIds() {
return collectIds;
}
public void setCollectIds(List collectIds) {
this.collectIds = collectIds;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/bean/ProjectArticle.java
================================================
package com.senon.lib_common.bean;
import java.util.List;
/**
* 项目列表
*/
public class ProjectArticle {
/**
* curPage : 1
* datas : [{"apkLink":"","author":"littledavid-tech","chapterId":294,"chapterName":"完整项目","collect":false,"courseId":13,"desc":"这个算是对Android学习总结,MVP架构+好多轮子","envelopePic":"http://wanandroid.com/blogimgs/9be242c9-e53e-4a54-9f49-d69b04b463b9.png","fresh":false,"id":7641,"link":"http://www.wanandroid.com/blog/show/2449","niceDate":"2天前","origin":"","projectLink":"https://github.com/littledavid-tech/WanAndroidApp","publishTime":1544499146000,"superChapterId":294,"superChapterName":"开源项目主Tab","tags":[{"name":"项目","url":"/project/list/1?cid=294"}],"title":"我的涂鸦之作WanAndroid第三方客户端","type":0,"userId":-1,"visible":1,"zan":0}]
* offset : 0
* over : false
* pageCount : 7
* size : 15
* total : 102
*/
private int curPage;
private int offset;
private boolean over;
private int pageCount;
private int size;
private int total;
private List datas;
public int getCurPage() {
return curPage;
}
public void setCurPage(int curPage) {
this.curPage = curPage;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public boolean isOver() {
return over;
}
public void setOver(boolean over) {
this.over = over;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List getDatas() {
return datas;
}
public void setDatas(List datas) {
this.datas = datas;
}
public static class DatasBean {
/**
* apkLink :
* author : littledavid-tech
* chapterId : 294
* chapterName : 完整项目
* collect : false
* courseId : 13
* desc : 这个算是对Android学习总结,MVP架构+好多轮子
* envelopePic : http://wanandroid.com/blogimgs/9be242c9-e53e-4a54-9f49-d69b04b463b9.png
* fresh : false
* id : 7641
* link : http://www.wanandroid.com/blog/show/2449
* niceDate : 2天前
* origin :
* projectLink : https://github.com/littledavid-tech/WanAndroidApp
* publishTime : 1544499146000
* superChapterId : 294
* superChapterName : 开源项目主Tab
* tags : [{"name":"项目","url":"/project/list/1?cid=294"}]
* title : 我的涂鸦之作WanAndroid第三方客户端
* type : 0
* userId : -1
* visible : 1
* zan : 0
*/
private String apkLink;
private String author;
private int chapterId;
private String chapterName;
private boolean collect;
private int courseId;
private String desc;
private String envelopePic;
private boolean fresh;
private int id;
private String link;
private String niceDate;
private String origin;
private String projectLink;
private long publishTime;
private int superChapterId;
private String superChapterName;
private String title;
private int type;
private int userId;
private int visible;
private int zan;
private List tags;
public String getApkLink() {
return apkLink;
}
public void setApkLink(String apkLink) {
this.apkLink = apkLink;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getChapterId() {
return chapterId;
}
public void setChapterId(int chapterId) {
this.chapterId = chapterId;
}
public String getChapterName() {
return chapterName;
}
public void setChapterName(String chapterName) {
this.chapterName = chapterName;
}
public boolean isCollect() {
return collect;
}
public void setCollect(boolean collect) {
this.collect = collect;
}
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getEnvelopePic() {
return envelopePic;
}
public void setEnvelopePic(String envelopePic) {
this.envelopePic = envelopePic;
}
public boolean isFresh() {
return fresh;
}
public void setFresh(boolean fresh) {
this.fresh = fresh;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getNiceDate() {
return niceDate;
}
public void setNiceDate(String niceDate) {
this.niceDate = niceDate;
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public String getProjectLink() {
return projectLink;
}
public void setProjectLink(String projectLink) {
this.projectLink = projectLink;
}
public long getPublishTime() {
return publishTime;
}
public void setPublishTime(long publishTime) {
this.publishTime = publishTime;
}
public int getSuperChapterId() {
return superChapterId;
}
public void setSuperChapterId(int superChapterId) {
this.superChapterId = superChapterId;
}
public String getSuperChapterName() {
return superChapterName;
}
public void setSuperChapterName(String superChapterName) {
this.superChapterName = superChapterName;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getVisible() {
return visible;
}
public void setVisible(int visible) {
this.visible = visible;
}
public int getZan() {
return zan;
}
public void setZan(int zan) {
this.zan = zan;
}
public List getTags() {
return tags;
}
public void setTags(List tags) {
this.tags = tags;
}
public static class TagsBean {
/**
* name : 项目
* url : /project/list/1?cid=294
*/
private String name;
private String url;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/bean/WXarticle.java
================================================
package com.senon.lib_common.bean;
import java.util.List;
/**
* 公众号文章
*/
public class WXarticle {
/**
* curPage : 2
* datas : [{"apkLink":"","author":"鸿洋","chapterId":408,"chapterName":"鸿洋","collect":false,"courseId":13,"desc":"","envelopePic":"","fresh":false,"id":7503,"link":"https://mp.weixin.qq.com/s/m1MhhUYi71OO9eZCU3xEwA","niceDate":"2018-11-12","origin":"","projectLink":"","publishTime":1541952000000,"superChapterId":408,"superChapterName":"公众号","tags":[{"name":"公众号","url":"/wxarticle/list/408/1"}],"title":"Toast 不显示了?","type":0,"userId":-1,"visible":1,"zan":0}]
* offset : 20
* over : false
* pageCount : 33
* size : 20
* total : 641
*/
private int curPage;
private int offset;
private boolean over;
private int pageCount;
private int size;
private int total;
private List datas;
public int getCurPage() {
return curPage;
}
public void setCurPage(int curPage) {
this.curPage = curPage;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public boolean isOver() {
return over;
}
public void setOver(boolean over) {
this.over = over;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List getDatas() {
return datas;
}
public void setDatas(List datas) {
this.datas = datas;
}
public static class DatasBean {
/**
* apkLink :
* author : 鸿洋
* chapterId : 408
* chapterName : 鸿洋
* collect : false
* courseId : 13
* desc :
* envelopePic :
* fresh : false
* id : 7503
* link : https://mp.weixin.qq.com/s/m1MhhUYi71OO9eZCU3xEwA
* niceDate : 2018-11-12
* origin :
* projectLink :
* publishTime : 1541952000000
* superChapterId : 408
* superChapterName : 公众号
* tags : [{"name":"公众号","url":"/wxarticle/list/408/1"}]
* title : Toast 不显示了?
* type : 0
* userId : -1
* visible : 1
* zan : 0
*/
private String apkLink;
private String author;
private int chapterId;
private String chapterName;
private boolean collect;
private int courseId;
private String desc;
private String envelopePic;
private boolean fresh;
private int id;
private String link;
private String niceDate;
private String origin;
private String projectLink;
private long publishTime;
private int superChapterId;
private String superChapterName;
private String title;
private int type;
private int userId;
private int visible;
private int zan;
private List tags;
public String getApkLink() {
return apkLink;
}
public void setApkLink(String apkLink) {
this.apkLink = apkLink;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getChapterId() {
return chapterId;
}
public void setChapterId(int chapterId) {
this.chapterId = chapterId;
}
public String getChapterName() {
return chapterName;
}
public void setChapterName(String chapterName) {
this.chapterName = chapterName;
}
public boolean isCollect() {
return collect;
}
public void setCollect(boolean collect) {
this.collect = collect;
}
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getEnvelopePic() {
return envelopePic;
}
public void setEnvelopePic(String envelopePic) {
this.envelopePic = envelopePic;
}
public boolean isFresh() {
return fresh;
}
public void setFresh(boolean fresh) {
this.fresh = fresh;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getNiceDate() {
return niceDate;
}
public void setNiceDate(String niceDate) {
this.niceDate = niceDate;
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public String getProjectLink() {
return projectLink;
}
public void setProjectLink(String projectLink) {
this.projectLink = projectLink;
}
public long getPublishTime() {
return publishTime;
}
public void setPublishTime(long publishTime) {
this.publishTime = publishTime;
}
public int getSuperChapterId() {
return superChapterId;
}
public void setSuperChapterId(int superChapterId) {
this.superChapterId = superChapterId;
}
public String getSuperChapterName() {
return superChapterName;
}
public void setSuperChapterName(String superChapterName) {
this.superChapterName = superChapterName;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getVisible() {
return visible;
}
public void setVisible(int visible) {
this.visible = visible;
}
public int getZan() {
return zan;
}
public void setZan(int zan) {
this.zan = zan;
}
public List getTags() {
return tags;
}
public void setTags(List tags) {
this.tags = tags;
}
public static class TagsBean {
/**
* name : 公众号
* url : /wxarticle/list/408/1
*/
private String name;
private String url;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/bean/WXchapters.java
================================================
package com.senon.lib_common.bean;
import java.util.List;
/**
* 微信公众号列表
*/
public class WXchapters {
/**
* children : []
* courseId : 13
* id : 408
* name : 鸿洋
* order : 190000
* parentChapterId : 407
* userControlSetTop : false
* visible : 1
*/
private int courseId;
private int id;
private String name;
private int order;
private int parentChapterId;
private boolean userControlSetTop;
private int visible;
private List> children;
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public int getParentChapterId() {
return parentChapterId;
}
public void setParentChapterId(int parentChapterId) {
this.parentChapterId = parentChapterId;
}
public boolean isUserControlSetTop() {
return userControlSetTop;
}
public void setUserControlSetTop(boolean userControlSetTop) {
this.userControlSetTop = userControlSetTop;
}
public int getVisible() {
return visible;
}
public void setVisible(int visible) {
this.visible = visible;
}
public List> getChildren() {
return children;
}
public void setChildren(List> children) {
this.children = children;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/common/contract/LoginContract.java
================================================
package com.senon.lib_common.common.contract;
import com.senon.lib_common.base.BasePresenter;
import com.senon.lib_common.base.BaseViewImp;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.Login;
import java.util.HashMap;
/**
* LoginContract
*/
public interface LoginContract {
//方法命名以 请求方法+Result 命名
interface View extends BaseViewImp {
void getLoginResult(BaseResponse data);
void getRegisterResult(BaseResponse data);
}
//方法命名以 get+方法 命名
abstract class Presenter extends BasePresenter {
public abstract void getLogin(HashMap map, boolean isDialog, boolean cancelable);
public abstract void getRegister(HashMap map, boolean isDialog, boolean cancelable);
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/common/contract/WebviewContract.java
================================================
package com.senon.lib_common.common.contract;
import com.senon.lib_common.base.BasePresenter;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.base.BaseViewImp;
import com.senon.lib_common.bean.Login;
import java.util.HashMap;
/**
* WebviewContract
*/
public interface WebviewContract {
//方法命名以 请求方法+Result 命名
interface View extends BaseViewImp {
void getCollectResult(int id,boolean isCollect);
void getCollFailResult(int id);
}
//方法命名以 get+方法 命名
abstract class Presenter extends BasePresenter {
public abstract void getCollect(int id ,boolean isDialog, boolean cancelable);
public abstract void getUnollect(int id, boolean isDialog, boolean cancelable);
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/common/presenter/LoginPresenter.java
================================================
package com.senon.lib_common.common.presenter;
import android.content.Context;
import com.senon.lib_common.bean.Login;
import com.senon.lib_common.common.contract.LoginContract;
import com.senon.lib_common.net.ServerUtils;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.net.callback.RequestCallback;
import com.senon.lib_common.net.callback.RxErrorHandler;
import com.senon.lib_common.utils.RetryWithDelay;
import com.senon.lib_common.utils.RxUtils;
import com.senon.lib_common.utils.ToastUtil;
import java.util.HashMap;
/**
* 登录 P
*/
public class LoginPresenter extends LoginContract.Presenter {
private Context context;
public LoginPresenter(Context context) {
this.context = context;
}
@Override
public void getLogin(HashMap map, boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().login(map)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.>bindToLifecycle(getView()))
.compose(RxUtils.>getSchedulerTransformer())
.subscribe(new RequestCallback>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getLoginResult(baseResponse);
}else{
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
@Override
public void getRegister(HashMap map, boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().register(map)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.>bindToLifecycle(getView()))
.compose(RxUtils.>getSchedulerTransformer())
.subscribe(new RequestCallback>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getRegisterResult(baseResponse);
}else{
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/common/presenter/WebviewPresenter.java
================================================
package com.senon.lib_common.common.presenter;
import android.content.Context;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.Login;
import com.senon.lib_common.common.contract.WebviewContract;
import com.senon.lib_common.net.ServerUtils;
import com.senon.lib_common.net.callback.RequestCallback;
import com.senon.lib_common.net.callback.RxErrorHandler;
import com.senon.lib_common.utils.RetryWithDelay;
import com.senon.lib_common.utils.RxUtils;
import com.senon.lib_common.utils.ToastUtil;
import java.util.HashMap;
/**
* Webview P
*/
public class WebviewPresenter extends WebviewContract.Presenter {
private Context context;
public WebviewPresenter(Context context) {
this.context = context;
}
@Override
public void getCollect(final int id, boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getCollect(id)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.bindToLifecycle(getView()))
.compose(RxUtils.getSchedulerTransformer())
.subscribe(new RequestCallback(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getCollectResult(id,true);
}else{
getView().getCollFailResult(id);
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
@Override
public void getUnollect(final int id, boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getUncollectOriginId(id)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.bindToLifecycle(getView()))
.compose(RxUtils.getSchedulerTransformer())
.subscribe(new RequestCallback(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getCollectResult(id,false);
}else{
getView().getCollFailResult(id);
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/common/ui/Common_LoginActivity.java
================================================
package com.senon.lib_common.common.ui;
import android.graphics.Paint;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Autowired;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.ConstantLoginArouter;
import com.senon.lib_common.R;
import com.senon.lib_common.base.BaseActivity;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.bean.Login;
import com.senon.lib_common.common.contract.LoginContract;
import com.senon.lib_common.common.presenter.LoginPresenter;
import com.senon.lib_common.net.cookies.PersistentCookieStore;
import com.senon.lib_common.utils.BaseEvent;
import com.senon.lib_common.utils.StatusBarUtils;
import com.senon.lib_common.utils.ToastUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
/**
* 所有模块统一登录页面
*/
@Route(path = ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)
public class Common_LoginActivity extends BaseActivity implements
LoginContract.View {
@Autowired
String targetUrl;
private EditText account_edt,password_edt;
private TextView register_tv;
@Override
public int getLayoutId() {
StatusBarUtils.with(this).init();
return R.layout.activity_common__login;
}
@Override
public LoginContract.Presenter createPresenter() {
return new LoginPresenter(this);
}
@Override
public LoginContract.View createView() {
return this;
}
@Override
public void init() {
EventBus.getDefault().register(this);
account_edt = findViewById(R.id.account_edt);
password_edt = findViewById(R.id.password_edt);
register_tv = findViewById(R.id.register_tv);
register_tv.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);
}
@Override
public void getLoginResult(BaseResponse data) {
//登录成功时
//保存参数
PersistentCookieStore.getCookieStore().saveUserInfo(
data.getData().getUsername(),
password_edt.getText().toString().trim());
if(targetUrl != null){
//跳转到目标页
ARouter.getInstance().build(targetUrl).navigation();
}
BaseEvent event = new BaseEvent();
event.setCode(0);
EventBus.getDefault().post(event);
finish();
}
@Override
public void getRegisterResult(BaseResponse data) {
}
public void onClick(View view) {
int id = view.getId();
if(id == R.id.login_btn){
String account = account_edt.getText().toString();
String password = password_edt.getText().toString();
if (account.isEmpty()) {
ToastUtil.initToast("请输入账号");
return;
}
if (password.isEmpty()) {
ToastUtil.initToast("请输入密码");
return;
}
getPresenter().getLogin(ComUtil.getMd5Str(
new String[]{"username", "password"},
new String[]{account.trim(), password.trim()})
, true, true);
}else if(id == R.id.visitor_tv){
// 跳转到目标页
if(targetUrl != null){
//跳转到目标页
ARouter.getInstance().build(targetUrl).navigation();
}
finish();
}else if(id == R.id.register_tv){
//跳转到注册页 同意用arouter跳转,便于以后移动模块的改动
ARouter.getInstance().build(ConstantArouter.PATH_COMMON_REGISTERACTIVITY)
.withString("targetUrl",targetUrl)
.navigation();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行
public void onEventReceived(BaseEvent event) {
if(event.getCode() == 0){
finish();
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/common/ui/Common_RegisterActivity.java
================================================
package com.senon.lib_common.common.ui;
import android.graphics.Paint;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Autowired;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.ConstantLoginArouter;
import com.senon.lib_common.R;
import com.senon.lib_common.base.BaseActivity;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.Login;
import com.senon.lib_common.common.contract.LoginContract;
import com.senon.lib_common.common.presenter.LoginPresenter;
import com.senon.lib_common.net.cookies.PersistentCookieStore;
import com.senon.lib_common.utils.BaseEvent;
import com.senon.lib_common.utils.StatusBarUtils;
import com.senon.lib_common.utils.ToastUtil;
import org.greenrobot.eventbus.EventBus;
/**
* 所有模块统一注册页面
*/
@Route(path = ConstantArouter.PATH_COMMON_REGISTERACTIVITY)
public class Common_RegisterActivity extends BaseActivity implements
LoginContract.View {
@Autowired
String targetUrl;
private EditText account_edt,password_edt,password_re_edt;
private TextView login_tv;
@Override
public int getLayoutId() {
StatusBarUtils.with(this).init();
return R.layout.activity_common__register;
}
@Override
public LoginContract.Presenter createPresenter() {
return new LoginPresenter(this);
}
@Override
public LoginContract.View createView() {
return this;
}
@Override
public void init() {
if (targetUrl == null) {
//默认跳转到MainActivity
targetUrl = ConstantLoginArouter.PATH_APP_MAINACTIVITY;
}
account_edt = findViewById(R.id.account_edt);
password_edt = findViewById(R.id.password_edt);
password_re_edt = findViewById(R.id.password_re_edt);
login_tv = findViewById(R.id.login_tv);
login_tv.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);
}
@Override
public void getLoginResult(BaseResponse data) {
}
@Override
public void getRegisterResult(BaseResponse data) {
//登录成功时
//保存参数
PersistentCookieStore.getCookieStore().saveUserInfo(
data.getData().getUsername(),
password_edt.getText().toString().trim());
//跳转到目标页
if(targetUrl != null){
ARouter.getInstance().build(targetUrl).navigation();
}
BaseEvent event = new BaseEvent();
event.setCode(0);
EventBus.getDefault().post(event);
finish();
}
public void onClick(View view) {
int id = view.getId();
if(id == R.id.register_btn){
String account = account_edt.getText().toString();
String password = password_edt.getText().toString();
String repassword = password_re_edt.getText().toString();
if (account.isEmpty()) {
ToastUtil.initToast("请输入账号");
return;
}
if (password.isEmpty()) {
ToastUtil.initToast("请输入密码");
return;
}
if (repassword.isEmpty()) {
ToastUtil.initToast("请输入确认密码");
return;
}
if (!password.equals(repassword)) {
ToastUtil.initToast("确认密码与密码不同");
return;
}
getPresenter().getRegister(ComUtil.getMd5Str(
new String[]{"username", "password", "repassword"},
new String[]{account.trim(), password.trim(),repassword.trim()})
, true, true);
}else if(id == R.id.login_tv){
finish();
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/common/ui/Common_WebviewActivity.java
================================================
package com.senon.lib_common.common.ui;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Autowired;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.ConstantLoginArouter;
import com.senon.lib_common.R;
import com.senon.lib_common.base.BaseActivity;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.common.contract.WebviewContract;
import com.senon.lib_common.common.presenter.WebviewPresenter;
import com.senon.lib_common.utils.BaseEvent;
import com.senon.lib_common.utils.StatusBarUtils;
import org.greenrobot.eventbus.EventBus;
/**
* webview
*/
@Route(path = ConstantArouter.PATH_COMMON_WEBVIEWCTIVITY)
public class Common_WebviewActivity extends BaseActivity implements
WebviewContract.View {
@Autowired
int id;
@Autowired
String url;
@Autowired
boolean isCollection;
@Autowired
String title;
private TextView toolbar_title_tv;
private ProgressBar progressBar;
private WebView webView;
private TextView collection_tv;
@Override
public int getLayoutId() {
StatusBarUtils.with(this).init();
return R.layout.activity_common__webview;
}
@Override
public WebviewContract.Presenter createPresenter() {
return new WebviewPresenter(this);
}
@Override
public WebviewContract.View createView() {
return this;
}
@Override
public void init() {
ComUtil.changeStatusBarTextColor(this,true);
progressBar = findViewById(R.id.progressBar);
webView = findViewById(R.id.webView);
collection_tv = findViewById(R.id.collection_tv);
toolbar_title_tv = findViewById(R.id.toolbar_title_tv);
initClickListener();
initWebView();
}
private void initClickListener() {
toolbar_title_tv.setText(title);
toolbar_title_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webView.scrollTo(0,0);
}
});
findViewById(R.id.toolbar_back_igv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
if(id == 0){//id为空 则不设置收藏按钮
collection_tv.setVisibility(View.GONE);
return;
}
collection_tv.setText(isCollection ? "已收藏":"收藏");
collection_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isCollection = !isCollection;//该为相反状态
collection_tv.setText(isCollection ? "已收藏":"收藏");
if(isCollection){
getPresenter().getCollect(id,false,true);
}else{
getPresenter().getUnollect(id,false,true);
}
}
});
}
private void initWebView() {
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true); // 设置支持javascript脚本
webSettings.setPluginState(WebSettings.PluginState.ON);
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setTextZoom(100);
webSettings.setAppCacheEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setDatabaseEnabled(true);
if (ComUtil.isNetworkConnected()) {
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
} else {
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
}
webView.loadUrl(url);
webView.setWebViewClient(new WebViewClient() {
//实现点击webView页面的链接
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
view.loadUrl(url);
return true;
}
});
//设置WebViewClient用来辅助WebView处理各种通知请求事件等,如更新历史记录、网页开始加载/完毕、报告错误信息等
webView.setWebViewClient(new WebViewClient() {
// 以下方法避免 自动打开系统自带的浏览器,而是让新打开的网页在当前的WebView中显示
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
// 用于辅助WebView处理JavaScript的对话框、网站图标、网站标题以及网页加载进度等
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress == 100) {
progressBar.setVisibility(View.INVISIBLE);
} else {
if (progressBar.getVisibility() == View.INVISIBLE) {
progressBar.setVisibility(View.VISIBLE);
}
progressBar.setProgress(newProgress);
}
super.onProgressChanged(view, newProgress);
}
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
super.onShowCustomView(view, callback);
}
@Override
public void onHideCustomView() {
super.onHideCustomView();
}
});
}
@Override
public void getCollectResult(int id,boolean isCollect) {
BaseEvent event = new BaseEvent();
event.setCode(101);
event.setId(id);
event.setCollect(isCollect);
EventBus.getDefault().post(event);
}
@Override
public void getCollFailResult(int id) {
if(this.id == id){
isCollection = !isCollection;
collection_tv.setText(isCollection ? "已收藏":"收藏");
}
ARouter.getInstance().build(ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)
.navigation();
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/net/RequestInterceptor.java
================================================
package com.senon.lib_common.net;
import org.json.JSONObject;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
/**
* 网络统一拦截
*/
public class RequestInterceptor implements Interceptor {
private final int DEVICE_TYPE = 1; // 设备类型
private RequestInterceptor() {
}
private static RequestInterceptor instance;
public static RequestInterceptor getInstance() {
if (instance == null) {
synchronized (RequestInterceptor.class) {
if (instance == null) {
instance = new RequestInterceptor();
}
}
}
return instance;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.header("data", fetchHeaderInfo())
.method(original.method(), original.body());
return chain.proceed(requestBuilder.build());
}
private String fetchHeaderInfo() {
// String deviceCode = MD5Utils.GetMD5Code(MobileInfo.phoneOnlyCode(context));
Map map = new HashMap<>();
// map.put("DeviceType", String.valueOf(DEVICE_TYPE));
// map.put("DeviceToken", deviceCode);
// map.put("APPVersion", APP_VERSION_NAME);
// map.put("RegistrationID", jpushID);
// map.put("Authorization", token);
JSONObject json = new JSONObject(map);
return json.toString();
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/net/ServerUtils.java
================================================
package com.senon.lib_common.net;
import com.senon.lib_common.AppConfig;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.api.BaseApi;
import com.senon.lib_common.net.cookies.CookiesManager;
import com.senon.lib_common.utils.ConstantUtils;
import java.io.File;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
/**
* 网络请求 工具
*/
public class ServerUtils {
private static final int TIME_OUT = 5 * 1000;//链接超时时间
private volatile static BaseApi mBaseApi;
private static File cacheFile = new File(AppConfig.PATH_CACHE);
private static Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
public static BaseApi getCommonApi() {
try {
if (mBaseApi == null) {
synchronized (ServerUtils.class) {
if (mBaseApi == null) {
mBaseApi = createService(BaseApi.class, AppConfig.BASE_URL);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return mBaseApi;
}
private static S createService(Class serviceClass, String url) throws Exception {
Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(url)
.client(httpClient.build())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
return retrofit.create(serviceClass);
}
private static Interceptor cacheInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!ComUtil.isNetworkConnected()) {
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
Response response = chain.proceed(request);
if (ComUtil.isNetworkConnected()) {
int maxAge = 0;
// 有网络时, 不缓存, 最大保存时长为0
response.newBuilder()
.header("Cache-Control", "public, max-age=" + maxAge)
.removeHeader("Pragma")
.build();
} else {
// 无网络时,设置超时为1周
int maxStale = 60 * 60 * 24 * 7;
response.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.removeHeader("Pragma")
.build();
}
return response;
}
};
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder()
//设置超时
.readTimeout(TIME_OUT, TimeUnit.SECONDS)
.writeTimeout(TIME_OUT, TimeUnit.SECONDS)
.connectTimeout(TIME_OUT, TimeUnit.SECONDS)
// .addInterceptor(RequestInterceptor.getInstance())//网络请求 统一拦截
.addInterceptor(getLogInterceptor())
.sslSocketFactory(getSSLSocketFactory())
//设置缓存
.addNetworkInterceptor(cacheInterceptor)
.addInterceptor(cacheInterceptor)
.cache(cache)
//设置cookies
.cookieJar(new CookiesManager())
.hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
private static HttpLoggingInterceptor getLogInterceptor() {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
if (ConstantUtils.isAppDebug()) {
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
} else {
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
}
return loggingInterceptor;
}
/**
* 不验证证书
*
* @return
* @throws Exception
*/
private static SSLSocketFactory getSSLSocketFactory() {
//创建一个不验证证书链的证书信任管理器。
final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain,
String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain,
String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
}};
final SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts,
new java.security.SecureRandom());
return sslContext
.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/net/callback/ErrorListener.java
================================================
package com.senon.lib_common.net.callback;
public interface ErrorListener {
void handleError(Throwable e);
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/net/callback/RequestCallback.java
================================================
package com.senon.lib_common.net.callback;
import android.content.Context;
import com.senon.lib_common.net.progress.ProgressCancelListener;
import com.senon.lib_common.net.progress.ProgressDialogHandler;
import io.reactivex.Observer;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
/**
* RxJava 自定义回调
*/
public abstract class RequestCallback implements Observer,ProgressCancelListener {
private ErrorListener errorListener;
private Disposable mDisposable;
private Context mContext;
private boolean cancelable = false;//该dialog如果开启 则可以设置是否能够返回键取消请求
private ProgressDialogHandler mProgressDialogHandler;//默认为null 即不开启dialog
public RequestCallback(Context context,ErrorListener errorListener) {
this(context,errorListener,false);
}
/**
* 传这个构造默认开启dialog
* @param cancelable 该dialog如果开启 则可以设置是否能够返回键取消请求
*/
public RequestCallback(Context context,ErrorListener errorListener,boolean cancelable) {
this(context,errorListener,true,cancelable);
}
public RequestCallback(Context context,ErrorListener errorListener,boolean showDialog,boolean cancelable) {
this.mContext = context;
this.errorListener = errorListener;
this.cancelable = cancelable;
if(showDialog){
this.mProgressDialogHandler = new ProgressDialogHandler(context, this, cancelable);
}
}
private void showProgressDialog() {
if (mProgressDialogHandler != null) {
mProgressDialogHandler.obtainMessage(ProgressDialogHandler.SHOW_PROGRESS_DIALOG).sendToTarget();
}
}
private void dismissProgressDialog() {
if (mProgressDialogHandler != null) {
mProgressDialogHandler.obtainMessage(ProgressDialogHandler.DISMISS_PROGRESS_DIALOG).sendToTarget();
mProgressDialogHandler = null;
}
}
@Override
public void onSubscribe(@NonNull Disposable d) {
this.mDisposable = d;
showProgressDialog();
}
@Override
public void onNext(@NonNull T t) {
}
@Override
public void onError(@NonNull Throwable e) {
e.printStackTrace();
dismissProgressDialog();
if (errorListener != null) {
errorListener.handleError(e);
}
}
@Override
public void onComplete() {
dismissProgressDialog();
}
@Override
public void onCancelProgress() {
//如果处于订阅状态,则取消订阅
if (!mDisposable.isDisposed()) {
mDisposable.dispose();
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/net/callback/RxErrorHandler.java
================================================
package com.senon.lib_common.net.callback;
import com.senon.lib_common.utils.LogUtils;
import com.senon.lib_common.utils.ToastUtil;
public class RxErrorHandler implements ErrorListener {
private volatile static RxErrorHandler rxErrorHandler;
private RxErrorHandler() {
}
public static RxErrorHandler getInstance() {
if (rxErrorHandler == null) {
synchronized (RxErrorHandler.class) {
if (rxErrorHandler == null) {
rxErrorHandler = new RxErrorHandler();
}
}
}
return rxErrorHandler;
}
@Override
public void handleError(Throwable throwable) {
String errorString = throwable.toString();
LogUtils.e("网络错误信息为 ========>>>" + throwable.toString());
//返回的错误为空
if (errorString == null) {
ToastUtil.initToast("网络数据异常,请重试");
} else {
//请求超时
if (errorString.contains("TimeoutException") || errorString.contains("SocketTimeoutException")) {
ToastUtil.initToast("网络请求超时,请重试");
}
//能识别的请求异常,忽略不提示
if (errorString.contains("SSLException")) {
}
//403、404等服务错误
if (errorString.contains("ServiceConfigurationError") || errorString.contains("AuthenticatorException")) {
ToastUtil.initToast("网络数据异常,请重试");
}
//网络未连接
if (errorString.contains("NetworkErrorException") || errorString.contains("NoConnectionPendingException") || errorString.contains("UnknownHostException")) {
ToastUtil.initToast("您的网络不给力,请检查网络设置");
}
//连接不到服务器
if (errorString.contains("ConnectException")) {
ToastUtil.initToast("网络连接失败");
}
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/net/cookies/CookiesManager.java
================================================
package com.senon.lib_common.net.cookies;
import android.support.annotation.NonNull;
import java.util.List;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
/**
* @author lw
* @date 2018/1/25
*/
public class CookiesManager implements CookieJar {
private static final PersistentCookieStore COOKIE_STORE = PersistentCookieStore.getCookieStore();
@Override
public void saveFromResponse(@NonNull HttpUrl url, @NonNull List cookies) {
if (cookies.size() > 0) {
for (Cookie item : cookies) {
COOKIE_STORE.add(url, item);
}
}
}
@Override
public List loadForRequest(@NonNull HttpUrl url) {
return COOKIE_STORE.get(url);
}
/**
* 清除所有cookie
*/
public static void clearAllCookies() {
COOKIE_STORE.removeAll();
}
/**
* 清除指定cookie
*
* @param url HttpUrl
* @param cookie Cookie
* @return if clear cookies
*/
public static boolean clearCookies(HttpUrl url, Cookie cookie) {
return COOKIE_STORE.remove(url, cookie);
}
/**
* 获取cookies
*
* @return List
*/
public static List getCookies() {
return COOKIE_STORE.getCookies();
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/net/cookies/OkHttpCookies.java
================================================
package com.senon.lib_common.net.cookies;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import okhttp3.Cookie;
/**
* Cookies对象
*/
class OkHttpCookies implements Serializable {
private transient final Cookie cookies;
private transient Cookie clientCookies;
OkHttpCookies(Cookie cookies) {
this.cookies = cookies;
}
Cookie getCookies() {
Cookie bestCookies = cookies;
if (clientCookies != null) {
bestCookies = clientCookies;
}
return bestCookies;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(cookies.name());
out.writeObject(cookies.value());
out.writeLong(cookies.expiresAt());
out.writeObject(cookies.domain());
out.writeObject(cookies.path());
out.writeBoolean(cookies.secure());
out.writeBoolean(cookies.httpOnly());
out.writeBoolean(cookies.hostOnly());
out.writeBoolean(cookies.persistent());
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
String name = (String) in.readObject();
String value = (String) in.readObject();
long expiresAt = in.readLong();
String domain = (String) in.readObject();
String path = (String) in.readObject();
boolean secure = in.readBoolean();
boolean httpOnly = in.readBoolean();
boolean hostOnly = in.readBoolean();
Cookie.Builder builder = new Cookie.Builder();
builder = builder.name(name);
builder = builder.value(value);
builder = builder.expiresAt(expiresAt);
builder = hostOnly ? builder.hostOnlyDomain(domain) : builder.domain(domain);
builder = builder.path(path);
builder = secure ? builder.secure() : builder;
builder = httpOnly ? builder.httpOnly() : builder;
clientCookies = builder.build();
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/net/cookies/PersistentCookieStore.java
================================================
package com.senon.lib_common.net.cookies;
import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
import android.util.Log;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import okhttp3.Cookie;
import okhttp3.HttpUrl;
/**
* 持久化Cookies
*/
public class PersistentCookieStore {
private static final String LOG_TAG = "PersistentCookieStore";
private static final String COOKIE_PREFS = "Cookies_Prefs";
private static final String NAME = "user_name";
private static final String PASSWORD = "user_password";
private final Map> cookies;
private final SharedPreferences cookiePrefs;
private static PersistentCookieStore cookieStore;
public static void init(Context context){
cookieStore = new PersistentCookieStore(context);
}
public static PersistentCookieStore getCookieStore(){
return cookieStore;
}
private PersistentCookieStore(Context context) {
cookies = new HashMap<>();
cookiePrefs = context.getSharedPreferences(COOKIE_PREFS, Context.MODE_PRIVATE);
//将持久化的cookies缓存到内存中 即map cookies
Map prefsMap = cookiePrefs.getAll();
for (Map.Entry entry : prefsMap.entrySet()) {
String[] cookieNames = TextUtils.split((String) entry.getValue(), ",");
for (String name : cookieNames) {
String encodedCookie = cookiePrefs.getString(name, null);
if (encodedCookie != null) {
Cookie decodedCookie = decodeCookie(encodedCookie);
if (decodedCookie != null) {
if (!cookies.containsKey(entry.getKey())) {
cookies.put(entry.getKey(), new ConcurrentHashMap());
}
cookies.get(entry.getKey()).put(name, decodedCookie);
}
}
}
}
}
private String getCookieToken(Cookie cookie) {
return cookie.name() + "@" + cookie.domain();
}
public void add(HttpUrl url, Cookie cookie) {
String name = getCookieToken(cookie);
//将cookies缓存到内存中 如果缓存过期 就重置此cookie
if (!cookie.persistent()) {
if (!cookies.containsKey(url.host())) {
cookies.put(url.host(), new ConcurrentHashMap(10));
}
cookies.get(url.host()).put(name, cookie);
} else {
if (cookies.containsKey(url.host())) {
cookies.get(url.host()).remove(name);
}
}
//将cookies持久化到本地
SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
prefsWriter.putString(url.host(), TextUtils.join(",", cookies.get(url.host()).keySet()));//将key值存储用以查询
prefsWriter.putString(name, encodeCookie(new OkHttpCookies(cookie)));
prefsWriter.apply();
}
public List get(HttpUrl url) {
ArrayList ret = new ArrayList<>();
if (cookies.containsKey(url.host())) {
ret.addAll(cookies.get(url.host()).values());
}
return ret;
}
void removeAll() {
SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
prefsWriter.clear();
prefsWriter.apply();
cookies.clear();
}
public void saveUserInfo(String username,String password){
//将userinfo持久化到本地
SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
prefsWriter.putString(NAME,username);
prefsWriter.putString(PASSWORD,password);
prefsWriter.apply();
}
public boolean isLogin(){
if(cookiePrefs.getString(NAME,null) != null &&
cookiePrefs.getString(PASSWORD,null) != null){
return true;
}
return false;
}
public String getUsername(){
String name = cookiePrefs.getString(NAME,null);
if(cookiePrefs.getString(NAME,null) != null){
return name;
}
return "未知用户";
}
boolean remove(HttpUrl url, Cookie cookie) {
String name = getCookieToken(cookie);
if (cookies.containsKey(url.host()) && cookies.get(url.host()).containsKey(name)) {
cookies.get(url.host()).remove(name);
SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
if (cookiePrefs.contains(name)) {
prefsWriter.remove(name);
}
prefsWriter.putString(url.host(), TextUtils.join(",", cookies.get(url.host()).keySet()));
prefsWriter.apply();
return true;
} else {
return false;
}
}
List getCookies() {
ArrayList ret = new ArrayList<>();
for (String key : cookies.keySet()) {
ret.addAll(cookies.get(key).values());
}
return ret;
}
/**
* cookies 序列化成 string
*
* @param cookie 要序列化的cookie
* @return 序列化之后的string
*/
private String encodeCookie(OkHttpCookies cookie) {
if (cookie == null) {
return null;
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ObjectOutputStream outputStream = new ObjectOutputStream(os);
outputStream.writeObject(cookie);
} catch (IOException e) {
Log.d(LOG_TAG, "IOException in encodeCookie", e);
return null;
}
return byteArrayToHexString(os.toByteArray());
}
/**
* 将字符串反序列化成cookies
*
* @param cookieString cookies string
* @return cookie object
*/
private Cookie decodeCookie(String cookieString) {
byte[] bytes = hexStringToByteArray(cookieString);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
Cookie cookie = null;
try {
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
cookie = ((OkHttpCookies) objectInputStream.readObject()).getCookies();
} catch (IOException e) {
Log.d(LOG_TAG, "IOException in decodeCookie", e);
} catch (ClassNotFoundException e) {
Log.d(LOG_TAG, "ClassNotFoundException in decodeCookie", e);
}
return cookie;
}
/**
* 二进制数组转十六进制字符串
*
* @param bytes byte array to be converted
* @return string containing hex values
*/
private String byteArrayToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (byte element : bytes) {
int v = element & 0xff;
if (v < 16) {
sb.append('0');
}
sb.append(Integer.toHexString(v));
}
return sb.toString().toUpperCase(Locale.US);
}
/**
* 十六进制字符串转二进制数组
*
* @param hexString string of hex-encoded values
* @return decoded byte array
*/
private byte[] hexStringToByteArray(String hexString) {
int len = hexString.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
}
return data;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/net/progress/ProgressCancelListener.java
================================================
package com.senon.lib_common.net.progress;
/**
* 取消请求监听
*/
public interface ProgressCancelListener {
void onCancelProgress();
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/net/progress/ProgressDialogHandler.java
================================================
package com.senon.lib_common.net.progress;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;
import cn.pedant.SweetAlert.SweetAlertDialog;
/**
* Dialog的进度控制
*/
public class ProgressDialogHandler extends Handler {
public static final int SHOW_PROGRESS_DIALOG = 1;
public static final int DISMISS_PROGRESS_DIALOG = 2;
private SweetAlertDialog sad;
private Context context;
private boolean cancelable;
private ProgressCancelListener mProgressCancelListener;
public ProgressDialogHandler(Context context, ProgressCancelListener mProgressCancelListener, boolean cancelable) {
super();
this.context = context;
this.mProgressCancelListener = mProgressCancelListener;
this.cancelable = cancelable;
}
private void initProgressDialog() {
if (sad == null) {
sad = new SweetAlertDialog(context);
sad.changeAlertType(SweetAlertDialog.PROGRESS_TYPE);
sad.setTitleText("正在加载...");
sad.setCancelable(cancelable);
if (cancelable) {
sad.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
mProgressCancelListener.onCancelProgress();
}
});
}
if (!sad.isShowing()) {
sad.show();
}
}
}
private void dismissProgressDialog() {
if (sad != null) {
sad.dismiss();
sad = null;
}
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_PROGRESS_DIALOG:
initProgressDialog();
break;
case DISMISS_PROGRESS_DIALOG:
dismissProgressDialog();
break;
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/service/InitializeService.java
================================================
package com.senon.lib_common.service;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
/**
* 在Service中 初始化耗时的SDK等(BaseAppDeletage调用)
* 为了在application中 不进行耗时操作 影响冷启动 白屏时间增加
*
* IntentService特点:
* 1.在任务完成后将自动停止。
* 2.任务在队列中执行,是有先后顺序的。
* 3.任务在子线程中运行,可以执行耗时任务。
*/
public class InitializeService extends IntentService {
private static final String ACTION_INIT = "initApplication";
public InitializeService() {
super("InitializeService");
}
public static void start(Context context) {
Intent intent = new Intent(context, InitializeService.class);
intent.setAction(ACTION_INIT);
context.startService(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_INIT.equals(action)) {
initApplication();
}
}
}
//初始化
private void initApplication() {
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/utils/ACache.java
================================================
package com.senon.lib_common.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import com.senon.lib_common.AppConfig;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author Michael Yang(www.yangfuhai.com) update at 2013.08.07
*/
public class ACache {
public static final int TIME_HOUR = 60 * 60;
public static final int TIME_DAY = TIME_HOUR * 24;
private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb
private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量
private static Map mInstanceMap = new HashMap();
private ACacheManager mCache;
public static ACache get(Context ctx) {
return get(ctx, "Data");
}
public static ACache get(Context ctx, String cacheName) {
File f = new File(AppConfig.PATH_DATA, cacheName);
return get(f, MAX_SIZE, MAX_COUNT);
}
public static ACache get(File cacheDir) {
return get(cacheDir, MAX_SIZE, MAX_COUNT);
}
public static ACache get(Context ctx, long max_zise, int max_count) {
File f = new File(AppConfig.PATH_DATA, "Data");
return get(f, max_zise, max_count);
}
public static ACache get(File cacheDir, long max_zise, int max_count) {
ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid());
if (manager == null) {
manager = new ACache(cacheDir, max_zise, max_count);
mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager);
}
return manager;
}
public static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (String aChildren : children) {
boolean success = deleteDir(new File(dir, aChildren));
if (!success) {
return false;
}
}
}
assert dir != null;
return dir.delete();
}
public static String getCacheSize(File file) {
return getFormatSize(getFolderSize(file));
}
public static long getFolderSize(File file) {
long size = 0;
try {
File[] fileList = file.listFiles();
for (File aFileList : fileList) {
// 如果下面还有文件
if (aFileList.isDirectory()) {
size = size + getFolderSize(aFileList);
} else {
size = size + aFileList.length();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return size;
}
public static String getFormatSize(double size) {
double kiloByte = size / 1024;
if (kiloByte < 1) {
// return size + "Byte";
return "0K";
}
double megaByte = kiloByte / 1024;
if (megaByte < 1) {
BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
return result1.setScale(2, BigDecimal.ROUND_HALF_UP)
.toPlainString() + "KB";
}
double gigaByte = megaByte / 1024;
if (gigaByte < 1) {
BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
return result2.setScale(2, BigDecimal.ROUND_HALF_UP)
.toPlainString() + "MB";
}
double teraBytes = gigaByte / 1024;
if (teraBytes < 1) {
BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
return result3.setScale(2, BigDecimal.ROUND_HALF_UP)
.toPlainString() + "GB";
}
BigDecimal result4 = new BigDecimal(teraBytes);
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()
+ "TB";
}
private static String myPid() {
return "_" + android.os.Process.myPid();
}
private ACache(File cacheDir, long max_size, int max_count) {
if (!cacheDir.exists() && !cacheDir.mkdirs()) {
throw new RuntimeException("can't make dirs in " + cacheDir.getAbsolutePath());
}
mCache = new ACacheManager(cacheDir, max_size, max_count);
}
// =======================================
// ============ String数据 读写 ==============
// =======================================
/**
* 保存 String数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的String数据
*/
public void put(String key, String value) {
File file = mCache.newFile(key);
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(file), 1024);
out.write(value);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
mCache.put(file);
}
}
/**
* 保存 String数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的String数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, String value, int saveTime) {
put(key, Utils.newStringWithDateInfo(saveTime, value));
}
/**
* 读取 String数据
*
* @return String 数据
*/
public String getAsString(String key) {
File file = mCache.get(key);
if (!file.exists()) return null;
boolean removeFile = false;
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(file));
String readString = "";
String currentLine;
while ((currentLine = in.readLine()) != null) {
readString += currentLine;
}
if (!Utils.isDue(readString)) {
return Utils.clearDateInfo(readString);
}
else {
removeFile = true;
return null;
}
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (removeFile) remove(key);
}
}
// =======================================
// ============= JSONObject 数据 读写 ==============
// =======================================
/**
* 保存 JSONObject数据 到 缓存中
* @param key 保存的key
* @param value 保存的JSON数据
*/
public void put(String key, JSONObject value) {
put(key, value.toString());
}
/**
* 保存 JSONObject数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的JSONObject数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, JSONObject value, int saveTime) {
put(key, value.toString(), saveTime);
}
/**
* 读取JSONObject数据
*
* @return JSONObject数据
*/
public JSONObject getAsJSONObject(String key) {
String JSONString = getAsString(key);
try {
JSONObject obj = new JSONObject(JSONString);
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// =======================================
// ============ JSONArray 数据 读写 =============
// =======================================
/**
* 保存 JSONArray数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的JSONArray数据
*/
public void put(String key, JSONArray value) {
put(key, value.toString());
}
/**
* 保存 JSONArray数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的JSONArray数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, JSONArray value, int saveTime) {
put(key, value.toString(), saveTime);
}
/**
* 读取JSONArray数据
*
* @return JSONArray数据
*/
public JSONArray getAsJSONArray(String key) {
String JSONString = getAsString(key);
try {
JSONArray obj = new JSONArray(JSONString);
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// =======================================
// ============== byte 数据 读写 =============
// =======================================
/**
* 保存 byte数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的数据
*/
public void put(String key, byte[] value) {
File file = mCache.newFile(key);
FileOutputStream out = null;
try {
out = new FileOutputStream(file);
out.write(value);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
mCache.put(file);
}
}
/**
* 保存 byte数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, byte[] value, int saveTime) {
put(key, Utils.newByteArrayWithDateInfo(saveTime, value));
}
/**
* 获取 byte 数据
*
* @return byte 数据
*/
public byte[] getAsBinary(String key) {
RandomAccessFile RAFile = null;
boolean removeFile = false;
try {
File file = mCache.get(key);
if (!file.exists()) return null;
RAFile = new RandomAccessFile(file, "r");
byte[] byteArray = new byte[(int) RAFile.length()];
RAFile.read(byteArray);
if (!Utils.isDue(byteArray)) {
return Utils.clearDateInfo(byteArray);
}
else {
removeFile = true;
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (RAFile != null) {
try {
RAFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (removeFile) remove(key);
}
}
// =======================================
// ============= 序列化 数据 读写 ===============
// =======================================
/**
* 保存 Serializable数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的value
*/
public void put(String key, Serializable value) {
put(key, value, -1);
}
/**
* 保存 Serializable数据到 缓存中
*
* @param key 保存的key
* @param value 保存的value
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, Serializable value, int saveTime) {
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(value);
byte[] data = baos.toByteArray();
if (saveTime != -1) {
put(key, data, saveTime);
}
else {
put(key, data);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
oos.close();
} catch (IOException e) {
}
}
}
/**
* 读取 Serializable数据
*
* @return Serializable 数据
*/
public Object getAsObject(String key) {
byte[] data = getAsBinary(key);
if (data != null) {
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
bais = new ByteArrayInputStream(data);
ois = new ObjectInputStream(bais);
Object reObject = ois.readObject();
return reObject;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
if (bais != null) bais.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (ois != null) ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
// =======================================
// ============== bitmap 数据 读写 =============
// =======================================
/**
* 保存 bitmap 到 缓存中
*
* @param key 保存的key
* @param value 保存的bitmap数据
*/
public void put(String key, Bitmap value) {
put(key, Utils.Bitmap2Bytes(value));
}
/**
* 保存 bitmap 到 缓存中
*
* @param key 保存的key
* @param value 保存的 bitmap 数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, Bitmap value, int saveTime) {
put(key, Utils.Bitmap2Bytes(value), saveTime);
}
/**
* 读取 bitmap 数据
*
* @return bitmap 数据
*/
public Bitmap getAsBitmap(String key) {
if (getAsBinary(key) == null) {
return null;
}
return Utils.Bytes2Bimap(getAsBinary(key));
}
// =======================================
// ============= drawable 数据 读写 =============
// =======================================
/**
* 保存 drawable 到 缓存中
*
* @param key 保存的key
* @param value 保存的drawable数据
*/
public void put(String key, Drawable value) {
put(key, Utils.drawable2Bitmap(value));
}
/**
* 保存 drawable 到 缓存中
*
* @param key 保存的key
* @param value 保存的 drawable 数据
* @param saveTime 保存的时间,单位:秒
*/
public void put(String key, Drawable value, int saveTime) {
put(key, Utils.drawable2Bitmap(value), saveTime);
}
/**
* 读取 Drawable 数据
*
* @return Drawable 数据
*/
public Drawable getAsDrawable(String key) {
if (getAsBinary(key) == null) {
return null;
}
return Utils.bitmap2Drawable(Utils.Bytes2Bimap(getAsBinary(key)));
}
/**
* 获取缓存文件
*
* @return value 缓存的文件
*/
public File file(String key) {
File f = mCache.newFile(key);
if (f.exists()) return f;
return null;
}
/**
* 移除某个key
*
* @return 是否移除成功
*/
public boolean remove(String key) {
return mCache.remove(key);
}
/**
* 清除所有数据
*/
public void clear() {
mCache.clear();
}
/**
* @author 杨福海(michael) www.yangfuhai.com
* @version 1.0
* @title 缓存管理器
*/
public class ACacheManager {
private final AtomicLong cacheSize;
private final AtomicInteger cacheCount;
private final long sizeLimit;
private final int countLimit;
private final Map lastUsageDates = Collections.synchronizedMap(new HashMap());
protected File cacheDir;
private ACacheManager(File cacheDir, long sizeLimit, int countLimit) {
this.cacheDir = cacheDir;
this.sizeLimit = sizeLimit;
this.countLimit = countLimit;
cacheSize = new AtomicLong();
cacheCount = new AtomicInteger();
calculateCacheSizeAndCacheCount();
}
/**
* 计算 cacheSize和cacheCount
*/
private void calculateCacheSizeAndCacheCount() {
new Thread(new Runnable() {
@Override public void run() {
int size = 0;
int count = 0;
File[] cachedFiles = cacheDir.listFiles();
if (cachedFiles != null) {
for (File cachedFile : cachedFiles) {
size += calculateSize(cachedFile);
count += 1;
lastUsageDates.put(cachedFile, cachedFile.lastModified());
}
cacheSize.set(size);
cacheCount.set(count);
}
}
}).start();
}
private void put(File file) {
int curCacheCount = cacheCount.get();
while (curCacheCount + 1 > countLimit) {
long freedSize = removeNext();
cacheSize.addAndGet(-freedSize);
curCacheCount = cacheCount.addAndGet(-1);
}
cacheCount.addAndGet(1);
long valueSize = calculateSize(file);
long curCacheSize = cacheSize.get();
while (curCacheSize + valueSize > sizeLimit) {
long freedSize = removeNext();
curCacheSize = cacheSize.addAndGet(-freedSize);
}
cacheSize.addAndGet(valueSize);
Long currentTime = System.currentTimeMillis();
file.setLastModified(currentTime);
lastUsageDates.put(file, currentTime);
}
private File get(String key) {
File file = newFile(key);
Long currentTime = System.currentTimeMillis();
file.setLastModified(currentTime);
lastUsageDates.put(file, currentTime);
return file;
}
private File newFile(String key) {
return new File(cacheDir, key.hashCode() + "");
}
private boolean remove(String key) {
File image = get(key);
return image.delete();
}
private void clear() {
lastUsageDates.clear();
cacheSize.set(0);
File[] files = cacheDir.listFiles();
if (files != null) {
for (File f : files) {
f.delete();
}
}
}
/**
* 移除旧的文件
*/
private long removeNext() {
if (lastUsageDates.isEmpty()) {
return 0;
}
Long oldestUsage = null;
File mostLongUsedFile = null;
Set> entries = lastUsageDates.entrySet();
synchronized (lastUsageDates) {
for (Entry entry : entries) {
if (mostLongUsedFile == null) {
mostLongUsedFile = entry.getKey();
oldestUsage = entry.getValue();
}
else {
Long lastValueUsage = entry.getValue();
if (lastValueUsage < oldestUsage) {
oldestUsage = lastValueUsage;
mostLongUsedFile = entry.getKey();
}
}
}
}
long fileSize = calculateSize(mostLongUsedFile);
if (mostLongUsedFile.delete()) {
lastUsageDates.remove(mostLongUsedFile);
}
return fileSize;
}
private long calculateSize(File file) {
return file.length();
}
}
/**
* @author 杨福海(michael) www.yangfuhai.com
* @version 1.0
* @title 时间计算工具类
*/
private static class Utils {
/**
* 判断缓存的String数据是否到期
*
* @return true:到期了 false:还没有到期
*/
private static boolean isDue(String str) {
return isDue(str.getBytes());
}
/**
* 判断缓存的byte数据是否到期
*
* @return true:到期了 false:还没有到期
*/
private static boolean isDue(byte[] data) {
String[] strs = getDateInfoFromDate(data);
if (strs != null && strs.length == 2) {
String saveTimeStr = strs[0];
while (saveTimeStr.startsWith("0")) {
saveTimeStr = saveTimeStr.substring(1, saveTimeStr.length());
}
long saveTime = Long.valueOf(saveTimeStr);
long deleteAfter = Long.valueOf(strs[1]);
if (System.currentTimeMillis() > saveTime + deleteAfter * 1000) {
return true;
}
}
return false;
}
private static String newStringWithDateInfo(int second, String strInfo) {
return createDateInfo(second) + strInfo;
}
private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) {
byte[] data1 = createDateInfo(second).getBytes();
byte[] retdata = new byte[data1.length + data2.length];
System.arraycopy(data1, 0, retdata, 0, data1.length);
System.arraycopy(data2, 0, retdata, data1.length, data2.length);
return retdata;
}
private static String clearDateInfo(String strInfo) {
if (strInfo != null && hasDateInfo(strInfo.getBytes())) {
strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1, strInfo.length());
}
return strInfo;
}
private static byte[] clearDateInfo(byte[] data) {
if (hasDateInfo(data)) {
return copyOfRange(data, indexOf(data, mSeparator) + 1, data.length);
}
return data;
}
private static boolean hasDateInfo(byte[] data) {
return data != null && data.length > 15 && data[13] == '-' && indexOf(data, mSeparator) > 14;
}
private static String[] getDateInfoFromDate(byte[] data) {
if (hasDateInfo(data)) {
String saveDate = new String(copyOfRange(data, 0, 13));
String deleteAfter = new String(copyOfRange(data, 14, indexOf(data, mSeparator)));
return new String[] { saveDate, deleteAfter };
}
return null;
}
private static int indexOf(byte[] data, char c) {
for (int i = 0; i < data.length; i++) {
if (data[i] == c) {
return i;
}
}
return -1;
}
private static byte[] copyOfRange(byte[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0) throw new IllegalArgumentException(from + " > " + to);
byte[] copy = new byte[newLength];
System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
return copy;
}
private static final char mSeparator = ' ';
private static String createDateInfo(int second) {
String currentTime = System.currentTimeMillis() + "";
while (currentTime.length() < 13) {
currentTime = "0" + currentTime;
}
return currentTime + "-" + second + mSeparator;
}
/*
* Bitmap → byte[]
*/
private static byte[] Bitmap2Bytes(Bitmap bm) {
if (bm == null) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
/*
* byte[] → Bitmap
*/
private static Bitmap Bytes2Bimap(byte[] b) {
if (b.length == 0) {
return null;
}
return BitmapFactory.decodeByteArray(b, 0, b.length);
}
/*
* Drawable → Bitmap
*/
private static Bitmap drawable2Bitmap(Drawable drawable) {
if (drawable == null) {
return null;
}
// 取 drawable 的长宽
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
// 取 drawable 的颜色格式
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE
? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
// 建立对应 bitmap
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
// 建立对应 bitmap 的画布
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
// 把 drawable 内容画到画布中
drawable.draw(canvas);
return bitmap;
}
/*
* Bitmap → Drawable
*/
@SuppressWarnings("deprecation") private static Drawable bitmap2Drawable(Bitmap bm) {
if (bm == null) {
return null;
}
return new BitmapDrawable(bm);
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/utils/BaseEvent.java
================================================
package com.senon.lib_common.utils;
/**
* eventbus发送实体
*/
public class BaseEvent {
/**
// * -1:退出登录时通知Mainactivity finish
* 0:登录成功 刷新所有主界面数据列表
* 1:退出成功 。。。
*
* 101:文章收藏/取消收藏 (HomeMainFragment、ArtMainFragment、HomeArticleActivity、HomeProjectActivity)
* 102:文章收藏/取消收藏失败 。。。
*
*
*
*
*/
private int code;
private String msg;
private T data;
private boolean isCollect;
private int id;
private boolean ingored;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public boolean isCollect() {
return isCollect;
}
public void setCollect(boolean collect) {
isCollect = collect;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isIngored() {
return ingored;
}
public void setIngored(boolean ingored) {
this.ingored = ingored;
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/utils/ConstantUtils.java
================================================
package com.senon.lib_common.utils;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
/**
* 基础常量工具类
*/
public class ConstantUtils {
private static Context context;
/**
* 初始化工具类
* @param context 上下文
*/
public static void init(Context context) {
ConstantUtils.context = context.getApplicationContext();
}
/**
* 获取ApplicationContext
* @return ApplicationContext
*/
public static Context getAPPContext() {
if (context != null) return context;
throw new NullPointerException("u should init first");
}
/**
* 判断App是否是Debug版本
* @return {@code true}: 是
{@code false}: 否
*/
public static boolean isAppDebug() {
String packageName = context.getPackageName();
if (packageName == null || packageName.trim().length() == 0)
return false;
try {
PackageManager pm = context.getPackageManager();
ApplicationInfo ai = pm.getApplicationInfo(context.getPackageName(), 0);
return ai != null && (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/utils/LogUtils.java
================================================
package com.senon.lib_common.utils;
import android.util.Log;
import java.util.Locale;
/**
* 打印log日志工具类
*/
public class LogUtils {
private static boolean LOG = true;
private static boolean LOGV = true;
private static boolean LOGD = true;
private static boolean LOGI = true;
private static boolean LOGW = true;
private static boolean LOGE = true;
public static void setLogEnable(boolean enable) {
LOG = enable;
}
public static void v(String mess) {
if (LOG && LOGV) {
Log.v(getTag(), buildMessage(mess));
}
}
public static void d(String mess) {
if (LOG && LOGD) {
Log.d(getTag(), buildMessage(mess));
}
}
public static void i(String mess) {
if (LOG && LOGI) {
Log.i(getTag(), buildMessage(mess));
}
}
public static void w(String mess) {
if (LOG && LOGW) {
Log.w(getTag(), buildMessage(mess));
}
}
public static void e(String mess) {
if (LOG && LOGE) {
log(getTag(), buildMessage(mess));
}
}
public static void log(String tag, String msg){
if(msg.length() > 4000) {
for(int i=0;i clazz = trace[i].getClass();
if (!clazz.equals(LogUtils.class)) {
callingClass = trace[i].getClassName();
callingClass = callingClass.substring(callingClass
.lastIndexOf('.') + 1);
break;
}
}
return callingClass;
}
private static String buildMessage(String msg) {
StackTraceElement[] trace = new Throwable().fillInStackTrace()
.getStackTrace();
String caller = "";
for (int i = 2; i < trace.length; i++) {
Class> clazz = trace[i].getClass();
if (!clazz.equals(LogUtils.class)) {
caller = trace[i].getMethodName();
break;
}
}
return String.format(Locale.US, "[%d] %s: %s", Thread.currentThread()
.getId(), caller, msg);
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/utils/MD5Utils.java
================================================
package com.senon.lib_common.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* MD5工具
*/
public class MD5Utils {
//静态方法,便于作为工具类
public static String getMd5(String plainText) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(plainText.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
//32位加密
return buf.toString();
// 16位的加密
//return buf.toString().substring(8, 24);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/utils/PreferenceTool.java
================================================
package com.senon.lib_common.utils;
import android.content.Context;
import android.content.SharedPreferences;
import com.senon.lib_opensource.BuildConfig;
import java.util.Map;
/**
* 共享参数工具类
*/
public class PreferenceTool {
private static final String PREF_NAME = BuildConfig.APPLICATION_ID + "_preferences";
private static SharedPreferences.Editor editor;
private static SharedPreferences pref;
public static void init(Context context) {
pref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
editor = pref.edit();
}
public static void clear() {
if (editor == null) return;
editor.clear();
}
public static void commit() {
if (editor == null) return;
editor.commit();
}
public static void apply() {
if (editor == null) return;
editor.apply();
}
public static boolean contains(String key) {
return pref != null && pref.contains(key);
}
public static float getFloat(String key, float defValue) {
return pref != null ? pref.getFloat(key, defValue) : defValue;
}
public static int getInt(String key, int defValue) {
return pref != null ? pref.getInt(key, defValue) : defValue;
}
public static long getLong(String key, long defValue) {
return pref != null ? pref.getLong(key, defValue) : defValue;
}
public static String getString(String key) {
return pref != null ? pref.getString(key, "") : "";
}
public static String getString(String key, String defValue) {
return pref != null ? pref.getString(key, defValue) : defValue;
}
public static boolean getBoolean(String key, boolean defValue) {
return pref != null ? pref.getBoolean(key, defValue) : defValue;
}
public static Map getAll() {
return pref != null ? pref.getAll() : null;
}
public static void putFloat(String key, float value) {
if (editor == null) return;
editor.putFloat(key, value);
}
public static void putInt(String key, int value) {
if (editor == null) return;
editor.putInt(key, value);
}
public static void putLong(String key, long value) {
if (editor == null) return;
editor.putLong(key, value);
}
public static void putString(String key, String value) {
if (editor == null) return;
editor.putString(key, value);
}
public static void putBoolean(String key, boolean value) {
if (editor == null) return;
editor.putBoolean(key, value);
}
public static void remove(String key) {
if (editor == null) return;
editor.remove(key);
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/utils/RetryWithDelay.java
================================================
package com.senon.lib_common.utils;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Function;
public class RetryWithDelay implements Function, ObservableSource>> {
private final int maxRetries;
private final int retryDelaySecond;
private int retryCount;
public RetryWithDelay(int maxRetries, int retryDelaySecond) {
this.maxRetries = maxRetries;
this.retryDelaySecond = retryDelaySecond;
}
@Override
public ObservableSource> apply(@NonNull Observable throwableObservable) throws Exception {
return throwableObservable
.flatMap(new Function>() {
@Override
public ObservableSource> apply(@NonNull Throwable throwable) throws Exception {
if (++retryCount <= maxRetries) {
// When this Observable calls onNext, the original Observable will be retried (i.e. re-subscribed).
LogUtils.d("get error, it will try after " + retryDelaySecond
+ " second, retry count " + retryCount);
return Observable.timer(retryDelaySecond,
TimeUnit.SECONDS);
}
// Max retries hit. Just pass the error along.
return Observable.error(throwable);
}
});
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/utils/RxUtils.java
================================================
package com.senon.lib_common.utils;
import com.senon.lib_common.base.BaseViewImp;
import com.trello.rxlifecycle2.LifecycleTransformer;
import com.trello.rxlifecycle2.android.ActivityEvent;
import com.trello.rxlifecycle2.android.FragmentEvent;
import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
import com.trello.rxlifecycle2.components.support.RxFragment;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.schedulers.Schedulers;
/**
* 在presenter中使用生命周期管理,防止内存泄漏
*/
public class RxUtils {
public static LifecycleTransformer bindToLifecycle(BaseViewImp view) {
if (view instanceof RxAppCompatActivity) {
return ((RxAppCompatActivity) view).bindToLifecycle();
} else if (view instanceof RxFragment) {
return ((RxFragment) view).bindToLifecycle();
} else {
throw new IllegalArgumentException("view isn't activity or fragment");
}
}
public static LifecycleTransformer bindActivityUntilEvent(BaseViewImp view,ActivityEvent event) {
if (view instanceof RxAppCompatActivity) {
return ((RxAppCompatActivity) view).bindUntilEvent(event);
} else {
throw new IllegalArgumentException("view isn't activity");
}
}
public static LifecycleTransformer bindFragmentUntilEvent(BaseViewImp view,FragmentEvent event) {
if (view instanceof RxFragment) {
return ((RxFragment) view).bindUntilEvent(event);
} else {
throw new IllegalArgumentException("view isn't fragment");
}
}
public static ObservableTransformer getSchedulerTransformer(){
return new ObservableTransformer() {
@Override
public ObservableSource apply(@NonNull Observable upstream) {
return upstream
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/utils/StatusBarUtils.java
================================================
package com.senon.lib_common.utils;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
/**
* 状态栏沉浸
*/
public class StatusBarUtils {
private Activity mActivity;
//状态栏颜色
private int mColor = -1;
//状态栏drawble
private Drawable mDrawable;
//是否是最外层布局是 DrawerLayout 的侧滑菜单
private boolean mIsDrawerLayout;
//是否包含 ActionBar
private boolean mIsActionBar;
//侧滑菜单页面的内容视图
private int mContentResourseIdInDrawer;
public StatusBarUtils(Activity activity) {
mActivity = activity;
}
public static StatusBarUtils with(Activity activity) {
return new StatusBarUtils(activity);
}
public int getColor() {
return mColor;
}
public StatusBarUtils setColor(int color) {
mColor = color;
return this;
}
public Drawable getDrawable() {
return mDrawable;
}
public StatusBarUtils setDrawable(Drawable drawable) {
mDrawable = drawable;
return this;
}
public boolean isDrawerLayout() {
return mIsDrawerLayout;
}
public boolean isActionBar() {
return mIsActionBar;
}
public StatusBarUtils setIsActionBar(boolean actionBar) {
mIsActionBar = actionBar;
return this;
}
/**
* 是否是最外层布局为 DrawerLayout 的侧滑菜单
*
* @param drawerLayout 是否最外层布局为 DrawerLayout
* @param contentId 内容视图的 id
* @return
*/
public StatusBarUtils setDrawerLayoutContentId(boolean drawerLayout, int contentId) {
mIsDrawerLayout = drawerLayout;
mContentResourseIdInDrawer = contentId;
return this;
}
public void init() {
fullScreen(mActivity);
if (mColor != -1) {
//设置了状态栏颜色
addStatusViewWithColor(mActivity, mColor);
}
if (mDrawable != null) {
//设置了状态栏 drawble,例如渐变色
addStatusViewWithDrawble(mActivity, mDrawable);
}
if (isDrawerLayout()) {
//未设置 fitsSystemWindows 且是侧滑菜单,需要设置 fitsSystemWindows 以解决 4.4 上侧滑菜单上方白条问题
fitsSystemWindows(mActivity);
}
if (isActionBar()) {
//要增加内容视图的 paddingTop,否则内容被 ActionBar 遮盖
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
ViewGroup rootView = (ViewGroup) mActivity.getWindow().getDecorView().findViewById(android.R.id.content);
rootView.setPadding(0, getStatusBarHeight(mActivity) + getActionBarHeight(mActivity), 0, 0);
}
}
}
/**
* 去除 ActionBar 阴影
*/
public StatusBarUtils clearActionBarShadow() {
if (Build.VERSION.SDK_INT >= 21) {
ActionBar supportActionBar = ((AppCompatActivity) mActivity).getSupportActionBar();
if (supportActionBar != null) {
supportActionBar.setElevation(0);
}
}
return this;
}
/**
* 设置页面最外层布局 FitsSystemWindows 属性
*
* @param activity
*/
private void fitsSystemWindows(Activity activity) {
ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
View parentView = contentFrameLayout.getChildAt(0);
if (parentView != null && Build.VERSION.SDK_INT >= 14) {
parentView.setFitsSystemWindows(true);
//布局预留状态栏高度的 padding
if (parentView instanceof DrawerLayout) {
DrawerLayout drawer = (DrawerLayout) parentView;
//将主页面顶部延伸至status bar;虽默认为false,但经测试,DrawerLayout需显示设置
drawer.setClipToPadding(false);
}
}
}
/**
* 利用反射获取状态栏高度
*
* @return
*/
public static int getStatusBarHeight(Activity activity) {
int result = 0;
//获取状态栏高度的资源id
int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = activity.getResources().getDimensionPixelSize(resourceId);
}
Log.e("getStatusBarHeight", result + "");
return result;
}
/**
* 获得 ActionBar 的高度
*
* @param context
* @return
*/
public static int getActionBarHeight(Context context) {
int result = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
TypedValue tv = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
}
return result;
}
/**
* 添加状态栏占位视图
*
* @param activity
*/
private void addStatusViewWithColor(Activity activity, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (isDrawerLayout()) {
//要在内容布局增加状态栏,否则会盖在侧滑菜单上
ViewGroup rootView = (ViewGroup) activity.findViewById(android.R.id.content);
//DrawerLayout 则需要在第一个子视图即内容试图中添加padding
View parentView = rootView.getChildAt(0);
LinearLayout linearLayout = new LinearLayout(activity);
linearLayout.setOrientation(LinearLayout.VERTICAL);
View statusBarView = new View(activity);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity));
statusBarView.setBackgroundColor(color);
//添加占位状态栏到线性布局中
linearLayout.addView(statusBarView, lp);
//侧滑菜单
DrawerLayout drawer = (DrawerLayout) parentView;
//内容视图
View content = activity.findViewById(mContentResourseIdInDrawer);
//将内容视图从 DrawerLayout 中移除
drawer.removeView(content);
//添加内容视图
linearLayout.addView(content, content.getLayoutParams());
//将带有占位状态栏的新的内容视图设置给 DrawerLayout
drawer.addView(linearLayout, 0);
} else {
//设置 paddingTop
ViewGroup rootView = (ViewGroup) mActivity.getWindow().getDecorView().findViewById(android.R.id.content);
rootView.setPadding(0, getStatusBarHeight(mActivity), 0, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//直接设置状态栏颜色
activity.getWindow().setStatusBarColor(color);
} else {
//增加占位状态栏
ViewGroup decorView = (ViewGroup) mActivity.getWindow().getDecorView();
View statusBarView = new View(activity);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity));
statusBarView.setBackgroundColor(color);
decorView.addView(statusBarView, lp);
}
}
}
}
/**
* 添加状态栏占位视图
*
* @param activity
*/
private void addStatusViewWithDrawble(Activity activity, Drawable drawable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//占位状态栏
View statusBarView = new View(activity);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
statusBarView.setBackground(drawable);
} else {
statusBarView.setBackgroundDrawable(drawable);
}
if (isDrawerLayout()) {
//要在内容布局增加状态栏,否则会盖在侧滑菜单上
ViewGroup rootView = (ViewGroup) activity.findViewById(android.R.id.content);
//DrawerLayout 则需要在第一个子视图即内容试图中添加padding
View parentView = rootView.getChildAt(0);
LinearLayout linearLayout = new LinearLayout(activity);
linearLayout.setOrientation(LinearLayout.VERTICAL);
//添加占位状态栏到线性布局中
linearLayout.addView(statusBarView, lp);
//侧滑菜单
DrawerLayout drawer = (DrawerLayout) parentView;
//内容视图
View content = activity.findViewById(mContentResourseIdInDrawer);
//将内容视图从 DrawerLayout 中移除
drawer.removeView(content);
//添加内容视图
linearLayout.addView(content, content.getLayoutParams());
//将带有占位状态栏的新的内容视图设置给 DrawerLayout
drawer.addView(linearLayout, 0);
} else {
//增加占位状态栏,并增加状态栏高度的 paddingTop
ViewGroup decorView = (ViewGroup) mActivity.getWindow().getDecorView();
decorView.addView(statusBarView, lp);
//设置 paddingTop
ViewGroup rootView = (ViewGroup) mActivity.getWindow().getDecorView().findViewById(android.R.id.content);
rootView.setPadding(0, getStatusBarHeight(mActivity), 0, 0);
}
}
}
/**
* 通过设置全屏,设置状态栏透明
*
* @param activity
*/
private void fullScreen(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色
Window window = activity.getWindow();
View decorView = window.getDecorView();
//两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
decorView.setSystemUiVisibility(option);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
//导航栏颜色也可以正常设置
// window.setNavigationBarColor(Color.TRANSPARENT);
} else {
Window window = activity.getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
attributes.flags |= flagTranslucentStatus;
// attributes.flags |= flagTranslucentNavigation;
window.setAttributes(attributes);
}
}
}
/**
* 通过设置全屏,设置状态栏透明 导航栏黑色
*
* @param activity
*/
public static void setStatusTransparent(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
// attributes.flags |= flagTranslucentStatus;
attributes.flags |= flagTranslucentNavigation;
window.setAttributes(attributes);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
window.setNavigationBarColor(Color.TRANSPARENT);
} else {
Window window = activity.getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
attributes.flags |= flagTranslucentStatus;
attributes.flags |= flagTranslucentNavigation;
window.setAttributes(attributes);
}
}
}
}
================================================
FILE: lib_common/src/main/java/com/senon/lib_common/utils/ToastUtil.java
================================================
package com.senon.lib_common.utils;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentActivity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.senon.lib_common.R;
/**
* Toast工具类
*/
public class ToastUtil {
/**
* 可以在多线程里运行的toast
*/
private static volatile Toast mToast;
private static final Object lock = new Object();
private static Context context;
private static TextView toastTv;
public static void init(Context con){
context = con;
}
public static void initToast(String msg) {
initToast(msg, context, true);
}
public static void initToast(int resId, Context context) {
if (context instanceof Activity || context instanceof FragmentActivity)
context = context.getApplicationContext();
initToast(context.getString(resId), context, true);
}
public static void initToast(String msg, Context context, boolean isSingleton) {
if (context instanceof Activity || context instanceof FragmentActivity)
context = context.getApplicationContext();
if (mToast != null && isSingleton) {
toastTv.setText(msg);
} else {
synchronized (lock) {
// mToast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);
mToast = showToast(context,msg,Toast.LENGTH_SHORT);
}
}
mToast.setGravity(Gravity.CENTER, 0, 0);//默认显示位置
mToast.show();
}
//可以设置toast的位置
public static void setGravity(int gravity, int xOffset, int yOffset) {
mToast.setGravity(gravity, xOffset, yOffset);
}
//可以自定义toast的view
public void setView(View view) {
mToast.setView(view);
}
/**
当你在线程中使用toast时,请使用这个方法(可以控制显示多长时间)
*/
public static void showInThread(@NonNull final Context context, final String msg, final int length) {
new Thread() {
@Override
public void run() {
Looper.prepare();//先移除
Toast.makeText(context, msg, length).show();
Looper.loop();// 进入loop中的循环,查看消息队列
}
}.start();
}
/**
* 以下全部代码为一个整体,可以控制显示时间的Toast
*/
private static Handler mHandler = null;
private static int duration = 0;
private static int currDuration = 0;
private static final int DEFAULT = 2000;
public static void showByDuration(Context context, String msg, int duration) {
duration = duration;
currDuration = DEFAULT;
// mToast = Toast.makeText(context, msg, Toast.LENGTH_LONG);
mToast = showToast(context,msg,Toast.LENGTH_LONG);
mHandler = new Handler(context.getMainLooper());
mHandler.post(mToastThread);
}
private static Runnable mToastThread = new Runnable() {
public void run() {
mToast.show();
mHandler.postDelayed(mToastThread, DEFAULT);// 每隔2秒显示一次
if (duration != 0) {
if (currDuration <= duration) {
currDuration += DEFAULT;
} else {
cancel();
}
}
}
};
private static void cancel() {
mHandler.removeCallbacks(mToastThread);// 先把显示线程删除
mToast.cancel();// 把最后一个线程的显示效果cancel掉,就一了百了了
currDuration = DEFAULT;
}
private static Toast showToast(Context context, String msg, int duration) {
if (null != context) {
if (mToast == null) {
mToast = new Toast(context);
LayoutInflater inflater = LayoutInflater.from(context);
View layout = inflater.inflate(R.layout.toast_layout, null);
toastTv = layout.findViewById(R.id.message);
toastTv.setText(msg);
mToast.setDuration(duration);
mToast.setView(layout);
}else {
toastTv.setText(msg);
}
}
return mToast;
}
}
================================================
FILE: lib_common/src/main/res/drawable/register_border.xml
================================================
================================================
FILE: lib_common/src/main/res/drawable/register_border_2.xml
================================================
================================================
FILE: lib_common/src/main/res/drawable/register_border_9.xml
================================================
================================================
FILE: lib_common/src/main/res/drawable/shape_gradient.xml
================================================
================================================
FILE: lib_common/src/main/res/drawable/style_progress_bar.xml
================================================
-
-
-
================================================
FILE: lib_common/src/main/res/drawable/toast_shape.xml
================================================
================================================
FILE: lib_common/src/main/res/layout/activity_common__login.xml
================================================
================================================
FILE: lib_common/src/main/res/layout/activity_common__register.xml
================================================
================================================
FILE: lib_common/src/main/res/layout/activity_common__webview.xml
================================================
================================================
FILE: lib_common/src/main/res/layout/layout_fragmhome_tab.xml
================================================
================================================
FILE: lib_common/src/main/res/layout/layout_toolbar.xml
================================================
================================================
FILE: lib_common/src/main/res/layout/toast_layout.xml
================================================
================================================
FILE: lib_common/src/main/res/values/colors.xml
================================================
#3F51B5
#303F9F
#FF4081
#2BBBE6
#00ffffff
#282828
#666666
#FFFFFF
#FF7219
#80000000
#99000000
#dd000000
#ff000000
#BDBDBD
#F0F0F0
#cccccc
#dddddd
#5e5656
#f2f2f2
#FF8519
#EA5038
#FF8519
#999999
#B3B3B3
#FF8519
#303030
#a53c3c
#5e99ff
#f1f0f6
#9b9b9b
#5f93fb
#aeb0b4
#777777
#999999
#aaaaaa
#F5F5F5
#ffcc3131
#232323
#EA5038
#1086C2
#f9f8f2
#e19917
================================================
FILE: lib_common/src/main/res/values/dimens.xml
================================================
-10mm
-20mm
0.5mm
1.0mm
2.0mm
3.0mm
4.0mm
5.0mm
6.0mm
7.0mm
8.0mm
9.0mm
10.0mm
11.0mm
12.0mm
13.0mm
14.0mm
15.0mm
16.0mm
17.0mm
18.0mm
19.0mm
20.0mm
21.0mm
22.0mm
23.0mm
24.0mm
25.0mm
26.0mm
27.0mm
28.0mm
29.0mm
30.0mm
31.0mm
32.0mm
33.0mm
34.0mm
35.0mm
36.0mm
37.0mm
38.0mm
39.0mm
40.0mm
41.0mm
42.0mm
43.0mm
44.0mm
45.0mm
46.0mm
47.0mm
48.0mm
49.0mm
50.0mm
51.0mm
52.0mm
53.0mm
54.0mm
55.0mm
56.0mm
57.0mm
58.0mm
59.0mm
60.0mm
61.0mm
62.0mm
63.0mm
64.0mm
65.0mm
66.0mm
67.0mm
68.0mm
69.0mm
70.0mm
71.0mm
72.0mm
73.0mm
74.0mm
75.0mm
76.0mm
77.0mm
78.0mm
79.0mm
80.0mm
81.0mm
82.0mm
83.0mm
84.0mm
85.0mm
86.0mm
87.0mm
88.0mm
89.0mm
90.0mm
91.0mm
92.0mm
93.0mm
94.0mm
95.0mm
96.0mm
97.0mm
98.0mm
99.0mm
100.0mm
101.0mm
102.0mm
103.0mm
104.0mm
105.0mm
106.0mm
107.0mm
108.0mm
109.0mm
110.0mm
111.0mm
112.0mm
113.0mm
114.0mm
115.0mm
116.0mm
117.0mm
118.0mm
119.0mm
120.0mm
121.0mm
122.0mm
123.0mm
124.0mm
125.0mm
126.0mm
127.0mm
128.0mm
129.0mm
130.0mm
131.0mm
132.0mm
133.0mm
134.0mm
135.0mm
136.0mm
137.0mm
138.0mm
139.0mm
140.0mm
141.0mm
142.0mm
143.0mm
144.0mm
145.0mm
146.0mm
147.0mm
148.0mm
149.0mm
150.0mm
151.0mm
152.0mm
153.0mm
154.0mm
155.0mm
156.0mm
157.0mm
158.0mm
159.0mm
160.0mm
161.0mm
162.0mm
163.0mm
164.0mm
165.0mm
166.0mm
167.0mm
168.0mm
169.0mm
170.0mm
171.0mm
172.0mm
173.0mm
174.0mm
175.0mm
176.0mm
177.0mm
178.0mm
179.0mm
180.0mm
181.0mm
182.0mm
183.0mm
184.0mm
185.0mm
186.0mm
187.0mm
188.0mm
189.0mm
190.0mm
191.0mm
192.0mm
193.0mm
194.0mm
195.0mm
196.0mm
197.0mm
198.0mm
199.0mm
200.0mm
201.0mm
202.0mm
203.0mm
204.0mm
205.0mm
206.0mm
207.0mm
208.0mm
209.0mm
210.0mm
211.0mm
212.0mm
213.0mm
214.0mm
215.0mm
216.0mm
217.0mm
218.0mm
219.0mm
220.0mm
221.0mm
222.0mm
223.0mm
224.0mm
225.0mm
226.0mm
227.0mm
228.0mm
229.0mm
230.0mm
231.0mm
232.0mm
233.0mm
234.0mm
235.0mm
236.0mm
237.0mm
238.0mm
239.0mm
240.0mm
241.0mm
242.0mm
243.0mm
244.0mm
245.0mm
246.0mm
247.0mm
248.0mm
249.0mm
250.0mm
251.0mm
252.0mm
253.0mm
254.0mm
255.0mm
256.0mm
257.0mm
258.0mm
259.0mm
260.0mm
261.0mm
262.0mm
263.0mm
264.0mm
265.0mm
266.0mm
267.0mm
268.0mm
269.0mm
270.0mm
271.0mm
272.0mm
273.0mm
274.0mm
275.0mm
276.0mm
277.0mm
278.0mm
279.0mm
280.0mm
281.0mm
282.0mm
283.0mm
284.0mm
285.0mm
286.0mm
287.0mm
288.0mm
289.0mm
290.0mm
291.0mm
292.0mm
293.0mm
294.0mm
295.0mm
296.0mm
297.0mm
298.0mm
299.0mm
300.0mm
301.0mm
302.0mm
303.0mm
304.0mm
305.0mm
306.0mm
307.0mm
308.0mm
309.0mm
310.0mm
311.0mm
312.0mm
313.0mm
314.0mm
315.0mm
316.0mm
317.0mm
318.0mm
319.0mm
320.0mm
321.0mm
322.0mm
323.0mm
324.0mm
325.0mm
326.0mm
327.0mm
328.0mm
329.0mm
330.0mm
331.0mm
332.0mm
333.0mm
334.0mm
335.0mm
336.0mm
337.0mm
338.0mm
339.0mm
340.0mm
341.0mm
342.0mm
343.0mm
344.0mm
345.0mm
346.0mm
347.0mm
348.0mm
349.0mm
350.0mm
351.0mm
352.0mm
353.0mm
354.0mm
355.0mm
356.0mm
357.0mm
358.0mm
359.0mm
360.0mm
361.0mm
362.0mm
363.0mm
364.0mm
365.0mm
366.0mm
367.0mm
368.0mm
369.0mm
370.0mm
371.0mm
372.0mm
373.0mm
374.0mm
375.0mm
376.0mm
377.0mm
378.0mm
379.0mm
380.0mm
381.0mm
382.0mm
383.0mm
384.0mm
385.0mm
386.0mm
387.0mm
388.0mm
389.0mm
390.0mm
391.0mm
392.0mm
393.0mm
394.0mm
395.0mm
396.0mm
397.0mm
398.0mm
399.0mm
400.0mm
401.0mm
402.0mm
403.0mm
404.0mm
405.0mm
406.0mm
407.0mm
408.0mm
409.0mm
410.0mm
411.0mm
412.0mm
413.0mm
414.0mm
415.0mm
416.0mm
417.0mm
418.0mm
419.0mm
420.0mm
421.0mm
422.0mm
423.0mm
424.0mm
425.0mm
426.0mm
427.0mm
428.0mm
429.0mm
430.0mm
431.0mm
432.0mm
433.0mm
434.0mm
435.0mm
436.0mm
437.0mm
438.0mm
439.0mm
440.0mm
441.0mm
442.0mm
443.0mm
444.0mm
445.0mm
446.0mm
447.0mm
448.0mm
449.0mm
450.0mm
451.0mm
452.0mm
453.0mm
454.0mm
455.0mm
456.0mm
457.0mm
458.0mm
459.0mm
460.0mm
461.0mm
462.0mm
463.0mm
464.0mm
465.0mm
466.0mm
467.0mm
468.0mm
469.0mm
470.0mm
471.0mm
472.0mm
473.0mm
474.0mm
475.0mm
476.0mm
477.0mm
478.0mm
479.0mm
480.0mm
481.0mm
482.0mm
483.0mm
484.0mm
485.0mm
486.0mm
487.0mm
488.0mm
489.0mm
490.0mm
491.0mm
492.0mm
493.0mm
494.0mm
495.0mm
496.0mm
497.0mm
498.0mm
499.0mm
500.0mm
501.0mm
502.0mm
503.0mm
504.0mm
505.0mm
506.0mm
507.0mm
508.0mm
509.0mm
510.0mm
511.0mm
512.0mm
513.0mm
514.0mm
515.0mm
516.0mm
517.0mm
518.0mm
519.0mm
520.0mm
521.0mm
522.0mm
523.0mm
524.0mm
525.0mm
526.0mm
527.0mm
528.0mm
529.0mm
530.0mm
531.0mm
532.0mm
533.0mm
534.0mm
535.0mm
536.0mm
537.0mm
538.0mm
539.0mm
540.0mm
541.0mm
542.0mm
543.0mm
544.0mm
545.0mm
546.0mm
547.0mm
548.0mm
549.0mm
550.0mm
551.0mm
552.0mm
553.0mm
554.0mm
555.0mm
556.0mm
557.0mm
558.0mm
559.0mm
560.0mm
561.0mm
562.0mm
563.0mm
564.0mm
565.0mm
566.0mm
567.0mm
568.0mm
569.0mm
570.0mm
571.0mm
572.0mm
573.0mm
574.0mm
575.0mm
576.0mm
577.0mm
578.0mm
579.0mm
580.0mm
581.0mm
582.0mm
583.0mm
584.0mm
585.0mm
586.0mm
587.0mm
588.0mm
589.0mm
590.0mm
591.0mm
592.0mm
593.0mm
594.0mm
595.0mm
596.0mm
597.0mm
598.0mm
599.0mm
600.0mm
601.0mm
602.0mm
603.0mm
604.0mm
605.0mm
606.0mm
607.0mm
608.0mm
609.0mm
610.0mm
611.0mm
612.0mm
613.0mm
614.0mm
615.0mm
616.0mm
617.0mm
618.0mm
619.0mm
620.0mm
621.0mm
622.0mm
623.0mm
624.0mm
625.0mm
626.0mm
627.0mm
628.0mm
629.0mm
630.0mm
631.0mm
632.0mm
633.0mm
634.0mm
635.0mm
636.0mm
637.0mm
638.0mm
639.0mm
640.0mm
641.0mm
642.0mm
643.0mm
644.0mm
645.0mm
646.0mm
647.0mm
648.0mm
649.0mm
650.0mm
651.0mm
652.0mm
653.0mm
654.0mm
655.0mm
656.0mm
657.0mm
658.0mm
659.0mm
660.0mm
661.0mm
662.0mm
663.0mm
664.0mm
665.0mm
666.0mm
667.0mm
668.0mm
669.0mm
670.0mm
671.0mm
672.0mm
673.0mm
674.0mm
675.0mm
676.0mm
677.0mm
678.0mm
679.0mm
680.0mm
681.0mm
682.0mm
683.0mm
684.0mm
685.0mm
686.0mm
687.0mm
688.0mm
689.0mm
690.0mm
691.0mm
692.0mm
693.0mm
694.0mm
695.0mm
696.0mm
697.0mm
698.0mm
699.0mm
700.0mm
701.0mm
702.0mm
703.0mm
704.0mm
705.0mm
706.0mm
707.0mm
708.0mm
709.0mm
710.0mm
711.0mm
712.0mm
713.0mm
714.0mm
715.0mm
716.0mm
717.0mm
718.0mm
719.0mm
720.0mm
721.0mm
722.0mm
723.0mm
724.0mm
725.0mm
726.0mm
727.0mm
728.0mm
729.0mm
730.0mm
731.0mm
732.0mm
733.0mm
734.0mm
735.0mm
736.0mm
737.0mm
738.0mm
739.0mm
740.0mm
741.0mm
742.0mm
743.0mm
744.0mm
745.0mm
746.0mm
747.0mm
748.0mm
749.0mm
750.0mm
751.0mm
752.0mm
753.0mm
754.0mm
755.0mm
756.0mm
757.0mm
758.0mm
759.0mm
760.0mm
761.0mm
762.0mm
763.0mm
764.0mm
765.0mm
766.0mm
767.0mm
768.0mm
769.0mm
770.0mm
771.0mm
772.0mm
773.0mm
774.0mm
775.0mm
776.0mm
777.0mm
778.0mm
779.0mm
780.0mm
781.0mm
782.0mm
783.0mm
784.0mm
785.0mm
786.0mm
787.0mm
788.0mm
789.0mm
790.0mm
791.0mm
792.0mm
793.0mm
794.0mm
795.0mm
796.0mm
797.0mm
798.0mm
799.0mm
800.0mm
801.0mm
802.0mm
803.0mm
804.0mm
805.0mm
806.0mm
807.0mm
808.0mm
809.0mm
810.0mm
811.0mm
812.0mm
813.0mm
814.0mm
815.0mm
816.0mm
817.0mm
818.0mm
819.0mm
820.0mm
821.0mm
822.0mm
823.0mm
824.0mm
825.0mm
826.0mm
827.0mm
828.0mm
829.0mm
830.0mm
831.0mm
832.0mm
833.0mm
834.0mm
835.0mm
836.0mm
837.0mm
838.0mm
839.0mm
840.0mm
841.0mm
842.0mm
843.0mm
844.0mm
845.0mm
846.0mm
847.0mm
848.0mm
849.0mm
850.0mm
851.0mm
852.0mm
853.0mm
854.0mm
855.0mm
856.0mm
857.0mm
858.0mm
859.0mm
860.0mm
861.0mm
862.0mm
863.0mm
864.0mm
865.0mm
866.0mm
867.0mm
868.0mm
869.0mm
870.0mm
871.0mm
872.0mm
873.0mm
874.0mm
875.0mm
876.0mm
877.0mm
878.0mm
879.0mm
880.0mm
881.0mm
882.0mm
883.0mm
884.0mm
885.0mm
886.0mm
887.0mm
888.0mm
889.0mm
890.0mm
891.0mm
892.0mm
893.0mm
894.0mm
895.0mm
896.0mm
897.0mm
898.0mm
899.0mm
900.0mm
901.0mm
902.0mm
903.0mm
904.0mm
905.0mm
906.0mm
907.0mm
908.0mm
909.0mm
910.0mm
911.0mm
912.0mm
913.0mm
914.0mm
915.0mm
916.0mm
917.0mm
918.0mm
919.0mm
920.0mm
921.0mm
922.0mm
923.0mm
924.0mm
925.0mm
926.0mm
927.0mm
928.0mm
929.0mm
930.0mm
931.0mm
932.0mm
933.0mm
934.0mm
935.0mm
936.0mm
937.0mm
938.0mm
939.0mm
940.0mm
941.0mm
942.0mm
943.0mm
944.0mm
945.0mm
946.0mm
947.0mm
948.0mm
949.0mm
950.0mm
951.0mm
952.0mm
953.0mm
954.0mm
955.0mm
956.0mm
957.0mm
958.0mm
959.0mm
960.0mm
961.0mm
962.0mm
963.0mm
964.0mm
965.0mm
966.0mm
967.0mm
968.0mm
969.0mm
970.0mm
971.0mm
972.0mm
973.0mm
974.0mm
975.0mm
976.0mm
977.0mm
978.0mm
979.0mm
980.0mm
981.0mm
982.0mm
983.0mm
984.0mm
985.0mm
986.0mm
987.0mm
988.0mm
989.0mm
990.0mm
991.0mm
992.0mm
993.0mm
994.0mm
995.0mm
996.0mm
997.0mm
998.0mm
999.0mm
1000.0mm
1001.0mm
1002.0mm
1003.0mm
1004.0mm
1005.0mm
1006.0mm
1007.0mm
1008.0mm
1009.0mm
1010.0mm
1011.0mm
1012.0mm
1013.0mm
1014.0mm
1015.0mm
1016.0mm
1017.0mm
1018.0mm
1019.0mm
1020.0mm
1021.0mm
1022.0mm
1023.0mm
1024.0mm
1025.0mm
1026.0mm
1027.0mm
1028.0mm
1029.0mm
1030.0mm
1031.0mm
1032.0mm
1033.0mm
1034.0mm
1035.0mm
1036.0mm
1037.0mm
1038.0mm
1039.0mm
1040.0mm
1041.0mm
1042.0mm
1043.0mm
1044.0mm
1045.0mm
1046.0mm
1047.0mm
1048.0mm
1049.0mm
1050.0mm
1051.0mm
1052.0mm
1053.0mm
1054.0mm
1055.0mm
1056.0mm
1057.0mm
1058.0mm
1059.0mm
1060.0mm
1061.0mm
1062.0mm
1063.0mm
1064.0mm
1065.0mm
1066.0mm
1067.0mm
1068.0mm
1069.0mm
1070.0mm
1071.0mm
1072.0mm
1073.0mm
1074.0mm
1075.0mm
1076.0mm
1077.0mm
1078.0mm
1079.0mm
1080.0mm
1081.0mm
1082.0mm
1083.0mm
1084.0mm
1085.0mm
1086.0mm
1087.0mm
1088.0mm
1089.0mm
1090.0mm
1091.0mm
1092.0mm
1093.0mm
1094.0mm
1095.0mm
1096.0mm
1097.0mm
1098.0mm
1099.0mm
1100.0mm
1101.0mm
1102.0mm
1103.0mm
1104.0mm
1105.0mm
1106.0mm
1107.0mm
1108.0mm
1109.0mm
1110.0mm
1111.0mm
1112.0mm
1113.0mm
1114.0mm
1115.0mm
1116.0mm
1117.0mm
1118.0mm
1119.0mm
1120.0mm
1121.0mm
1122.0mm
1123.0mm
1124.0mm
1125.0mm
1126.0mm
1127.0mm
1128.0mm
1129.0mm
1130.0mm
1131.0mm
1132.0mm
1133.0mm
1134.0mm
1135.0mm
1136.0mm
1137.0mm
1138.0mm
1139.0mm
1140.0mm
1141.0mm
1142.0mm
1143.0mm
1144.0mm
1145.0mm
1146.0mm
1147.0mm
1148.0mm
1149.0mm
1150.0mm
1151.0mm
1152.0mm
1153.0mm
1154.0mm
1155.0mm
1156.0mm
1157.0mm
1158.0mm
1159.0mm
1160.0mm
1161.0mm
1162.0mm
1163.0mm
1164.0mm
1165.0mm
1166.0mm
1167.0mm
1168.0mm
1169.0mm
1170.0mm
1171.0mm
1172.0mm
1173.0mm
1174.0mm
1175.0mm
1176.0mm
1177.0mm
1178.0mm
1179.0mm
1180.0mm
1181.0mm
1182.0mm
1183.0mm
1184.0mm
1185.0mm
1186.0mm
1187.0mm
1188.0mm
1189.0mm
1190.0mm
1191.0mm
1192.0mm
1193.0mm
1194.0mm
1195.0mm
1196.0mm
1197.0mm
1198.0mm
1199.0mm
1200.0mm
1201.0mm
1202.0mm
1203.0mm
1204.0mm
1205.0mm
1206.0mm
1207.0mm
1208.0mm
1209.0mm
1210.0mm
1211.0mm
1212.0mm
1213.0mm
1214.0mm
1215.0mm
1216.0mm
1217.0mm
1218.0mm
1219.0mm
1220.0mm
1221.0mm
1222.0mm
1223.0mm
1224.0mm
1225.0mm
1226.0mm
1227.0mm
1228.0mm
1229.0mm
1230.0mm
1231.0mm
1232.0mm
1233.0mm
1234.0mm
1235.0mm
1236.0mm
1237.0mm
1238.0mm
1239.0mm
1240.0mm
1241.0mm
1242.0mm
1243.0mm
1244.0mm
1245.0mm
1246.0mm
1247.0mm
1248.0mm
1249.0mm
1250.0mm
1251.0mm
1252.0mm
1253.0mm
1254.0mm
1255.0mm
1256.0mm
1257.0mm
1258.0mm
1259.0mm
1260.0mm
1261.0mm
1262.0mm
1263.0mm
1264.0mm
1265.0mm
1266.0mm
1267.0mm
1268.0mm
1269.0mm
1270.0mm
1271.0mm
1272.0mm
1273.0mm
1274.0mm
1275.0mm
1276.0mm
1277.0mm
1278.0mm
1279.0mm
1280.0mm
1281.0mm
1282.0mm
1283.0mm
1284.0mm
1285.0mm
1286.0mm
1287.0mm
1288.0mm
1289.0mm
1290.0mm
1291.0mm
1292.0mm
1293.0mm
1294.0mm
1295.0mm
1296.0mm
1297.0mm
1298.0mm
1299.0mm
1300.0mm
1301.0mm
1302.0mm
1303.0mm
1304.0mm
1305.0mm
1306.0mm
1307.0mm
1308.0mm
1309.0mm
1310.0mm
1311.0mm
1312.0mm
1313.0mm
1314.0mm
1315.0mm
1316.0mm
1317.0mm
1318.0mm
1319.0mm
1320.0mm
1321.0mm
1322.0mm
1323.0mm
1324.0mm
1325.0mm
1326.0mm
1327.0mm
1328.0mm
1329.0mm
1330.0mm
1331.0mm
1332.0mm
1333.0mm
1334mm
================================================
FILE: lib_common/src/main/res/values/strings.xml
================================================
lib_common
================================================
FILE: lib_common/src/main/res/values/styles.xml
================================================
================================================
FILE: lib_common/src/test/java/com/senon/lib_common/ExampleUnitTest.java
================================================
package com.senon.lib_common;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see Testing documentation
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
================================================
FILE: lib_opensource/.gitignore
================================================
/build
================================================
FILE: lib_opensource/build.gradle
================================================
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.android["compileSdkVersion"]
defaultConfig {
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
versionCode rootProject.ext.android["versionCode"]
versionName rootProject.ext.android["versionName"]
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation rootProject.ext.dependencies["junit"]
api rootProject.ext.dependencies["support-v4"]
api rootProject.ext.dependencies["appcompat-v7"]
api rootProject.ext.dependencies["design"]
api rootProject.ext.dependencies["recyclerview-v7"]
api rootProject.ext.dependencies["cardview-v7"]
api rootProject.ext.dependencies["rxandroid"]
api rootProject.ext.dependencies["retrofit"]
api rootProject.ext.dependencies["rxlifecycle"]
api rootProject.ext.dependencies["rxlifecycle-components"]
api rootProject.ext.dependencies["adapter-rxjava"]
api rootProject.ext.dependencies["retrofit-converter"]
api rootProject.ext.dependencies["retrofit-converter-gson"]
api rootProject.ext.dependencies["stetho"]
api rootProject.ext.dependencies["stetho-okhttp3"]
api rootProject.ext.dependencies["okhttp3"]
api rootProject.ext.dependencies["okhttp3-logging-interceptor"]
api rootProject.ext.dependencies["router"]
api rootProject.ext.dependencies["sweetalert"]
api rootProject.ext.dependencies["autosize"]
api (rootProject.ext.dependencies["lrecyclerview"]) {
exclude group: 'com.android.support'
}
api rootProject.ext.dependencies["smartrefreshlayout"]
api rootProject.ext.dependencies["glide"]
api rootProject.ext.dependencies["eventbus"]
api rootProject.ext.dependencies["circleimageview"]
}
================================================
FILE: lib_opensource/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: lib_opensource/src/androidTest/java/com/senon/lib_opensource/ExampleInstrumentedTest.java
================================================
package com.senon.lib_opensource;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see Testing documentation
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.senon.lib_opensource", appContext.getPackageName());
}
}
================================================
FILE: lib_opensource/src/main/AndroidManifest.xml
================================================
================================================
FILE: lib_opensource/src/test/java/com/senon/lib_opensource/ExampleUnitTest.java
================================================
package com.senon.lib_opensource;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see Testing documentation
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
================================================
FILE: module_art/.gitignore
================================================
/build
================================================
FILE: module_art/build.gradle
================================================
if(isBuildModule.toBoolean()){
apply plugin: 'com.android.application'
}else{
apply plugin: 'com.android.library'
}
android {
compileSdkVersion rootProject.ext.android["compileSdkVersion"]
resourcePrefix "art_"
sourceSets {
main {
if (isBuildModule.toBoolean()) {
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/release/AndroidManifest.xml'
java{
//全部Module一起编译的时候剔除debug目录
exclude '**/**/debug/**'
}
}
}
}
defaultConfig {
if(isBuildModule.toBoolean()){
applicationId "com.senon.module_art"
}
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
versionCode rootProject.ext.android["versionCode"]
versionName rootProject.ext.android["versionName"]
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
testImplementation rootProject.ext.dependencies["junit"]
api project(':lib_common')
annotationProcessor rootProject.ext.dependencies["router-compiler"]
}
================================================
FILE: module_art/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: module_art/src/androidTest/java/com/senon/module_art/ExampleInstrumentedTest.java
================================================
package com.senon.module_art;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see Testing documentation
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.senon.module_art", appContext.getPackageName());
}
}
================================================
FILE: module_art/src/main/debug/AndroidManifest.xml
================================================
================================================
FILE: module_art/src/main/java/com/senon/module_art/App_Art.java
================================================
package com.senon.module_art;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.base.BaseApplication;
import com.senon.lib_common.utils.ConstantUtils;
/**
* art debug Application
*/
public class App_Art extends BaseApplication {
@Override
public void onCreate() {
super.onCreate();
initARouter();
}
private void initARouter() {
if (ConstantUtils.isAppDebug()) {
//开启InstantRun之后,一定要在ARouter.init之前调用openDebug
ARouter.openDebug();
ARouter.openLog();
}
ARouter.init(this);
}
}
================================================
FILE: module_art/src/main/java/com/senon/module_art/MainActivity.java
================================================
package com.senon.module_art;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.ConstantLoginArouter;
import com.senon.lib_common.utils.ConstantUtils;
import com.senon.lib_common.utils.LogUtils;
import com.senon.lib_common.utils.StatusBarUtils;
import com.senon.module_art.fragment.ArtMainFragment;
/**
* 公众号 art fragment
*/
@Route(path = ConstantLoginArouter.PATH_ART_MAINACTIVITY)
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
private FragmentManager fragmentManager;//声明fragment管理
private ArtMainFragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StatusBarUtils.with(this).init();
setContentView(R.layout.art_activity_main);
ComUtil.changeStatusBarTextColor(this,true);
ARouter.getInstance().inject(this);
LogUtils.e("------->isAppDebug===== "+ ConstantUtils.isAppDebug());
findView();
}
private void findView() {
viewPager = findViewById(R.id.art_main_vp);
fragmentManager = getSupportFragmentManager();
fragment = new ArtMainFragment();
viewPager.setAdapter(new MyFragmentPagerAdapter(fragmentManager));
}
//FragmentPagerAdapter
class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return fragment;
}
@Override
public int getCount() {
return 1;
}
}
}
================================================
FILE: module_art/src/main/java/com/senon/module_art/SplashActivity.java
================================================
package com.senon.module_art;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.ConstantLoginArouter;
public class SplashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.art_activity_splash);
findViewById(R.id.art_main_login_tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String curUrl = ConstantLoginArouter.PATH_ART_MAINACTIVITY;
ARouter.getInstance().build(ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)
.withString("targetUrl",curUrl)
.navigation();
}
});
}
}
================================================
FILE: module_art/src/main/java/com/senon/module_art/adapter/ArtMainAdapter.java
================================================
package com.senon.module_art.adapter;
import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.adapter.RecycleHolder;
import com.senon.lib_common.adapter.RecyclerAdapter;
import com.senon.lib_common.bean.WXarticle;
import com.senon.lib_common.bean.WXchapters;
import com.senon.module_art.R;
import com.senon.module_art.fragment.ArtMainFragment;
import java.util.ArrayList;
import java.util.List;
/**
* art主界面--列表Recycleview适配器
*/
public class ArtMainAdapter extends RecyclerView.Adapter implements View.OnClickListener {
private int ITEM_ONE = 2;
private int ITEM_HEAD = 1;
private int headViewCount = 1;
private OnItemClickListener onItemClickListener;
private Context mContext;
private List chapters = new ArrayList<>();//公众号列表
private List articles = new ArrayList<>();//公众号文章
private int id = ArtMainFragment.ID;
private boolean refreshHead = true;
public void notifyDataChanged() {
notifyDataSetChanged();
}
//设置公众号文章
public void setArticleDatas(List datas) {
if (datas != null) {
this.articles.clear();
this.articles.addAll(datas);
notifyDataChanged();
}
}
//设置公众号列表
public void setChaptersDatas(List datas,int id) {
if (datas != null) {
this.chapters.clear();
this.chapters.addAll(datas);
this.id = id;
notifyDataChanged();
}
}
public ArtMainAdapter(Context context) {
mContext = context;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ITEM_HEAD) {
View view = LayoutInflater.from(mContext).inflate(R.layout.art_adapter_artmain_fragment_head, parent, false);
return new HeaderViewHolder(view);
} else if (viewType == ITEM_ONE) {
View view = LayoutInflater.from(mContext).inflate(R.layout.art_adapter_artmain_fragment_article, parent, false);
return new OneViewHolder(view);
}
return null;
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int mPosition) {
if (holder instanceof HeaderViewHolder) {
if(chapters.size() > 0 && refreshHead){
refreshHead = false;
((HeaderViewHolder) holder).lrv.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
((HeaderViewHolder) holder).adapter = new RecyclerAdapter(mContext, chapters, R.layout.art_adapter_artmain_fragment_head_item) {
@Override
public void convert(final RecycleHolder helper, final WXchapters item, final int position) {
helper.setText(R.id.tv,item.getName());
if(item.getId() == id){
helper.setBackgroundRes(R.id.tv,R.drawable.art_shape_yellow_con20);
}else{
helper.setBackgroundRes(R.id.tv,R.drawable.art_shape_transp_con20);
}
helper.setTextColor(R.id.tv,item.getId() == id ? R.color.login_bg_start_1 :R.color.shallow_black);
helper.setOnClickListener(R.id.tv, new View.OnClickListener() {
@Override
public void onClick(View v) {
id = item.getId();
if(onItemClickListener != null){
onItemClickListener.onHeadItemClick(v,position,item.getId());
}
((HeaderViewHolder) holder).adapter.notifyDataSetChanged();
for (int i = 0; i < chapters.size(); i++) {
if(id == chapters.get(i).getId()){
((HeaderViewHolder) holder).lrv.smoothScrollToPosition(i);
}
}
}
});
}
};
((HeaderViewHolder) holder).lrv.setAdapter(((HeaderViewHolder) holder).adapter);
}
} else if (holder instanceof OneViewHolder) {
//注意除去头布局
final int position = mPosition - 1;
final WXarticle.DatasBean data = articles.get(position);
((OneViewHolder) holder).itemView.setTag(position);
((OneViewHolder) holder).type_tv.setText(data.getSuperChapterName() + "/" + data.getChapterName());
((OneViewHolder) holder).content_tv.setText(Html.fromHtml(data.getTitle()));
((OneViewHolder) holder).user_tv.setText(data.getAuthor());
((OneViewHolder) holder).time_tv.setText(data.getNiceDate());
((OneViewHolder) holder).author_tv.setVisibility(position == 0 ? View.VISIBLE : View.GONE);
((OneViewHolder) holder).art_placeholder_tv.setVisibility(position == articles.size()-1 ? View.VISIBLE : View.GONE);
((OneViewHolder) holder).author_tv.setText(data.getAuthor());
((OneViewHolder) holder).content_lay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ARouter.getInstance().build(ConstantArouter.PATH_COMMON_WEBVIEWCTIVITY)
.withInt("id",data.getId())
.withString("url",data.getLink())
.withString("title",data.getTitle())
.withBoolean("isCollection",data.isCollect())
.navigation();
}
});
}
}
@Override
public int getItemCount() {
return articles.size() + headViewCount;
}
@Override
public int getItemViewType(int position) {
if (isHeadView(position)) {
return ITEM_HEAD;
}
return ITEM_ONE;
}
public boolean isHeadView(int position) {
return headViewCount != 0 && position < headViewCount;
}
@Override
public void onClick(View view) {
if (onItemClickListener != null) {
onItemClickListener.onItemClick(view, (Integer) view.getTag());
}
}
//公众号列表
class HeaderViewHolder extends RecyclerView.ViewHolder {
private RecyclerView lrv;
private RecyclerAdapter adapter;
public HeaderViewHolder(View itemView) {
super(itemView);
lrv = itemView.findViewById(R.id.art_main_fragment_head_lrv);
}
}
//最新博文
class OneViewHolder extends RecyclerView.ViewHolder {
private RelativeLayout content_lay;
private TextView author_tv;
private TextView type_tv, content_tv, user_tv, time_tv;
private View art_placeholder_tv;
public OneViewHolder(View itemView) {
super(itemView);
content_lay = itemView.findViewById(R.id.content_lay);
author_tv = itemView.findViewById(R.id.author_tv);
type_tv = itemView.findViewById(R.id.type_tv);
content_tv = itemView.findViewById(R.id.content_tv);
user_tv = itemView.findViewById(R.id.user_tv);
time_tv = itemView.findViewById(R.id.time_tv);
art_placeholder_tv = itemView.findViewById(R.id.art_placeholder_tv);
}
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public interface OnItemClickListener {
void onHeadItemClick(View view, int position,int mId);
void onItemClick(View view, int position);
}
}
================================================
FILE: module_art/src/main/java/com/senon/module_art/contract/ArtMainFragmentCon.java
================================================
package com.senon.module_art.contract;
import com.senon.lib_common.base.BasePresenter;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.base.BaseViewImp;
import com.senon.lib_common.bean.Banner;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.bean.ProjectArticle;
import com.senon.lib_common.bean.WXarticle;
import com.senon.lib_common.bean.WXchapters;
import java.util.List;
/**
* ArtMainFragmentCon V 、P契约类
*/
public interface ArtMainFragmentCon {
interface View extends BaseViewImp {
void getWXartChapResult(BaseResponse> data);
void getWXartListResult(BaseResponse data);
}
abstract class Presenter extends BasePresenter {
public abstract void getWXarticleChapters(boolean isDialog, boolean cancelable);
public abstract void getWXarticleList(int id,int page,boolean isDialog, boolean cancelable);
}
}
================================================
FILE: module_art/src/main/java/com/senon/module_art/fragment/ArtMainFragment.java
================================================
package com.senon.module_art.fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import com.github.jdsjlzx.interfaces.OnLoadMoreListener;
import com.github.jdsjlzx.interfaces.OnRefreshListener;
import com.github.jdsjlzx.recyclerview.LRecyclerView;
import com.github.jdsjlzx.recyclerview.LRecyclerViewAdapter;
import com.github.jdsjlzx.recyclerview.ProgressStyle;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.base.BaseLazyFragment;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.Banner;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.bean.ProjectArticle;
import com.senon.lib_common.bean.WXarticle;
import com.senon.lib_common.bean.WXchapters;
import com.senon.lib_common.utils.BaseEvent;
import com.senon.lib_common.utils.LogUtils;
import com.senon.lib_common.utils.ToastUtil;
import com.senon.module_art.R;
import com.senon.module_art.adapter.ArtMainAdapter;
import com.senon.module_art.contract.ArtMainFragmentCon;
import com.senon.module_art.presenter.ArtMainFragmentPre;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.List;
/**
* art mian fragment
*/
public class ArtMainFragment extends BaseLazyFragment implements
ArtMainFragmentCon.View {
public final static int ID = -1;
private final static int PAGE = 1;
private RecyclerView lrv;
private SmartRefreshLayout home_refreshLayout;
private TextView home_homefragment_title_tv;
private List chapters = new ArrayList<>();
private WXarticle articles;
private int page = PAGE;//公众号页码
private int id = ID;//公众号id
private ArtMainAdapter adapter;
private LinearLayoutManager layoutManager;
@Override
public int getLayoutId() {
return R.layout.art_fragment_main;
}
@Override
public ArtMainFragmentCon.Presenter createPresenter() {
return new ArtMainFragmentPre(mContext);
}
@Override
public ArtMainFragmentCon.View createView() {
return this;
}
@Override
public void init(View rootView) {
lrv = rootView.findViewById(R.id.home_homefragment_lrv);
home_refreshLayout = rootView.findViewById(R.id.home_refreshLayout);
home_homefragment_title_tv = rootView.findViewById(R.id.home_homefragment_title_tv);
home_homefragment_title_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(lrv != null && adapter!= null){
lrv.smoothScrollToPosition(0);
}
}
});
}
@Override
public void onFragmentFirst() {
super.onFragmentFirst();
//第一次可见时,自动加载页面
LogUtils.e("-----> 子fragment进行初始化操作");
EventBus.getDefault().register(this);
//初始化adapter 设置适配器
initAdapter();
//添加滑动位置监听
addLrvListener();
}
private void addLrvListener() {
lrv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//在此做处理
if (null != layoutManager) {
//当前条目索引
int position = layoutManager.findFirstVisibleItemPosition();
if(position > 1){
home_homefragment_title_tv.setVisibility(View.VISIBLE);
}else{
//根据view的高度来做显示隐藏判断
//根据索引来获取对应的itemView
View firstVisiableChildView = layoutManager.findViewByPosition(position);
//获取当前显示条目的高度
int itemHeight = firstVisiableChildView.getHeight();
//获取当前Recyclerview 偏移量
int offset = - firstVisiableChildView.getTop();
if (offset > itemHeight / 4) {
//做显示布局操作
home_homefragment_title_tv.setVisibility(View.VISIBLE);
} else {
//做隐藏布局操作
home_homefragment_title_tv.setVisibility(View.GONE);
}
}
}
}
});
}
private void initAdapter() {
adapter = new ArtMainAdapter(mContext);
layoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false);
lrv.setLayoutManager(layoutManager);
lrv.setAdapter(adapter);
home_refreshLayout.setOnRefreshListener(new com.scwang.smartrefresh.layout.listener.OnRefreshListener() {
@Override
public void onRefresh(RefreshLayout refreshlayout) {
getWXarticleChapters();
}
});
home_refreshLayout.setOnLoadMoreListener(new com.scwang.smartrefresh.layout.listener.OnLoadMoreListener() {
@Override
public void onLoadMore(RefreshLayout refreshlayout) {
getWXarticleList(id,++page);
}
});
adapter.setOnItemClickListener(new ArtMainAdapter.OnItemClickListener() {
@Override
public void onHeadItemClick(View view, int position,int mId) {
id = mId;
page = PAGE;//初始化页码为第一页
getWXarticleList(id,page);
}
@Override
public void onItemClick(View view, int position) {
}
});
home_refreshLayout.autoRefresh(100);
}
//获取公众号列表
private void getWXarticleChapters(){
getPresenter().getWXarticleChapters(false, true);
}
//查看某个公众号历史数据
private void getWXarticleList(int id,int page){
getPresenter().getWXarticleList(id,page,false, true);
}
//完成数据加载
private void refreshData(){
home_refreshLayout.finishRefresh();
home_refreshLayout.finishLoadMore();
adapter.notifyDataChanged();
}
@Override
public void onFragmentVisble() {
super.onFragmentVisble();
//之后每次可见的操作
LogUtils.e("-----> 子fragment每次可见时的操作");
}
@Override
public void getWXartChapResult(BaseResponse> data) {
if(data.getData() != null && !data.getData().isEmpty()){
chapters.clear();
chapters.addAll(data.getData());
if(id == ID){
id = chapters.get(0).getId();//初始id为第一个id
}
adapter.setChaptersDatas(chapters,id);
page = PAGE;//初始化页码为第一页
getWXarticleList(id,page);
}
}
@Override
public void getWXartListResult(BaseResponse data) {
if(data.getData().getDatas() != null && !data.getData().getDatas().isEmpty()){
if(page == PAGE){
articles = data.getData();
}else{
articles.getDatas().addAll(data.getData().getDatas());
}
adapter.setArticleDatas(articles.getDatas());
}
refreshData();
}
@Override
public void onDestroyView() {
super.onDestroyView();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行
public void onEventReceived(BaseEvent event) {
if(event.getCode() == 1){//退出登录 刷新列表
getWXarticleChapters();
}else if (event.getCode() == 101) {
int id = event.getId();
boolean isCollect = event.isCollect();
for (WXarticle.DatasBean bean : articles.getDatas()) {
if(bean.getId() == id){
bean.setCollect(isCollect);
adapter.notifyDataChanged();
return;
}
}
}
}
}
================================================
FILE: module_art/src/main/java/com/senon/module_art/presenter/ArtMainFragmentPre.java
================================================
package com.senon.module_art.presenter;
import android.content.Context;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.Banner;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.bean.ProjectArticle;
import com.senon.lib_common.bean.WXarticle;
import com.senon.lib_common.bean.WXchapters;
import com.senon.lib_common.net.ServerUtils;
import com.senon.lib_common.net.callback.RequestCallback;
import com.senon.lib_common.net.callback.RxErrorHandler;
import com.senon.lib_common.utils.RetryWithDelay;
import com.senon.lib_common.utils.RxUtils;
import com.senon.lib_common.utils.ToastUtil;
import com.senon.module_art.contract.ArtMainFragmentCon;
import java.util.List;
/**
* HomeMainFragmentCon P
*/
public class ArtMainFragmentPre extends ArtMainFragmentCon.Presenter{
private Context context;
public ArtMainFragmentPre(Context context) {
this.context = context;
}
@Override
public void getWXarticleChapters(boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getWXarticleChapters()
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.>>bindToLifecycle(getView()))
.compose(RxUtils.>>getSchedulerTransformer())
.subscribe(new RequestCallback>>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse> baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getWXartChapResult(baseResponse);
}else{
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
@Override
public void getWXarticleList(int id,int page, boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getWXarticleList(id,page)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.>bindToLifecycle(getView()))
.compose(RxUtils.>getSchedulerTransformer())
.subscribe(new RequestCallback>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getWXartListResult(baseResponse);
}else{
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
}
================================================
FILE: module_art/src/main/release/AndroidManifest.xml
================================================
================================================
FILE: module_art/src/main/res/drawable/art_launcher_background.xml
================================================
================================================
FILE: module_art/src/main/res/drawable/art_shape_transp_con20.xml
================================================
================================================
FILE: module_art/src/main/res/drawable/art_shape_white_con30.xml
================================================
================================================
FILE: module_art/src/main/res/drawable/art_shape_yellow_con20.xml
================================================
================================================
FILE: module_art/src/main/res/layout/art_activity_main.xml
================================================
================================================
FILE: module_art/src/main/res/layout/art_activity_splash.xml
================================================
================================================
FILE: module_art/src/main/res/layout/art_adapter_artmain_fragment_article.xml
================================================
================================================
FILE: module_art/src/main/res/layout/art_adapter_artmain_fragment_head.xml
================================================
================================================
FILE: module_art/src/main/res/layout/art_adapter_artmain_fragment_head_item.xml
================================================
================================================
FILE: module_art/src/main/res/layout/art_fragment_main.xml
================================================
================================================
FILE: module_art/src/main/res/values/colors.xml
================================================
================================================
FILE: module_art/src/main/res/values/strings.xml
================================================
玩安卓_公众号
================================================
FILE: module_art/src/main/res/values/styles.xml
================================================
================================================
FILE: module_art/src/test/java/com/senon/module_art/ExampleUnitTest.java
================================================
package com.senon.module_art;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see Testing documentation
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
================================================
FILE: module_home/.gitignore
================================================
/build
================================================
FILE: module_home/build.gradle
================================================
if (isBuildModule.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
android {
compileSdkVersion rootProject.ext.android["compileSdkVersion"]
resourcePrefix "home_"
sourceSets {
main {
if (isBuildModule.toBoolean()) {
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/release/AndroidManifest.xml'
java {
//全部Module一起编译的时候剔除debug目录
exclude '**/**/debug/**'
}
}
}
}
defaultConfig {
if (isBuildModule.toBoolean()) {
applicationId "com.senon.module_home"
}
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
versionCode rootProject.ext.android["versionCode"]
versionName rootProject.ext.android["versionName"]
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
testImplementation rootProject.ext.dependencies["junit"]
api project(':lib_common')
annotationProcessor rootProject.ext.dependencies["router-compiler"]
api rootProject.ext.dependencies["bannerview"]
}
================================================
FILE: module_home/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: module_home/src/androidTest/java/com/senon/module_home/ExampleInstrumentedTest.java
================================================
package com.senon.module_home;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see Testing documentation
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.senon.module_home", appContext.getPackageName());
}
}
================================================
FILE: module_home/src/main/debug/AndroidManifest.xml
================================================
================================================
FILE: module_home/src/main/java/com/senon/module_home/App_Home.java
================================================
package com.senon.module_home;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.base.BaseApplication;
import com.senon.lib_common.utils.ConstantUtils;
/**
* home debug Application
*/
public class App_Home extends BaseApplication {
@Override
public void onCreate() {
super.onCreate();
initARouter();
}
private void initARouter() {
if (ConstantUtils.isAppDebug()) {
//开启InstantRun之后,一定要在ARouter.init之前调用openDebug
ARouter.openDebug();
ARouter.openLog();
}
ARouter.init(this);
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/MainActivity.java
================================================
package com.senon.module_home;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.ConstantLoginArouter;
import com.senon.lib_common.utils.ConstantUtils;
import com.senon.lib_common.utils.LogUtils;
import com.senon.lib_common.utils.StatusBarUtils;
import com.senon.module_home.fragment.HomeMainFragment;
/**
* home 首页
*/
@Route(path = ConstantLoginArouter.PATH_HOME_MAINACTIVITY)
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
private FragmentManager fragmentManager;//声明fragment管理
private HomeMainFragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StatusBarUtils.with(this).init();
setContentView(R.layout.home_activity_main);
ComUtil.changeStatusBarTextColor(this,true);
ARouter.getInstance().inject(this);
LogUtils.e("------->isAppDebug===== "+ ConstantUtils.isAppDebug());
findView();
}
private void findView() {
viewPager = findViewById(R.id.home_main_vp);
fragmentManager = getSupportFragmentManager();
fragment = new HomeMainFragment();
viewPager.setAdapter(new MyFragmentPagerAdapter(fragmentManager));
}
//FragmentPagerAdapter
class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return fragment;
}
@Override
public int getCount() {
return 1;
}
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/SplashActivity.java
================================================
package com.senon.module_home;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.ConstantLoginArouter;
public class SplashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home_activity_splash);
findViewById(R.id.home_main_login_tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String curUrl = ConstantLoginArouter.PATH_HOME_MAINACTIVITY;
ARouter.getInstance().build(ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)
.withString("targetUrl",curUrl)
.navigation();
}
});
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/activity/HomeArticleActivity.java
================================================
package com.senon.module_home.activity;
import android.support.v7.widget.LinearLayoutManager;
import android.text.Html;
import android.view.View;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.github.jdsjlzx.interfaces.OnLoadMoreListener;
import com.github.jdsjlzx.interfaces.OnRefreshListener;
import com.github.jdsjlzx.recyclerview.LRecyclerView;
import com.github.jdsjlzx.recyclerview.LRecyclerViewAdapter;
import com.github.jdsjlzx.recyclerview.ProgressStyle;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.ConstantLoginArouter;
import com.senon.lib_common.adapter.RecycleHolder;
import com.senon.lib_common.adapter.RecyclerAdapter;
import com.senon.lib_common.base.BaseActivity;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.bean.ProjectArticle;
import com.senon.lib_common.utils.BaseEvent;
import com.senon.lib_common.utils.StatusBarUtils;
import com.senon.module_home.R;
import com.senon.module_home.contract.HomeArticleActivityCon;
import com.senon.module_home.presenter.HomeArticleActivityPre;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import retrofit2.http.HEAD;
/**
* 最新博文列表页
*/
@Route(path = ConstantArouter.PATH_HOME_HOMEARTICLEACTIVITY)
public class HomeArticleActivity extends BaseActivity implements
HomeArticleActivityCon.View {
private LRecyclerView lrv;
private TextView toolbar_title_tv;
private boolean isLoadMore = false;//是否加载更多
private boolean isDownRefesh = false;//是否下拉刷新
private int currentPage = 0;//当前页数
private RecyclerAdapter adapter;
private HomeArticle articles;
private ArrayList mData = new ArrayList<>();//原始数据
private ArrayList tempData = new ArrayList<>();//间接数据
private LRecyclerViewAdapter mLRecyclerViewAdapter;//Lrecyclerview的包装适配器
@Override
public int getLayoutId() {
StatusBarUtils.with(this).init();
return R.layout.home_activity_home_article;
}
@Override
public HomeArticleActivityCon.Presenter createPresenter() {
return new HomeArticleActivityPre(this);
}
@Override
public HomeArticleActivityCon.View createView() {
return this;
}
@Override
public void init() {
ComUtil.changeStatusBarTextColor(this,true);
EventBus.getDefault().register(this);
lrv = findViewById(R.id.lrv);
toolbar_title_tv = ((TextView)findViewById(R.id.toolbar_title_tv));
toolbar_title_tv.setText("最新博文");
toolbar_title_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
lrv.smoothScrollToPosition(0);
}
});
findViewById(R.id.toolbar_back_igv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
initLRecyclerVeiw();
}
private void initLRecyclerVeiw() {
LinearLayoutManager manager = new LinearLayoutManager(this);
lrv.setLayoutManager(manager);
lrv.setRefreshProgressStyle(ProgressStyle.LineSpinFadeLoader); //设置下拉刷新Progress的样式
lrv.setArrowImageView(R.mipmap.news_renovate); //设置下拉刷新箭头
lrv.setLoadingMoreProgressStyle(ProgressStyle.BallSpinFadeLoader);
adapter = new RecyclerAdapter(this, mData,R.layout.home_adapter_homemain_fragment_article) {
@Override
public void convert(final RecycleHolder helper, final HomeArticle.DatasBean data, final int position) {
helper.setText(R.id.type_tv,data.getSuperChapterName() + "/" + data.getChapterName());
helper.setText(R.id.content_tv, Html.fromHtml(data.getTitle()).toString());
helper.setText(R.id.user_tv,data.getAuthor());
helper.setText(R.id.time_tv,data.getNiceDate());
helper.setText(R.id.collection_tv,data.isCollect() ? "已收藏":"收藏");
helper.setVisible(R.id.new_tv,data.isFresh());
helper.setVisible(R.id.top_layout,false);
helper.setOnClickListener(R.id.content_lay, new View.OnClickListener() {
@Override
public void onClick(View v) {
ARouter.getInstance().build(ConstantArouter.PATH_COMMON_WEBVIEWCTIVITY)
.withInt("id",data.getId())
.withString("url",data.getLink())
.withString("title",data.getTitle())
.withBoolean("isCollection",data.isCollect())
.navigation();
}
});
helper.setOnClickListener(R.id.collection_tv, new View.OnClickListener() {
@Override
public void onClick(View v) {
if(data.isCollect()){//已收藏
helper.setText(R.id.collection_tv,"收藏");
data.setCollect(!data.isCollect());
getPresenter().getUnollect(data.getId(),false,true);
}else{
helper.setText(R.id.collection_tv,"已收藏");
data.setCollect(!data.isCollect());
getPresenter().getCollect(data.getId(),false,true);
}
}
});
}
};
mLRecyclerViewAdapter = new LRecyclerViewAdapter(adapter);
lrv.setAdapter(mLRecyclerViewAdapter);
//设置底部加载颜色
lrv.setFooterViewColor(R.color.color_blue, R.color.text_gray, R.color.elegant_bg);
lrv.setHeaderViewColor(R.color.color_blue, R.color.text_gray, R.color.elegant_bg);
lrv.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh() {
getFirstPageData();
}
});
lrv.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore() {
isLoadMore = true;
currentPage++;
getOrderList();
}
});
lrv.forceToRefresh();
}
private void getFirstPageData() {
isDownRefesh = true;
currentPage = 0;
getOrderList();
}
private void getOrderList() {
getPresenter().getData(currentPage,false,true);
}
private void refreshData() {
if (lrv == null) {
return;
}
lrv.refreshComplete(currentPage);
mLRecyclerViewAdapter.notifyDataSetChanged();
isDownRefesh = false;
isLoadMore = false;
}
@Override
public void getDataResult(BaseResponse data) {
articles = data.getData();
tempData.clear();
tempData.addAll(data.getData().getDatas());
if (tempData.size() == 0 && mData.size() > 0 && isLoadMore) {//最后一页时
lrv.setNoMore(true);
isLoadMore = false;
} else if (isDownRefesh) {//下拉刷新时
mData.clear();
mData.addAll(tempData);
refreshData();
} else {//加载更多时
mData.addAll(tempData);
refreshData();
}
}
@Override
public void getCollectResult(int id, boolean isCollect) {
BaseEvent event = new BaseEvent();
event.setCode(101);
event.setId(id);
event.setCollect(isCollect);
EventBus.getDefault().post(event);
}
@Override
public void getCollFailResult(int id) {
for (HomeArticle.DatasBean bean : mData) {
if(bean.getId() == id){
bean.setCollect(!bean.isCollect());
mLRecyclerViewAdapter.notifyDataSetChanged();
break;
}
}
ARouter.getInstance().build(ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)
.navigation();
}
@Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行
public void onEventReceived(BaseEvent event) {
if (event.getCode() == 101) {
int id = event.getId();
boolean isCollect = event.isCollect();
for (HomeArticle.DatasBean bean : mData) {
if(bean.getId() == id){
bean.setCollect(isCollect);
mLRecyclerViewAdapter.notifyDataSetChanged();
return;
}
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/activity/HomeProjectActivity.java
================================================
package com.senon.module_home.activity;
import android.support.v7.widget.LinearLayoutManager;
import android.text.Html;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.bumptech.glide.Glide;
import com.github.jdsjlzx.interfaces.OnLoadMoreListener;
import com.github.jdsjlzx.interfaces.OnRefreshListener;
import com.github.jdsjlzx.recyclerview.LRecyclerView;
import com.github.jdsjlzx.recyclerview.LRecyclerViewAdapter;
import com.github.jdsjlzx.recyclerview.ProgressStyle;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.adapter.RecycleHolder;
import com.senon.lib_common.adapter.RecyclerAdapter;
import com.senon.lib_common.base.BaseActivity;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.bean.ProjectArticle;
import com.senon.lib_common.utils.BaseEvent;
import com.senon.lib_common.utils.StatusBarUtils;
import com.senon.module_home.R;
import com.senon.module_home.contract.HomeProjectActivityCon;
import com.senon.module_home.presenter.HomeProjectActivityPre;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
/**
* 最新项目列表页
*/
@Route(path = ConstantArouter.PATH_HOME_HOMEPROJECTACTIVITY)
public class HomeProjectActivity extends BaseActivity implements
HomeProjectActivityCon.View {
private LRecyclerView lrv;
private TextView toolbar_title_tv;
private boolean isLoadMore = false;//是否加载更多
private boolean isDownRefesh = false;//是否下拉刷新
private int currentPage = 1;//当前页数
private RecyclerAdapter adapter;
private ProjectArticle projects;
private ArrayList mData = new ArrayList<>();//原始数据
private ArrayList tempData = new ArrayList<>();//间接数据
private LRecyclerViewAdapter mLRecyclerViewAdapter;//Lrecyclerview的包装适配器
@Override
public int getLayoutId() {
StatusBarUtils.with(this).init();
return R.layout.home_activity_home_project;
}
@Override
public HomeProjectActivityCon.Presenter createPresenter() {
return new HomeProjectActivityPre(this);
}
@Override
public HomeProjectActivityCon.View createView() {
return this;
}
@Override
public void init() {
ComUtil.changeStatusBarTextColor(this,true);
EventBus.getDefault().register(this);
lrv = findViewById(R.id.lrv);
toolbar_title_tv = ((TextView)findViewById(R.id.toolbar_title_tv));
toolbar_title_tv.setText("最新项目");
toolbar_title_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
lrv.smoothScrollToPosition(0);
}
});
findViewById(R.id.toolbar_back_igv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
initLRecyclerVeiw();
}
private void initLRecyclerVeiw() {
LinearLayoutManager manager = new LinearLayoutManager(this);
lrv.setLayoutManager(manager);
lrv.setRefreshProgressStyle(ProgressStyle.LineSpinFadeLoader); //设置下拉刷新Progress的样式
lrv.setArrowImageView(R.mipmap.news_renovate); //设置下拉刷新箭头
lrv.setLoadingMoreProgressStyle(ProgressStyle.BallSpinFadeLoader);
adapter = new RecyclerAdapter(this, mData,R.layout.home_adapter_homemain_fragment_project) {
@Override
public void convert(final RecycleHolder helper, final ProjectArticle.DatasBean data, final int position) {
helper.setImageBitmap(R.id.content_igv,null);
Glide.with(HomeProjectActivity.this).load(data.getEnvelopePic()).into((ImageView) helper.findView(R.id.content_igv));
helper.setText(R.id.content_tv,Html.fromHtml(data.getTitle()).toString());
helper.setText(R.id.title_tv, Html.fromHtml(data.getTitle()).toString());
helper.setText(R.id.user_tv,data.getAuthor());
helper.setText(R.id.time_tv,data.getNiceDate());
helper.setVisible(R.id.top_layout,false);
helper.setVisible(R.id.home_placeholder_tv,position == mData.size()-1);
helper.setOnClickListener(R.id.content_lay, new View.OnClickListener() {
@Override
public void onClick(View v) {
ARouter.getInstance().build(ConstantArouter.PATH_COMMON_WEBVIEWCTIVITY)
.withInt("id",data.getId())
.withString("url",data.getLink())
.withString("title",data.getTitle())
.withBoolean("isCollection",data.isCollect())
.navigation();
}
});
}
};
mLRecyclerViewAdapter = new LRecyclerViewAdapter(adapter);
lrv.setAdapter(mLRecyclerViewAdapter);
//设置底部加载颜色
lrv.setFooterViewColor(R.color.color_blue, R.color.text_gray, R.color.elegant_bg);
lrv.setHeaderViewColor(R.color.color_blue, R.color.text_gray, R.color.elegant_bg);
lrv.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh() {
getFirstPageData();
}
});
lrv.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore() {
isLoadMore = true;
currentPage++;
getOrderList();
}
});
lrv.forceToRefresh();
}
private void getFirstPageData() {
isDownRefesh = true;
currentPage = 1;
getOrderList();
}
private void getOrderList() {
getPresenter().getData(currentPage,false,true);
}
private void refreshData() {
if (lrv == null) {
return;
}
lrv.refreshComplete(currentPage);
mLRecyclerViewAdapter.notifyDataSetChanged();
isDownRefesh = false;
isLoadMore = false;
}
@Override
public void getDataResult(BaseResponse data) {
projects = data.getData();
tempData.clear();
tempData.addAll(data.getData().getDatas());
if (tempData.size() == 0 && mData.size() > 0 && isLoadMore) {//最后一页时
lrv.setNoMore(true);
isLoadMore = false;
} else if (isDownRefesh) {//下拉刷新时
mData.clear();
mData.addAll(tempData);
refreshData();
} else {//加载更多时
mData.addAll(tempData);
refreshData();
}
}
@Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行
public void onEventReceived(BaseEvent event) {
if (event.getCode() == 101) {
int id = event.getId();
boolean isCollect = event.isCollect();
for (ProjectArticle.DatasBean bean : mData) {
if(bean.getId() == id){
bean.setCollect(isCollect);
mLRecyclerViewAdapter.notifyDataSetChanged();
return;
}
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/adapter/HomeMainAdapter.java
================================================
package com.senon.module_home.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.alibaba.android.arouter.launcher.ARouter;
import com.bumptech.glide.Glide;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.bean.Banner;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.bean.ProjectArticle;
import com.senon.lib_common.utils.ToastUtil;
import com.senon.module_home.R;
import com.zhouwei.mzbanner.MZBannerView;
import com.zhouwei.mzbanner.holder.MZHolderCreator;
import com.zhouwei.mzbanner.holder.MZViewHolder;
import java.util.ArrayList;
import java.util.List;
/**
* Home主界面--列表Recycleview适配器
*/
public class HomeMainAdapter extends RecyclerView.Adapter implements View.OnClickListener {
private int ITEM_ONE = 1;
private int ITEM_TWO = 2;
private int ITEM_HEAD = 3;
private int headViewCount = 1;
private OnItemClickListener onItemClickListener;
private Context mContext;
private List banners = new ArrayList<>();//banner图
private List articles = new ArrayList<>();//最新博文
private List projects = new ArrayList<>();//最新项目
private int bannerRefresh = 0;//0:设置banner 1:设置了 并且start 2:设置了 并且pause
public void notifyDataChanged() {
notifyDataSetChanged();
}
//设置banner图
public void setBannerDatas(List datas) {
if (datas != null) {
this.banners.clear();
this.banners.addAll(datas);
bannerRefresh = 0;
notifyDataChanged();
}
}
public void setBannerStatus(int bannerRefresh){
this.bannerRefresh = bannerRefresh;
notifyDataChanged();
}
//设置最新博文
public void setArticleDatas(List datas) {
if (datas != null) {
this.articles.clear();
this.articles.addAll(datas);
notifyDataChanged();
}
}
//设置最新项目
public void setProjectDatas(List datas) {
if (datas != null) {
this.projects.clear();
this.projects.addAll(datas);
notifyDataChanged();
}
}
public HomeMainAdapter(Context context) {
mContext = context;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ITEM_HEAD) {
View view = LayoutInflater.from(mContext).inflate(R.layout.home_adapter_homemain_fragment_head, parent, false);
return new HeaderViewHolder(view);
} else if (viewType == ITEM_ONE) {
View view = LayoutInflater.from(mContext).inflate(R.layout.home_adapter_homemain_fragment_article, parent, false);
return new OneViewHolder(view);
} else if (viewType == ITEM_TWO) {
View view = LayoutInflater.from(mContext).inflate(R.layout.home_adapter_homemain_fragment_project, parent, false);
return new TwoViewHolder(view);
}
return null;
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int mPosition) {
if (holder instanceof HeaderViewHolder) {
if(bannerRefresh == 0){
bannerRefresh = -1;
// 设置页面点击事件
((HeaderViewHolder) holder).banner.setBannerPageClickListener(new MZBannerView.BannerPageClickListener() {
@Override
public void onPageClick(View view, int position) {
ARouter.getInstance().build(ConstantArouter.PATH_COMMON_WEBVIEWCTIVITY)
.withString("url",banners.get(position).getUrl())
.withString("title",banners.get(position).getTitle())
.navigation();
}
});
// 设置数据
((HeaderViewHolder) holder).banner.setPages(banners, new MZHolderCreator() {
@Override
public BannerViewHolder createViewHolder() {
return new BannerViewHolder();
}
});
((HeaderViewHolder) holder).banner.start();
}else if(bannerRefresh == 1){
bannerRefresh = -1;
((HeaderViewHolder) holder).banner.start();
}else if(bannerRefresh == 2){
bannerRefresh = -1;
((HeaderViewHolder) holder).banner.pause();
}
} else if (holder instanceof OneViewHolder) {
//注意除去头布局
final int position = mPosition - 1;
final HomeArticle.DatasBean data = articles.get(position);
((OneViewHolder) holder).itemView.setTag(position);
((OneViewHolder) holder).type_tv.setText(data.getSuperChapterName() + "/" + data.getChapterName());
((OneViewHolder) holder).content_tv.setText(data.getTitle());
((OneViewHolder) holder).user_tv.setText(data.getAuthor());
((OneViewHolder) holder).time_tv.setText(data.getNiceDate());
((OneViewHolder) holder).new_tv.setVisibility(data.isFresh() ? View.VISIBLE : View.GONE);
((OneViewHolder) holder).top_layout.setVisibility(position == 0 ? View.VISIBLE : View.GONE);
((OneViewHolder) holder).collection_tv.setVisibility(View.GONE);
((OneViewHolder) holder).more_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance()
.build(ConstantArouter.PATH_HOME_HOMEARTICLEACTIVITY)
.navigation();
}
});
((OneViewHolder) holder).content_lay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance().build(ConstantArouter.PATH_COMMON_WEBVIEWCTIVITY)
.withInt("id",data.getId())
.withString("url",data.getLink())
.withString("title",data.getTitle())
.withBoolean("isCollection",data.isCollect())
.navigation();
}
});
} else if (holder instanceof TwoViewHolder) {
//注意除去头布局
final int position = mPosition - 1 - articles.size();
final ProjectArticle.DatasBean data = projects.get(position);
((TwoViewHolder) holder).itemView.setTag(position);
((TwoViewHolder) holder).content_igv.setImageBitmap(null);
Glide.with(mContext).load(data.getEnvelopePic()).into(((TwoViewHolder) holder).content_igv);
((TwoViewHolder) holder).content_tv.setText(data.getDesc());
((TwoViewHolder) holder).title_tv.setText(data.getTitle());
((TwoViewHolder) holder).user_tv.setText(data.getAuthor());
((TwoViewHolder) holder).time_tv.setText(data.getNiceDate());
((TwoViewHolder) holder).top_layout.setVisibility(position == 0 ? View.VISIBLE : View.GONE);
((TwoViewHolder) holder).home_placeholder_tv.setVisibility(position == projects.size()-1 ? View.VISIBLE : View.GONE);
((TwoViewHolder) holder).more_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance()
.build(ConstantArouter.PATH_HOME_HOMEPROJECTACTIVITY)
.navigation();
}
});
((TwoViewHolder) holder).content_lay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance().build(ConstantArouter.PATH_COMMON_WEBVIEWCTIVITY)
.withInt("id",data.getId())
.withString("url",data.getLink())
.withString("title",data.getTitle())
.withBoolean("isCollection",data.isCollect())
.navigation();
}
});
}
}
@Override
public int getItemCount() {
return articles.size() + projects.size() + headViewCount;
}
@Override
public int getItemViewType(int position) {
if (isHeadView(position)) {
return ITEM_HEAD;
} else if (isItemOne(position)) {
return ITEM_ONE;
} else if (isItemTwo(position)) {
return ITEM_TWO;
}
return 0;
}
public boolean isHeadView(int position) {
return headViewCount != 0 && position < headViewCount;
}
public boolean isItemOne(int position) {
if (articles.size() == 0) {
return false;
} else if (position <= articles.size()) {
return true;
}
return false;
}
public boolean isItemTwo(int position) {
if (projects.size() == 0) {
return false;
} else if (position <= articles.size() + projects.size()) {
return true;
}
return false;
}
@Override
public void onClick(View view) {
if (onItemClickListener != null) {
onItemClickListener.onItemClick(view, (Integer) view.getTag());
}
}
//头布局--轮播图
class HeaderViewHolder extends RecyclerView.ViewHolder {
private MZBannerView banner;
public HeaderViewHolder(View itemView) {
super(itemView);
banner = itemView.findViewById(R.id.banner);
}
}
//最新博文
class OneViewHolder extends RecyclerView.ViewHolder {
private RelativeLayout top_layout,content_lay;
private TextView more_tv, type_tv, content_tv, user_tv, time_tv;
private TextView new_tv,collection_tv;
public OneViewHolder(View itemView) {
super(itemView);
top_layout = itemView.findViewById(R.id.top_layout);
content_lay = itemView.findViewById(R.id.content_lay);
more_tv = itemView.findViewById(R.id.more_tv);
type_tv = itemView.findViewById(R.id.type_tv);
content_tv = itemView.findViewById(R.id.content_tv);
user_tv = itemView.findViewById(R.id.user_tv);
time_tv = itemView.findViewById(R.id.time_tv);
new_tv = itemView.findViewById(R.id.new_tv);
collection_tv = itemView.findViewById(R.id.collection_tv);
}
}
//最新项目
class TwoViewHolder extends RecyclerView.ViewHolder {
private RelativeLayout top_layout,content_lay;
private ImageView content_igv;
private TextView more_tv, title_tv, content_tv, user_tv, time_tv;
private View home_placeholder_tv;
public TwoViewHolder(View itemView) {
super(itemView);
top_layout = itemView.findViewById(R.id.top_layout);
content_lay = itemView.findViewById(R.id.content_lay);
content_igv = itemView.findViewById(R.id.content_igv);
more_tv = itemView.findViewById(R.id.more_tv);
title_tv = itemView.findViewById(R.id.title_tv);
content_tv = itemView.findViewById(R.id.content_tv);
user_tv = itemView.findViewById(R.id.user_tv);
time_tv = itemView.findViewById(R.id.time_tv);
home_placeholder_tv = itemView.findViewById(R.id.home_placeholder_tv);
}
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public interface OnItemClickListener {
void onHeadItemClick(View view, int position);
void onItemClick(View view, int position);
}
public static class BannerViewHolder implements MZViewHolder {
private ImageView igv;
@Override
public View createView(Context context) {
// 返回页面布局文件
View view = LayoutInflater.from(context).inflate(R.layout.home_adapter_homemain_fragment_banneritem,null);
igv = view.findViewById(R.id.igv);
return view;
}
@Override
public void onBind(Context context, int i, Banner banner) {
// 数据绑定
Glide.with(context).load(banner.getImagePath()).into(igv);
}
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/contract/HomeArticleActivityCon.java
================================================
package com.senon.module_home.contract;
import com.senon.lib_common.base.BasePresenter;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.base.BaseViewImp;
import com.senon.lib_common.bean.HomeArticle;
public interface HomeArticleActivityCon {
interface View extends BaseViewImp {
void getDataResult(BaseResponse data);
void getCollectResult(int id,boolean isCollect);
void getCollFailResult(int id);
}
abstract class Presenter extends BasePresenter {
public abstract void getData(int page,boolean isDialog, boolean cancelable);
public abstract void getCollect(int id ,boolean isDialog, boolean cancelable);
public abstract void getUnollect(int id, boolean isDialog, boolean cancelable);
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/contract/HomeMainFragmentCon.java
================================================
package com.senon.module_home.contract;
import com.senon.lib_common.base.BasePresenter;
import com.senon.lib_common.base.BaseViewImp;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.Banner;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.bean.ProjectArticle;
import java.util.List;
/**
* HomeMainFragmentCon V 、P契约类
*/
public interface HomeMainFragmentCon {
interface View extends BaseViewImp {
void getBannerResult(BaseResponse> data);
void getHomeArticleResult(BaseResponse data);
void getHomeProjectResult(BaseResponse data);
}
abstract class Presenter extends BasePresenter {
public abstract void getBanner(boolean isDialog, boolean cancelable);
public abstract void getHomeArticle(int page,boolean isDialog, boolean cancelable);
public abstract void getHomeProject(int page,boolean isDialog, boolean cancelable);
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/contract/HomeProjectActivityCon.java
================================================
package com.senon.module_home.contract;
import com.senon.lib_common.base.BasePresenter;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.base.BaseViewImp;
import com.senon.lib_common.bean.ProjectArticle;
public interface HomeProjectActivityCon {
interface View extends BaseViewImp {
void getDataResult(BaseResponse data);
}
abstract class Presenter extends BasePresenter {
public abstract void getData(int page,boolean isDialog, boolean cancelable);
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/fragment/HomeMainFragment.java
================================================
package com.senon.module_home.fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import com.github.jdsjlzx.interfaces.OnLoadMoreListener;
import com.github.jdsjlzx.interfaces.OnRefreshListener;
import com.github.jdsjlzx.recyclerview.LRecyclerView;
import com.github.jdsjlzx.recyclerview.LRecyclerViewAdapter;
import com.github.jdsjlzx.recyclerview.ProgressStyle;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.base.BaseLazyFragment;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.Banner;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.bean.ProjectArticle;
import com.senon.lib_common.utils.BaseEvent;
import com.senon.lib_common.utils.LogUtils;
import com.senon.module_home.R;
import com.senon.module_home.adapter.HomeMainAdapter;
import com.senon.module_home.contract.HomeMainFragmentCon;
import com.senon.module_home.presenter.HomeMainFragmentPre;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.List;
/**
* home mian fragment
*/
public class HomeMainFragment extends BaseLazyFragment implements
HomeMainFragmentCon.View {
private RecyclerView lrv;
private SmartRefreshLayout home_refreshLayout;
private TextView home_homefragment_title_tv;
private List banners = new ArrayList<>();
private HomeArticle article;
private ProjectArticle project;
private final int articlePage = 0;//首页文章页码
private final int projectPage = 1;//首页最新项目
private HomeMainAdapter adapter;
private LinearLayoutManager layoutManager;
@Override
public int getLayoutId() {
return R.layout.home_fragment_main;
}
@Override
public HomeMainFragmentCon.Presenter createPresenter() {
return new HomeMainFragmentPre(mContext);
}
@Override
public HomeMainFragmentCon.View createView() {
return this;
}
@Override
public void init(View rootView) {
lrv = rootView.findViewById(R.id.home_homefragment_lrv);
home_refreshLayout = rootView.findViewById(R.id.home_refreshLayout);
home_homefragment_title_tv = rootView.findViewById(R.id.home_homefragment_title_tv);
home_homefragment_title_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(lrv != null && adapter!= null){
lrv.smoothScrollToPosition(0);
}
}
});
}
@Override
public void onFragmentFirst() {
super.onFragmentFirst();
//第一次可见时,自动加载页面
LogUtils.e("-----> 子fragment进行初始化操作");
//注册eventbus
EventBus.getDefault().register(this);
//初始化adapter 设置适配器
initAdapter();
//添加滑动位置监听
addLrvListener();
}
private void addLrvListener() {
lrv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//在此做处理
if (null != layoutManager) {
//当前条目索引
int position = layoutManager.findFirstVisibleItemPosition();
if(position > 1){
home_homefragment_title_tv.setVisibility(View.VISIBLE);
}else{
//根据view的高度来做显示隐藏判断
//根据索引来获取对应的itemView
View firstVisiableChildView = layoutManager.findViewByPosition(position);
//获取当前显示条目的高度
int itemHeight = firstVisiableChildView.getHeight();
//获取当前Recyclerview 偏移量
int offset = - firstVisiableChildView.getTop();
if (offset > itemHeight / 4) {
//做显示布局操作
home_homefragment_title_tv.setVisibility(View.VISIBLE);
} else {
//做隐藏布局操作
home_homefragment_title_tv.setVisibility(View.GONE);
}
}
}
}
});
}
private void initAdapter() {
adapter = new HomeMainAdapter(mContext);
layoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false);
lrv.setLayoutManager(layoutManager);
lrv.setAdapter(adapter);
home_refreshLayout.setOnRefreshListener(new com.scwang.smartrefresh.layout.listener.OnRefreshListener() {
@Override
public void onRefresh(RefreshLayout refreshlayout) {
getFirstData();
}
});
home_refreshLayout.setEnableLoadMore(false);
home_refreshLayout.autoRefresh(100);
}
private void getFirstData(){
//加载banner
getPresenter().getBanner(false, true);
//加载首页最新文章
getPresenter().getHomeArticle(articlePage,false, true);
//加载项目列表数据-完整项目模块
getPresenter().getHomeProject(projectPage,false, true);
}
@Override
public void onFragmentVisble() {
super.onFragmentVisble();
//之后每次可见的操作
LogUtils.e("-----> 子fragment每次可见时的操作");
}
@Override
public void getBannerResult(BaseResponse> data) {
banners = data.getData();
adapter.setBannerDatas(banners);
refreshData();
}
@Override
public void getHomeArticleResult(BaseResponse data) {
List list = new ArrayList<>();
if(data.getData() != null){
for (int i = 0; i < data.getData().getDatas().size(); i++) {
if(i < 5){
list.add(data.getData().getDatas().get(i));
}
}
}
data.getData().setDatas(list);
article = data.getData();
adapter.setArticleDatas(article.getDatas());
refreshData();
}
@Override
public void getHomeProjectResult(BaseResponse data) {
List list = new ArrayList<>();
if(data.getData() != null){
for (int i = 0; i < data.getData().getDatas().size(); i++) {
if(i < 5){
list.add(data.getData().getDatas().get(i));
}
}
}
data.getData().setDatas(list);
project = data.getData();
adapter.setProjectDatas(project.getDatas());
refreshData();
}
@Override
public void onResume() {
super.onResume();
if(adapter != null){//banner生命周期需要调用的方法start
adapter.setBannerStatus(1);
}
}
@Override
public void onPause() {
super.onPause();
if(adapter != null){//banner生命周期需要调用的方法pause
adapter.setBannerStatus(2);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
EventBus.getDefault().unregister(this);
}
//完成数据加载
private void refreshData(){
home_refreshLayout.finishRefresh();
adapter.notifyDataChanged();
}
@Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行
public void onEventReceived(BaseEvent event) {
if(event.getCode() == 1){//退出登录 刷新列表
getFirstData();
}else if (event.getCode() == 101) {
int id = event.getId();
boolean isCollect = event.isCollect();
for (HomeArticle.DatasBean bean : article.getDatas()) {
if(bean.getId() == id){
bean.setCollect(isCollect);
return;
}
}
for (ProjectArticle.DatasBean bean : project.getDatas()) {
if(bean.getId() == id){
bean.setCollect(isCollect);
return;
}
}
}
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/presenter/HomeArticleActivityPre.java
================================================
package com.senon.module_home.presenter;
import android.content.Context;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.Banner;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.net.ServerUtils;
import com.senon.lib_common.net.callback.RequestCallback;
import com.senon.lib_common.net.callback.RxErrorHandler;
import com.senon.lib_common.utils.RetryWithDelay;
import com.senon.lib_common.utils.RxUtils;
import com.senon.lib_common.utils.ToastUtil;
import com.senon.module_home.contract.HomeArticleActivityCon;
import java.util.List;
/**
* HomeArticleActivityCon P
*/
public class HomeArticleActivityPre extends HomeArticleActivityCon.Presenter{
private Context context;
public HomeArticleActivityPre(Context context) {
this.context = context;
}
@Override
public void getData(int page,boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getHomeArticle(page)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.>bindToLifecycle(getView()))
.compose(RxUtils.>getSchedulerTransformer())
.subscribe(new RequestCallback>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getDataResult(baseResponse);
}else{
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
@Override
public void getCollect(final int id, boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getCollect(id)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.bindToLifecycle(getView()))
.compose(RxUtils.getSchedulerTransformer())
.subscribe(new RequestCallback(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getCollectResult(id,true);
}else{
getView().getCollFailResult(id);
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
@Override
public void getUnollect(final int id, boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getUncollectOriginId(id)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.bindToLifecycle(getView()))
.compose(RxUtils.getSchedulerTransformer())
.subscribe(new RequestCallback(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getCollectResult(id,false);
}else{
getView().getCollFailResult(id);
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/presenter/HomeMainFragmentPre.java
================================================
package com.senon.module_home.presenter;
import android.content.Context;
import com.senon.lib_common.bean.Banner;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.bean.Login;
import com.senon.lib_common.bean.ProjectArticle;
import com.senon.lib_common.net.ServerUtils;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.net.callback.RequestCallback;
import com.senon.lib_common.net.callback.RxErrorHandler;
import com.senon.lib_common.utils.RetryWithDelay;
import com.senon.lib_common.utils.RxUtils;
import com.senon.lib_common.utils.ToastUtil;
import com.senon.module_home.contract.HomeMainFragmentCon;
import java.util.List;
/**
* HomeMainFragmentCon P
*/
public class HomeMainFragmentPre extends HomeMainFragmentCon.Presenter{
private Context context;
public HomeMainFragmentPre(Context context) {
this.context = context;
}
@Override
public void getBanner(boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().banner()
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.>>bindToLifecycle(getView()))
.compose(RxUtils.>>getSchedulerTransformer())
.subscribe(new RequestCallback>>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse> baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getBannerResult(baseResponse);
}else{
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
@Override
public void getHomeArticle(int page, boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getHomeArticle(page)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.>bindToLifecycle(getView()))
.compose(RxUtils.>getSchedulerTransformer())
.subscribe(new RequestCallback>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getHomeArticleResult(baseResponse);
}else{
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
@Override
public void getHomeProject(int page, boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getHomeProject(page)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.>bindToLifecycle(getView()))
.compose(RxUtils.>getSchedulerTransformer())
.subscribe(new RequestCallback>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getHomeProjectResult(baseResponse);
}else{
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
}
================================================
FILE: module_home/src/main/java/com/senon/module_home/presenter/HomeProjectActivityPre.java
================================================
package com.senon.module_home.presenter;
import android.content.Context;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.ProjectArticle;
import com.senon.lib_common.net.ServerUtils;
import com.senon.lib_common.net.callback.RequestCallback;
import com.senon.lib_common.net.callback.RxErrorHandler;
import com.senon.lib_common.utils.RetryWithDelay;
import com.senon.lib_common.utils.RxUtils;
import com.senon.lib_common.utils.ToastUtil;
import com.senon.module_home.contract.HomeProjectActivityCon;
/**
* HomeProjectActivityCon P
*/
public class HomeProjectActivityPre extends HomeProjectActivityCon.Presenter{
private Context context;
public HomeProjectActivityPre(Context context) {
this.context = context;
}
@Override
public void getData(int page,boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getHomeProject(page)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.>bindToLifecycle(getView()))
.compose(RxUtils.>getSchedulerTransformer())
.subscribe(new RequestCallback>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getDataResult(baseResponse);
}else{
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
}
================================================
FILE: module_home/src/main/release/AndroidManifest.xml
================================================
================================================
FILE: module_home/src/main/res/drawable/home_ic_launcher_background.xml
================================================
================================================
FILE: module_home/src/main/res/drawable/home_shape_stro_red_con30.xml
================================================
================================================
FILE: module_home/src/main/res/drawable/home_shape_white_con30.xml
================================================
================================================
FILE: module_home/src/main/res/layout/home_activity_home_article.xml
================================================
================================================
FILE: module_home/src/main/res/layout/home_activity_home_project.xml
================================================
================================================
FILE: module_home/src/main/res/layout/home_activity_main.xml
================================================
================================================
FILE: module_home/src/main/res/layout/home_activity_splash.xml
================================================
================================================
FILE: module_home/src/main/res/layout/home_adapter_homemain_fragment_article.xml
================================================
================================================
FILE: module_home/src/main/res/layout/home_adapter_homemain_fragment_banneritem.xml
================================================
================================================
FILE: module_home/src/main/res/layout/home_adapter_homemain_fragment_head.xml
================================================
================================================
FILE: module_home/src/main/res/layout/home_adapter_homemain_fragment_project.xml
================================================
================================================
FILE: module_home/src/main/res/layout/home_fragment_main.xml
================================================
================================================
FILE: module_home/src/main/res/values/colors.xml
================================================
#3F51B5
#303F9F
#FF4081
================================================
FILE: module_home/src/main/res/values/strings.xml
================================================
玩安卓_主页
================================================
FILE: module_home/src/main/res/values/styles.xml
================================================
================================================
FILE: module_home/src/test/java/com/senon/module_home/ExampleUnitTest.java
================================================
package com.senon.module_home;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see Testing documentation
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
================================================
FILE: module_life/.gitignore
================================================
/build
================================================
FILE: module_life/build.gradle
================================================
if(isBuildModule.toBoolean()){
apply plugin: 'com.android.application'
}else{
apply plugin: 'com.android.library'
}
android {
compileSdkVersion rootProject.ext.android["compileSdkVersion"]
resourcePrefix "life_"
sourceSets {
main {
if (isBuildModule.toBoolean()) {
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/release/AndroidManifest.xml'
java{
//全部Module一起编译的时候剔除debug目录
exclude '**/**/debug/**'
}
}
}
}
defaultConfig {
if(isBuildModule.toBoolean()){
applicationId "com.senon.module_life"
}
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
versionCode rootProject.ext.android["versionCode"]
versionName rootProject.ext.android["versionName"]
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
testImplementation rootProject.ext.dependencies["junit"]
api project(':lib_common')
annotationProcessor rootProject.ext.dependencies["router-compiler"]
api rootProject.ext.dependencies["flowlayout"]
}
================================================
FILE: module_life/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: module_life/src/androidTest/java/com/senon/module_life/ExampleInstrumentedTest.java
================================================
package com.senon.module_life;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see Testing documentation
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.senon.module_life", appContext.getPackageName());
}
}
================================================
FILE: module_life/src/main/debug/AndroidManifest.xml
================================================
================================================
FILE: module_life/src/main/java/com/senon/module_life/App_Life.java
================================================
package com.senon.module_life;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.base.BaseApplication;
import com.senon.lib_common.utils.ConstantUtils;
/**
* life debug Application
*/
public class App_Life extends BaseApplication {
@Override
public void onCreate() {
super.onCreate();
initARouter();
}
private void initARouter() {
if (ConstantUtils.isAppDebug()) {
//开启InstantRun之后,一定要在ARouter.init之前调用openDebug
ARouter.openDebug();
ARouter.openLog();
}
ARouter.init(this);
}
}
================================================
FILE: module_life/src/main/java/com/senon/module_life/MainActivity.java
================================================
package com.senon.module_life;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.ConstantLoginArouter;
import com.senon.lib_common.utils.StatusBarUtils;
import com.senon.module_life.fragment.LifeMainFragment;
/**
* life 首页
*/
@Route(path = ConstantLoginArouter.PATH_LIFE_MAINACTIVITY)
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
private FragmentManager fragmentManager;//声明fragment管理
private LifeMainFragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StatusBarUtils.with(this).init();
setContentView(R.layout.life_activity_main);
ComUtil.changeStatusBarTextColor(this,true);
ARouter.getInstance().inject(this);
findView();
}
private void findView() {
viewPager = findViewById(R.id.life_main_vp);
fragmentManager = getSupportFragmentManager();
fragment = new LifeMainFragment();
viewPager.setAdapter(new MyFragmentPagerAdapter(fragmentManager));
}
//FragmentPagerAdapter
class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return fragment;
}
@Override
public int getCount() {
return 1;
}
}
}
================================================
FILE: module_life/src/main/java/com/senon/module_life/SplashActivity.java
================================================
package com.senon.module_life;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import com.alibaba.android.arouter.launcher.ARouter;
import com.senon.lib_common.ConstantLoginArouter;
public class SplashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.life_activity_splash);
findViewById(R.id.life_main_login_tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String curUrl = ConstantLoginArouter.PATH_LIFE_MAINACTIVITY;
ARouter.getInstance().build(ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)
.withString("targetUrl",curUrl)
.navigation();
}
});
}
}
================================================
FILE: module_life/src/main/java/com/senon/module_life/activity/KnowledgeSystemActivity.java
================================================
package com.senon.module_life.activity;
import android.support.v7.widget.LinearLayoutManager;
import android.text.Html;
import android.view.View;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Autowired;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.github.jdsjlzx.interfaces.OnLoadMoreListener;
import com.github.jdsjlzx.interfaces.OnRefreshListener;
import com.github.jdsjlzx.recyclerview.LRecyclerView;
import com.github.jdsjlzx.recyclerview.LRecyclerViewAdapter;
import com.github.jdsjlzx.recyclerview.ProgressStyle;
import com.senon.lib_common.ComUtil;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.ConstantLoginArouter;
import com.senon.lib_common.adapter.RecycleHolder;
import com.senon.lib_common.adapter.RecyclerAdapter;
import com.senon.lib_common.base.BaseActivity;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.HomeArticle;
import com.senon.lib_common.bean.KnowledgeSysArticle;
import com.senon.lib_common.utils.BaseEvent;
import com.senon.lib_common.utils.StatusBarUtils;
import com.senon.module_life.R;
import com.senon.module_life.contract.KnowledgeSysActivityCon;
import com.senon.module_life.presenter.KnowledgeSysActivityPre;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
/**
* 体系列表页
*/
@Route(path = ConstantArouter.PATH_LIFE_KNOWLEDGESYSTEMACTIVITY)
public class KnowledgeSystemActivity extends BaseActivity implements
KnowledgeSysActivityCon.View {
@Autowired
int cid;
@Autowired
String title;
private LRecyclerView lrv;
private TextView toolbar_title_tv;
private boolean isLoadMore = false;//是否加载更多
private boolean isDownRefesh = false;//是否下拉刷新
private int currentPage = 0;//当前页数
private RecyclerAdapter adapter;
private KnowledgeSysArticle project;
private ArrayList mData = new ArrayList<>();//原始数据
private ArrayList tempData = new ArrayList<>();//间接数据
private LRecyclerViewAdapter mLRecyclerViewAdapter;//Lrecyclerview的包装适配器
@Override
public int getLayoutId() {
StatusBarUtils.with(this).init();
return R.layout.life_activity_home_article;
}
@Override
public KnowledgeSysActivityCon.Presenter createPresenter() {
return new KnowledgeSysActivityPre(this);
}
@Override
public KnowledgeSysActivityCon.View createView() {
return this;
}
@Override
public void init() {
ComUtil.changeStatusBarTextColor(this,true);
EventBus.getDefault().register(this);
lrv = findViewById(R.id.lrv);
toolbar_title_tv = ((TextView)findViewById(R.id.toolbar_title_tv));
toolbar_title_tv.setText(title);
toolbar_title_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
lrv.smoothScrollToPosition(0);
}
});
findViewById(R.id.toolbar_back_igv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
initLRecyclerVeiw();
}
private void initLRecyclerVeiw() {
LinearLayoutManager manager = new LinearLayoutManager(this);
lrv.setLayoutManager(manager);
lrv.setRefreshProgressStyle(ProgressStyle.LineSpinFadeLoader); //设置下拉刷新Progress的样式
lrv.setArrowImageView(R.mipmap.news_renovate); //设置下拉刷新箭头
lrv.setLoadingMoreProgressStyle(ProgressStyle.BallSpinFadeLoader);
adapter = new RecyclerAdapter(this, mData,R.layout.life_adapter_knowledgesys_item) {
@Override
public void convert(final RecycleHolder helper, final KnowledgeSysArticle.DatasBean data, final int position) {
helper.setText(R.id.content_tv, Html.fromHtml(data.getTitle()).toString());
helper.setText(R.id.user_tv,data.getAuthor());
helper.setText(R.id.time_tv,data.getNiceDate());
helper.setText(R.id.collection_tv,data.isCollect() ? "已收藏":"收藏");
helper.setVisible(R.id.top_layout,false);
helper.setOnClickListener(R.id.content_lay, new View.OnClickListener() {
@Override
public void onClick(View v) {
ARouter.getInstance().build(ConstantArouter.PATH_COMMON_WEBVIEWCTIVITY)
.withInt("id",data.getId())
.withString("url",data.getLink())
.withString("title",data.getTitle())
.withBoolean("isCollection",data.isCollect())
.navigation();
}
});
helper.setOnClickListener(R.id.collection_tv, new View.OnClickListener() {
@Override
public void onClick(View v) {
if(data.isCollect()){//已收藏
helper.setText(R.id.collection_tv,"收藏");
data.setCollect(!data.isCollect());
getPresenter().getUnollect(data.getId(),false,true);
}else{
helper.setText(R.id.collection_tv,"已收藏");
data.setCollect(!data.isCollect());
getPresenter().getCollect(data.getId(),false,true);
}
}
});
}
};
mLRecyclerViewAdapter = new LRecyclerViewAdapter(adapter);
lrv.setAdapter(mLRecyclerViewAdapter);
//设置底部加载颜色
lrv.setFooterViewColor(R.color.color_blue, R.color.text_gray, R.color.elegant_bg);
lrv.setHeaderViewColor(R.color.color_blue, R.color.text_gray, R.color.elegant_bg);
lrv.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh() {
getFirstPageData();
}
});
lrv.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore() {
isLoadMore = true;
currentPage++;
getOrderList();
}
});
lrv.forceToRefresh();
}
private void getFirstPageData() {
isDownRefesh = true;
currentPage = 0;
getOrderList();
}
private void getOrderList() {
getPresenter().getData(cid,currentPage,false,true);
}
private void refreshData() {
if (lrv == null) {
return;
}
lrv.refreshComplete(currentPage);
mLRecyclerViewAdapter.notifyDataSetChanged();
isDownRefesh = false;
isLoadMore = false;
}
@Override
public void getDataResult(BaseResponse data) {
project = data.getData();
tempData.clear();
tempData.addAll(data.getData().getDatas());
if (tempData.size() == 0 && mData.size() > 0 && isLoadMore) {//最后一页时
lrv.setNoMore(true);
isLoadMore = false;
} else if (isDownRefesh) {//下拉刷新时
mData.clear();
mData.addAll(tempData);
refreshData();
} else {//加载更多时
mData.addAll(tempData);
refreshData();
}
}
@Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行
public void onEventReceived(BaseEvent event) {
if (event.getCode() == 101) {
int id = event.getId();
boolean isCollect = event.isCollect();
for (KnowledgeSysArticle.DatasBean bean : mData) {
if(bean.getId() == id){
bean.setCollect(isCollect);
mLRecyclerViewAdapter.notifyDataSetChanged();
return;
}
}
}
}
@Override
public void getCollectResult(int id, boolean isCollect) {
BaseEvent event = new BaseEvent();
event.setCode(101);
event.setId(id);
event.setCollect(isCollect);
EventBus.getDefault().post(event);
}
@Override
public void getCollFailResult(int id) {
for (KnowledgeSysArticle.DatasBean bean : mData) {
if(bean.getId() == id){
bean.setCollect(!bean.isCollect());
mLRecyclerViewAdapter.notifyDataSetChanged();
break;
}
}
ARouter.getInstance().build(ConstantLoginArouter.PATH_COMMON_LOGINACTIVITY)
.navigation();
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
================================================
FILE: module_life/src/main/java/com/senon/module_life/contract/KnowledgeSysActivityCon.java
================================================
package com.senon.module_life.contract;
import com.senon.lib_common.base.BasePresenter;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.base.BaseViewImp;
import com.senon.lib_common.bean.KnowledgeSysArticle;
public interface KnowledgeSysActivityCon {
interface View extends BaseViewImp {
void getDataResult(BaseResponse data);
void getCollectResult(int id,boolean isCollect);
void getCollFailResult(int id);
}
abstract class Presenter extends BasePresenter {
public abstract void getData(int cid,int page,boolean isDialog, boolean cancelable);
public abstract void getCollect(int id ,boolean isDialog, boolean cancelable);
public abstract void getUnollect(int id, boolean isDialog, boolean cancelable);
}
}
================================================
FILE: module_life/src/main/java/com/senon/module_life/contract/LifeMainFragmentCon.java
================================================
package com.senon.module_life.contract;
import com.senon.lib_common.base.BasePresenter;
import com.senon.lib_common.base.BaseViewImp;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.KnowledgeSystem;
import java.util.HashMap;
import java.util.List;
/**
* LifeMainFragmentCon V 、P契约类
*/
public interface LifeMainFragmentCon {
interface View extends BaseViewImp {
void getKnowledgeListResult(BaseResponse> data);
}
abstract class Presenter extends BasePresenter {
public abstract void getKnowledgeList(boolean isDialog, boolean cancelable);
}
}
================================================
FILE: module_life/src/main/java/com/senon/module_life/fragment/LifeMainFragment.java
================================================
package com.senon.module_life.fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.alibaba.android.arouter.launcher.ARouter;
import com.github.jdsjlzx.interfaces.OnLoadMoreListener;
import com.github.jdsjlzx.interfaces.OnRefreshListener;
import com.github.jdsjlzx.recyclerview.LRecyclerView;
import com.github.jdsjlzx.recyclerview.LRecyclerViewAdapter;
import com.github.jdsjlzx.recyclerview.ProgressStyle;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.senon.lib_common.ConstantArouter;
import com.senon.lib_common.adapter.RecycleHolder;
import com.senon.lib_common.adapter.RecyclerAdapter;
import com.senon.lib_common.base.BaseLazyFragment;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.Banner;
import com.senon.lib_common.bean.KnowledgeSystem;
import com.senon.lib_common.utils.BaseEvent;
import com.senon.lib_common.utils.LogUtils;
import com.senon.lib_common.utils.ToastUtil;
import com.senon.module_life.R;
import com.senon.module_life.contract.LifeMainFragmentCon;
import com.senon.module_life.presenter.LifeMainFragmentPre;
import com.zhy.view.flowlayout.FlowLayout;
import com.zhy.view.flowlayout.TagAdapter;
import com.zhy.view.flowlayout.TagFlowLayout;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* 体系homefragment
*/
public class LifeMainFragment extends BaseLazyFragment implements
LifeMainFragmentCon.View {
private RecyclerView lrv;
private SmartRefreshLayout life_refreshLayout;
private TextView life_homefragment_title_tv;
private List knowledges = new ArrayList<>();
private LinearLayoutManager layoutManager;
private RecyclerAdapter adapter;
@Override
public int getLayoutId() {
return R.layout.life_fragment_main;
}
@Override
public LifeMainFragmentCon.Presenter createPresenter() {
return new LifeMainFragmentPre(mContext);
}
@Override
public LifeMainFragmentCon.View createView() {
return this;
}
@Override
public void init(View rootView) {
lrv = rootView.findViewById(R.id.life_homefragment_lrv);
life_refreshLayout = rootView.findViewById(R.id.life_refreshLayout);
life_homefragment_title_tv = rootView.findViewById(R.id.life_homefragment_title_tv);
life_homefragment_title_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(lrv != null && adapter!= null){
lrv.smoothScrollToPosition(0);
}
}
});
}
@Override
public void onFragmentFirst() {
super.onFragmentFirst();
//第一次可见时,自动加载页面
LogUtils.e("-----> 子fragment进行初始化操作");
//注册eventbus
EventBus.getDefault().register(this);
//初始化adapter 设置适配器
initAdapter();
//添加滑动位置监听
addLrvListener();
}
private void addLrvListener() {
lrv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//在此做处理
if (null != layoutManager) {
//当前条目索引
int position = layoutManager.findFirstVisibleItemPosition();
if(position > 1){
life_homefragment_title_tv.setVisibility(View.VISIBLE);
}else if(position >= 0){
//根据view的高度来做显示隐藏判断
//根据索引来获取对应的itemView
View firstVisiableChildView = layoutManager.findViewByPosition(position);
//获取当前显示条目的高度
int itemHeight = firstVisiableChildView.getHeight();
//获取当前Recyclerview 偏移量
int offset = - firstVisiableChildView.getTop();
if (offset > itemHeight / 4) {
//做显示布局操作
life_homefragment_title_tv.setVisibility(View.VISIBLE);
} else {
//做隐藏布局操作
life_homefragment_title_tv.setVisibility(View.GONE);
}
}
}
}
});
}
private void getFirstData() {
getPresenter().getKnowledgeList(false,true);
}
private void initAdapter() {
layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
lrv.setLayoutManager(layoutManager);
adapter = new RecyclerAdapter(getContext(), knowledges, R.layout.life_adapter_lifemain_fragment) {
@Override
public void convert(final RecycleHolder helper, final KnowledgeSystem item, final int position) {
helper.setVisible(R.id.textview,position == 0?true:false);
helper.setVisible(R.id.home_placeholder_tv,position == knowledges.size() - 1?true:false);
helper.setText(R.id.content_tv,item.getName());
final TagFlowLayout flowLayout = helper.findView(R.id.flowlayout);
flowLayout.setAdapter(new TagAdapter(item.getChildren()){
@Override
public View getView(FlowLayout parent, int position, KnowledgeSystem.ChildrenBean bean){
TextView tv = (TextView) LayoutInflater.from(mContext).inflate(
R.layout.life_adapter_lifemain_flowlayout_item, flowLayout, false);
tv.setText(item.getChildren().get(position).getName());
return tv;
}
});
flowLayout.setOnTagClickListener(new TagFlowLayout.OnTagClickListener(){
@Override
public boolean onTagClick(View view, int position, FlowLayout parent){
ARouter.getInstance().build(ConstantArouter.PATH_LIFE_KNOWLEDGESYSTEMACTIVITY)
.withString("title",item.getChildren().get(position).getName())
.withInt("cid",item.getChildren().get(position).getId())
.navigation();
return true;
}
});
}
};
lrv.setAdapter(adapter);
life_refreshLayout.setOnRefreshListener(new com.scwang.smartrefresh.layout.listener.OnRefreshListener() {
@Override
public void onRefresh(RefreshLayout refreshlayout) {
getFirstData();
}
});
life_refreshLayout.setEnableLoadMore(false);
life_refreshLayout.autoRefresh(100);
}
@Override
public void onFragmentVisble() {
super.onFragmentVisble();
//之后每次可见的操作
LogUtils.e("-----> 子fragment每次可见时的操作");
}
@Override
public void getKnowledgeListResult(BaseResponse> data) {
knowledges.clear();
knowledges.addAll(data.getData());
adapter.notifyDataSetChanged();
life_refreshLayout.finishRefresh();
}
@Override
public void onDestroyView() {
super.onDestroyView();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventReceived(BaseEvent event) {
if(event.getCode() == 1){//退出登录 刷新列表
getFirstData();
}
}
}
================================================
FILE: module_life/src/main/java/com/senon/module_life/presenter/KnowledgeSysActivityPre.java
================================================
package com.senon.module_life.presenter;
import android.content.Context;
import com.senon.lib_common.base.BaseResponse;
import com.senon.lib_common.bean.KnowledgeSysArticle;
import com.senon.lib_common.bean.ProjectArticle;
import com.senon.lib_common.net.ServerUtils;
import com.senon.lib_common.net.callback.RequestCallback;
import com.senon.lib_common.net.callback.RxErrorHandler;
import com.senon.lib_common.utils.RetryWithDelay;
import com.senon.lib_common.utils.RxUtils;
import com.senon.lib_common.utils.ToastUtil;
import com.senon.module_life.contract.KnowledgeSysActivityCon;
/**
* KnowledgeSysActivity P
*/
public class KnowledgeSysActivityPre extends KnowledgeSysActivityCon.Presenter{
private Context context;
public KnowledgeSysActivityPre(Context context) {
this.context = context;
}
@Override
public void getData(int cid ,int page,boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getKnowledgeArticle(page,cid)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.>bindToLifecycle(getView()))
.compose(RxUtils.>getSchedulerTransformer())
.subscribe(new RequestCallback>(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getDataResult(baseResponse);
}else{
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
@Override
public void getCollect(final int id, boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getCollect(id)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.bindToLifecycle(getView()))
.compose(RxUtils.getSchedulerTransformer())
.subscribe(new RequestCallback(context, RxErrorHandler.getInstance(),isDialog,cancelable) {
@Override
public void onNext(BaseResponse baseResponse) {
super.onNext(baseResponse);
if(baseResponse.getCode() == 0){
getView().getCollectResult(id,true);
}else{
getView().getCollFailResult(id);
ToastUtil.initToast(baseResponse.getMsg());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
}
});
}
@Override
public void getUnollect(final int id, boolean isDialog, boolean cancelable) {
ServerUtils.getCommonApi().getUncollectOriginId(id)
.retryWhen(new RetryWithDelay(3,2))
.compose(RxUtils.