├── .gitignore ├── Joy.iml ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── jude │ │ └── joy │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── jude │ │ │ └── joy │ │ │ ├── app │ │ │ └── APP.java │ │ │ ├── config │ │ │ └── API.java │ │ │ ├── model │ │ │ ├── bean │ │ │ │ ├── ImageJoy.java │ │ │ │ ├── ImageJoyPage.java │ │ │ │ ├── TextJoy.java │ │ │ │ └── TextJoyPage.java │ │ │ └── server │ │ │ │ ├── ErrorTransform.java │ │ │ │ ├── HeaderInterceptors.java │ │ │ │ ├── RestInterceptors.java │ │ │ │ ├── SchedulerTransform.java │ │ │ │ ├── ServiceAPI.java │ │ │ │ ├── ServiceAPIModule.java │ │ │ │ └── ServiceModelComponent.java │ │ │ ├── module │ │ │ ├── image │ │ │ │ ├── ImageJoyFragment.java │ │ │ │ ├── ImageJoyPresenter.java │ │ │ │ ├── ImageJoyVH.java │ │ │ │ ├── PictureActivity.java │ │ │ │ └── PictureFragment.java │ │ │ ├── main │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainPresenter.java │ │ │ ├── setting │ │ │ │ ├── AboutUsActivity.java │ │ │ │ └── AboutUsPresenter.java │ │ │ └── text │ │ │ │ ├── TextJoyFragment.java │ │ │ │ ├── TextJoyPresenter.java │ │ │ │ └── TextJoyVH.java │ │ │ └── utils │ │ │ ├── ImageFilter.java │ │ │ ├── RecentDateFormat.java │ │ │ └── TextFilter.java │ └── res │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_main.xml │ │ ├── fragment_picture.xml │ │ ├── item_joy_image.xml │ │ └── item_joy_text.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── logo.png │ │ ├── mipmap-mdpi │ │ └── logo.png │ │ ├── mipmap-xhdpi │ │ └── logo.png │ │ ├── mipmap-xxhdpi │ │ └── logo.png │ │ ├── values-v19 │ │ └── styles.xml │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── color.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── jude │ └── joy │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .gradle 3 | .DS_Store 4 | /captures 5 | 6 | # built application files 7 | *.apk 8 | 9 | # files for the dex VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # generated files 16 | bin/ 17 | gen/ 18 | build 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Eclipse project files 24 | .classpath 25 | .project 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Intellij project files 31 | *.iml 32 | *.ipr 33 | *.iws 34 | .idea 35 | 36 | -------------------------------------------------------------------------------- /Joy.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Joy 2 | 豆逼APP源码 3 | 下载地址:http://www.wandoujia.com/apps/com.jude.joy 4 | 5 | ##Screenshot 6 | ![joy.png](http://img.wdjimg.com/mms/screenshot/2/24/bb2ec85c230a7eeecdc4399bc6892242_320_535.jpeg) 7 | ![joy.png](http://img.wdjimg.com/mms/screenshot/6/f5/3dad64a4c3359af5692072b08cb03f56_320_535.jpeg) 8 | 9 | ##dependencies 10 | - [appcompat-v7](https://developer.android.com/tools/support-library/features.html#v7-appcompat)/[cardview-v7](https://developer.android.com/tools/support-library/features.html#v7-cardview) 11 | - [Beam](https://github.com/Jude95/Beam) 12 | - [fresco](http://frescolib.org/) 13 | - [ButterKnife](http://jakewharton.github.io/butterknife/) 14 | - [requestvolley](https://github.com/Jude95/RequestVolley) 15 | - [utils](https://github.com/Jude95/Utils) 16 | - [gson](https://github.com/google/gson) 17 | 18 | ##API 19 | http://apistore.baidu.com/apiworks/servicedetail/864.html 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'me.tatarka.retrolambda' 3 | apply plugin: 'com.neenbedankt.android-apt' 4 | 5 | android { 6 | compileSdkVersion 24 7 | buildToolsVersion "24.0.0" 8 | 9 | defaultConfig { 10 | applicationId "com.jude.joy" 11 | minSdkVersion 15 12 | targetSdkVersion 24 13 | versionCode 5 14 | versionName "1.4" 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | compileOptions { 23 | sourceCompatibility JavaVersion.VERSION_1_8 24 | targetCompatibility JavaVersion.VERSION_1_8 25 | } 26 | 27 | } 28 | 29 | dependencies { 30 | compile fileTree(include: ['*.jar'], dir: 'libs') 31 | testCompile 'junit:junit:4.12' 32 | compile 'com.android.support:cardview-v7:24.0.0' 33 | compile 'com.android.support:appcompat-v7:24.0.0' 34 | compile 'com.jude:beam:3.0.1' 35 | compile('com.github.afollestad.material-dialogs:core:0.8.5.4@aar') { 36 | transitive = true 37 | } 38 | compile 'com.android.support:design:24.0.0' 39 | compile 'com.jude:utils:1.2.1' 40 | compile 'com.jakewharton:butterknife:8.0.1' 41 | apt 'com.jakewharton:butterknife-compiler:8.0.1' 42 | compile 'com.github.bumptech.glide:glide:3.6.1' 43 | compile 'com.google.code.gson:gson:2.6.2' 44 | compile 'com.squareup.retrofit2:retrofit:2.1.0' 45 | compile 'com.squareup.retrofit2:converter-gson:2.1.0' 46 | compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' 47 | compile 'com.squareup.okhttp3:logging-interceptor:3.3.1' 48 | compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar' 49 | compile 'com.google.dagger:dagger:2.4' 50 | apt 'com.google.dagger:dagger-compiler:2.4' 51 | compile 'com.pnikosis:materialish-progress:1.7' 52 | compile 'com.github.chrisbanes:PhotoView:1.2.6' 53 | } 54 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in F:\software\android-sdk_r24.0.2-windows\android-sdk-windows/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | #ButterKnife 19 | -dontwarn butterknife.internal.** 20 | -keep class **$$ViewInjector { *; } 21 | -keepnames class * { @butterknife.InjectView *;} 22 | 23 | #RetroLambda 24 | -dontwarn java.lang.invoke.* 25 | 26 | 27 | #Glide 28 | -keep public class * implements com.bumptech.glide.module.GlideModule 29 | -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { 30 | **[] $VALUES; 31 | public *; 32 | } 33 | -dontwarn jp.co.cyberagent.android.gpuimage.** 34 | 35 | #Retrofit 36 | #Using for retrofit & gson 37 | -keep class com.google.gson.** { *; } 38 | -keep class com.google.inject.** { *; } 39 | -keep class org.apache.http.** { *; } 40 | -keep class org.apache.james.mime4j.* { *; } 41 | -keep class javax.inject.** { *; } 42 | -keep class retrofit.** { *; } 43 | -keep class sun.misc.Unsafe { *; } 44 | -keep class com.google.gson.stream.** { *; } 45 | -keepclassmembernames interface * { 46 | @retrofit.http.* ; 47 | } 48 | -keep interface retrofit.** { *;} 49 | -keep interface com.squareup.** { *; } 50 | -dontwarn rx.** 51 | -dontwarn retrofit.** 52 | -dontwarn okio.** 53 | -keep class sun.misc.Unsafe { *; } 54 | 55 | -keepattributes Signature 56 | -keepattributes Exceptions 57 | 58 | #Model 59 | -keep class com.jude.joy.domain.** { *; } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/jude/joy/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/app/APP.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.app; 2 | 3 | import android.app.Application; 4 | 5 | import com.jude.beam.Beam; 6 | import com.jude.joy.BuildConfig; 7 | import com.jude.utils.JUtils; 8 | 9 | /** 10 | * Created by Mr.Jude on 2015/8/20. 11 | */ 12 | public class APP extends Application { 13 | 14 | @Override 15 | public void onCreate() { 16 | super.onCreate(); 17 | JUtils.initialize(this); 18 | JUtils.setDebug(BuildConfig.DEBUG, "JoyLog"); 19 | Beam.init(this); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/config/API.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.config; 2 | 3 | /** 4 | * Created by zhuchenxi on 15/8/2. 5 | */ 6 | public class API { 7 | public static final class URL{ 8 | public static final String JOY_TEXT = "http://apis.baidu.com/showapi_open_bus/showapi_joke/joke_text"; 9 | public static final String JOY_IMAGE = "http://apis.baidu.com/showapi_open_bus/showapi_joke/joke_pic"; 10 | } 11 | 12 | public static class KEY { 13 | public static final String STATUS = "showapi_res_code"; 14 | public static final String INFO = "showapi_res_error"; 15 | public static final String DATA = "showapi_res_body"; 16 | } 17 | 18 | public static class CODE { 19 | public static final int SUCCEED = 0; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/model/bean/ImageJoy.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.model.bean; 2 | 3 | /** 4 | * Created by Mr.Jude on 2015/8/20. 5 | */ 6 | public class ImageJoy { 7 | 8 | 9 | /** 10 | * ct : 2015-08-13 13:10:36.891 11 | * img : http://img.hao123.com/data/3_1b72caa7998cf674fecb4f334cf9d356_430 12 | * title : 牙膏还有这技能。 13 | * type : 2 14 | */ 15 | private String ct; 16 | private String img; 17 | private String title; 18 | private int type; 19 | 20 | public void setCt(String ct) { 21 | this.ct = ct; 22 | } 23 | 24 | public void setImg(String img) { 25 | this.img = img; 26 | } 27 | 28 | public void setTitle(String title) { 29 | this.title = title; 30 | } 31 | 32 | public void setType(int type) { 33 | this.type = type; 34 | } 35 | 36 | public String getCt() { 37 | return ct; 38 | } 39 | 40 | public String getImg() { 41 | return img; 42 | } 43 | 44 | public String getTitle() { 45 | return title; 46 | } 47 | 48 | public int getType() { 49 | return type; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/model/bean/ImageJoyPage.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.model.bean; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by Mr.Jude on 2015/8/20. 7 | */ 8 | public class ImageJoyPage { 9 | private int allNum; 10 | private int allPage; 11 | 12 | public int getAllNum() { 13 | return allNum; 14 | } 15 | 16 | public void setAllNum(int allNum) { 17 | this.allNum = allNum; 18 | } 19 | 20 | public int getAllPage() { 21 | return allPage; 22 | } 23 | 24 | public void setAllPage(int allPage) { 25 | this.allPage = allPage; 26 | } 27 | 28 | public List getContentlist() { 29 | return contentlist; 30 | } 31 | 32 | public void setContentlist(List contentlist) { 33 | this.contentlist = contentlist; 34 | } 35 | 36 | private List contentlist; 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/model/bean/TextJoy.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.model.bean; 2 | 3 | /** 4 | * Created by Mr.Jude on 2015/8/20. 5 | */ 6 | public class TextJoy { 7 | 8 | /** 9 | * ct : 2015-08-13 13:10:26.149 10 | * text : 新人发帖求过…… 媳妇最近怀孕了…天天这也不想吃那也不想吃…有一天发脾气要我给他做想吃的,结果做了好多还是没有想吃的…最后着急了大喊:再做不出我想吃的我就去大街上要饭……我想说:你吃什么自己都不知道我怎么做啊…唉…想想男人女人都不容易啊… 11 | * title : 媳妇儿有了… 12 | * type : 1 13 | */ 14 | private String ct; 15 | private String text; 16 | private String title; 17 | private int type; 18 | 19 | public void setCt(String ct) { 20 | this.ct = ct; 21 | } 22 | 23 | public void setText(String text) { 24 | this.text = text; 25 | } 26 | 27 | public void setTitle(String title) { 28 | this.title = title; 29 | } 30 | 31 | public void setType(int type) { 32 | this.type = type; 33 | } 34 | 35 | public String getCt() { 36 | return ct; 37 | } 38 | 39 | public String getText() { 40 | return text; 41 | } 42 | 43 | public String getTitle() { 44 | return title; 45 | } 46 | 47 | public int getType() { 48 | return type; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/model/bean/TextJoyPage.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.model.bean; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by Mr.Jude on 2015/8/20. 7 | */ 8 | public class TextJoyPage { 9 | private int allNum; 10 | private int allPage; 11 | private List contentlist; 12 | 13 | public int getAllNum() { 14 | return allNum; 15 | } 16 | 17 | public void setAllNum(int allNum) { 18 | this.allNum = allNum; 19 | } 20 | 21 | public int getAllPage() { 22 | return allPage; 23 | } 24 | 25 | public void setAllPage(int allPage) { 26 | this.allPage = allPage; 27 | } 28 | 29 | public List getContentlist() { 30 | return contentlist; 31 | } 32 | 33 | public void setContentlist(List contentlist) { 34 | this.contentlist = contentlist; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/model/server/ErrorTransform.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.model.server; 2 | 3 | import com.jude.utils.JUtils; 4 | 5 | import retrofit2.adapter.rxjava.HttpException; 6 | import rx.Observable; 7 | import rx.functions.Action1; 8 | 9 | /** 10 | * Created by Mr.Jude on 2015/8/25. 11 | * 对服务器请求的Observer的修改 12 | */ 13 | public class ErrorTransform implements Observable.Transformer { 14 | 15 | private Action1 handler; 16 | public ErrorTransform(Action1 handler) { 17 | this.handler = handler; 18 | } 19 | 20 | @Override 21 | public Observable call(Observable tObservable) { 22 | return tObservable.doOnError(handler) 23 | .onErrorResumeNext(Observable.empty()); 24 | } 25 | 26 | 27 | public static class ServerErrorHandler implements Action1 { 28 | private static final int W_TOAST = 1; 29 | 30 | public static final ServerErrorHandler NONE = new ServerErrorHandler(0); 31 | public static final ServerErrorHandler TOAST = new ServerErrorHandler(1<< W_TOAST); 32 | 33 | 34 | private int kind; 35 | 36 | public ServerErrorHandler(int kind) { 37 | this.kind = kind; 38 | } 39 | 40 | private boolean has(int index){ 41 | return (kind & 1<0; 42 | } 43 | 44 | @Override 45 | public void call(Throwable throwable) { 46 | JUtils.Log("Error:"+throwable.getClass().getName()+":"+throwable.getMessage()); 47 | String errorString; 48 | if (throwable instanceof HttpException) { 49 | HttpException err = (HttpException) throwable; 50 | if (err.code() >= 400 && err.code() < 500){ 51 | errorString = "请求错误:"+err.message(); 52 | }else if (err.code() >= 500){ 53 | errorString = "服务器错误"; 54 | }else { 55 | errorString = "请求错误:"+err.code(); 56 | } 57 | }else { 58 | errorString = "网络错误"; 59 | JUtils.Log(throwable.getMessage()); 60 | } 61 | if (has(W_TOAST)) JUtils.Toast(errorString); 62 | } 63 | 64 | 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/model/server/HeaderInterceptors.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.model.server; 2 | 3 | import java.io.IOException; 4 | 5 | import okhttp3.Interceptor; 6 | import okhttp3.Request; 7 | import okhttp3.Response; 8 | 9 | public class HeaderInterceptors implements Interceptor { 10 | @Override 11 | public Response intercept(Chain chain) throws IOException { 12 | Request request = chain.request(); 13 | Request.Builder builder = request.newBuilder(); 14 | builder.addHeader("apikey", "c676a989ffe83f89db5265482ef3222d"); 15 | return chain.proceed(builder.build()); 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/model/server/RestInterceptors.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.model.server; 2 | 3 | import com.jude.utils.JUtils; 4 | 5 | import org.json.JSONException; 6 | import org.json.JSONObject; 7 | 8 | import java.io.IOException; 9 | import java.util.Iterator; 10 | import java.util.ServiceConfigurationError; 11 | 12 | import okhttp3.Interceptor; 13 | import okhttp3.MediaType; 14 | import okhttp3.Request; 15 | import okhttp3.Response; 16 | import okhttp3.ResponseBody; 17 | 18 | /** 19 | * Created by Zane on 16/3/14. 20 | * 拦截,http缓存 21 | */ 22 | public class RestInterceptors implements Interceptor { 23 | 24 | private static final String TAG = "HeaderInterceptors"; 25 | 26 | @Override 27 | public Response intercept(Chain chain) throws IOException { 28 | 29 | Request request = chain.request(); 30 | 31 | Response originalResponse = chain.proceed(request); 32 | MediaType contentType = originalResponse.body().contentType(); 33 | 34 | //先解析一遍json数据,根据status和message去手动改状态码和描述 35 | String originalContent = originalResponse.body().string(); 36 | JUtils.Log("RestInterceptors",request.url().toString()+":\n"+originalContent); 37 | 38 | int code = 400; 39 | String errorMessage = ""; 40 | String body = "null"; 41 | 42 | JSONObject wrapper = null; 43 | try { 44 | wrapper = new JSONObject(originalContent); 45 | Iterator iterator = wrapper.keys(); 46 | while (iterator.hasNext()){ 47 | String key = iterator.next(); 48 | switch (key){ 49 | case "showapi_res_code": 50 | code = wrapper.getInt(key); 51 | if (code == 0)code=200; 52 | else code=400; 53 | break; 54 | case "showapi_res_error": 55 | errorMessage = wrapper.getString(key); 56 | break; 57 | default: 58 | body = wrapper.getString(key); 59 | break; 60 | } 61 | } 62 | } catch (JSONException e) { 63 | throw new ServiceConfigurationError("服务器错误:"+e.getLocalizedMessage()); 64 | } 65 | 66 | 67 | return originalResponse.newBuilder() 68 | .code(code) 69 | .message(errorMessage) 70 | .body(ResponseBody.create(contentType, body)) 71 | .build(); 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/model/server/SchedulerTransform.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.model.server; 2 | 3 | import rx.Observable; 4 | import rx.android.schedulers.AndroidSchedulers; 5 | import rx.schedulers.Schedulers; 6 | 7 | /** 8 | * Created by Mr.Jude on 2015/8/25. 9 | * 对服务器请求的Observer的修改 10 | */ 11 | public class SchedulerTransform implements Observable.Transformer { 12 | @Override 13 | public Observable call(Observable tObservable) { 14 | return tObservable 15 | .subscribeOn(Schedulers.io()) 16 | .observeOn(AndroidSchedulers.mainThread()) 17 | .unsubscribeOn(Schedulers.io()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/model/server/ServiceAPI.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.model.server; 2 | 3 | import com.jude.joy.model.bean.ImageJoyPage; 4 | import com.jude.joy.model.bean.TextJoyPage; 5 | 6 | import retrofit2.http.GET; 7 | import retrofit2.http.Query; 8 | import rx.Observable; 9 | 10 | public interface ServiceAPI { 11 | String BASEURL = "http://apis.baidu.com/showapi_open_bus/"; 12 | @GET("showapi_joke/joke_text") 13 | Observable getTextJoyList(@Query("page")int page); 14 | 15 | @GET("showapi_joke/joke_pic") 16 | Observable getImageJoyList(@Query("page")int page); 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/model/server/ServiceAPIModule.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.model.server; 2 | 3 | import com.google.gson.GsonBuilder; 4 | 5 | import javax.inject.Singleton; 6 | 7 | import dagger.Module; 8 | import dagger.Provides; 9 | import okhttp3.OkHttpClient; 10 | import okhttp3.logging.HttpLoggingInterceptor; 11 | import retrofit2.Retrofit; 12 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; 13 | import retrofit2.converter.gson.GsonConverterFactory; 14 | 15 | /** 16 | * Created by Mr.Jude on 2015/11/18. 17 | */ 18 | @Module 19 | public class ServiceAPIModule { 20 | @Singleton 21 | @Provides 22 | ServiceAPI provideServiceAPI(OkHttpClient okHttpClient) { 23 | Retrofit retrofit = new Retrofit.Builder() 24 | .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().create())) 25 | .baseUrl(ServiceAPI.BASEURL) 26 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 27 | .client(okHttpClient) 28 | .build(); 29 | return retrofit.create(ServiceAPI.class); 30 | } 31 | 32 | @Singleton 33 | @Provides 34 | OkHttpClient provideOkHttpClient() { 35 | return new OkHttpClient.Builder() 36 | .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) 37 | .addNetworkInterceptor(new HeaderInterceptors()) 38 | .addNetworkInterceptor(new RestInterceptors()) 39 | .build(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/model/server/ServiceModelComponent.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.model.server; 2 | 3 | import com.jude.joy.module.image.ImageJoyPresenter; 4 | import com.jude.joy.module.text.TextJoyPresenter; 5 | 6 | import javax.inject.Singleton; 7 | 8 | import dagger.Component; 9 | 10 | /** 11 | * Created by zhuchenxi on 16/1/25. 12 | */ 13 | @Singleton 14 | @Component(modules = {ServiceAPIModule.class}) 15 | public interface ServiceModelComponent { 16 | void inject(TextJoyPresenter model); 17 | 18 | void inject(ImageJoyPresenter model); 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/image/ImageJoyFragment.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.image; 2 | 3 | import android.view.ViewGroup; 4 | 5 | import com.jude.beam.bijection.RequiresPresenter; 6 | import com.jude.beam.expansion.list.BeamListFragment; 7 | import com.jude.beam.expansion.list.ListConfig; 8 | import com.jude.easyrecyclerview.adapter.BaseViewHolder; 9 | import com.jude.joy.model.bean.ImageJoy; 10 | 11 | /** 12 | * Created by Mr.Jude on 2015/8/20. 13 | */ 14 | @RequiresPresenter(ImageJoyPresenter.class) 15 | public class ImageJoyFragment extends BeamListFragment { 16 | @Override 17 | public BaseViewHolder getViewHolder(ViewGroup viewGroup, int i) { 18 | return new ImageJoyVH(viewGroup); 19 | } 20 | @Override 21 | public ListConfig getConfig() { 22 | return super.getConfig() 23 | .setLoadmoreAble(true) 24 | .setRefreshAble(true) 25 | .setNoMoreAble(true) 26 | .setErrorAble(true) 27 | .setErrorTouchToResumeAble(true); 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/image/ImageJoyPresenter.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.image; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.bumptech.glide.Glide; 8 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 9 | import com.jude.beam.expansion.list.BeamListFragmentPresenter; 10 | import com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter; 11 | import com.jude.joy.model.bean.ImageJoy; 12 | import com.jude.joy.model.bean.ImageJoyPage; 13 | import com.jude.joy.model.server.DaggerServiceModelComponent; 14 | import com.jude.joy.model.server.SchedulerTransform; 15 | import com.jude.joy.model.server.ServiceAPI; 16 | 17 | import java.util.ArrayList; 18 | 19 | import javax.inject.Inject; 20 | 21 | /** 22 | * Created by Mr.Jude on 2015/8/20. 23 | */ 24 | public class ImageJoyPresenter extends BeamListFragmentPresenter { 25 | @Inject 26 | ServiceAPI mServer; 27 | @Override 28 | protected void onCreate(ImageJoyFragment view, Bundle savedState) { 29 | super.onCreate(view, savedState); 30 | DaggerServiceModelComponent.builder().build().inject(this); 31 | onRefresh(); 32 | } 33 | 34 | @Override 35 | protected void onCreateView(@NonNull ImageJoyFragment view) { 36 | super.onCreateView(view); 37 | getAdapter().setOnItemClickListener(new RecyclerArrayAdapter.OnItemClickListener() { 38 | @Override 39 | public void onItemClick(int position) { 40 | ArrayList list = new ArrayList(); 41 | for (ImageJoy imageJoy : getAdapter().getAllData()) { 42 | list.add(imageJoy.getImg()); 43 | } 44 | Intent i = new Intent(getView().getContext(),PictureActivity.class); 45 | i.putExtra(PictureActivity.KEY_PICTURES,list); 46 | i.putExtra(PictureActivity.KEY_INDEX,position); 47 | getView().startActivity(i); 48 | } 49 | }); 50 | } 51 | 52 | @Override 53 | public void onRefresh() { 54 | mServer.getImageJoyList(1) 55 | .compose(new SchedulerTransform<>()) 56 | .map(ImageJoyPage::getContentlist) 57 | .doAfterTerminate(()-> setCurPage(2)) 58 | .doOnNext(list->{ 59 | for (ImageJoy imageJoy : list) { 60 | String url = imageJoy.getImg(); 61 | Glide.with(getView()).load(url) 62 | .diskCacheStrategy(DiskCacheStrategy.SOURCE) 63 | .preload(); 64 | } 65 | }) 66 | .unsafeSubscribe(getRefreshSubscriber()); 67 | } 68 | 69 | @Override 70 | public void onLoadMore() { 71 | mServer.getImageJoyList(getCurPage()) 72 | .compose(new SchedulerTransform<>()) 73 | .map(ImageJoyPage::getContentlist) 74 | .doOnNext(list->{ 75 | for (ImageJoy imageJoy : list) { 76 | String url = imageJoy.getImg(); 77 | Glide.with(getView()).load(url) 78 | .diskCacheStrategy(DiskCacheStrategy.SOURCE) 79 | .preload(); 80 | } 81 | }) 82 | .unsafeSubscribe(getMoreSubscriber()); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/image/ImageJoyVH.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.image; 2 | 3 | import android.view.ViewGroup; 4 | import android.widget.ImageView; 5 | import android.widget.TextView; 6 | 7 | import com.bumptech.glide.Glide; 8 | import com.jude.easyrecyclerview.adapter.BaseViewHolder; 9 | import com.jude.joy.R; 10 | import com.jude.joy.model.bean.ImageJoy; 11 | import com.jude.joy.utils.ImageFilter; 12 | import com.jude.joy.utils.RecentDateFormat; 13 | import com.jude.utils.JTimeTransform; 14 | 15 | import butterknife.BindView; 16 | import butterknife.ButterKnife; 17 | 18 | /** 19 | * Created by Mr.Jude on 2015/8/20. 20 | */ 21 | public class ImageJoyVH extends BaseViewHolder { 22 | 23 | @BindView(R.id.title) 24 | TextView title; 25 | @BindView(R.id.image) 26 | ImageView image; 27 | @BindView(R.id.time) 28 | TextView time; 29 | 30 | public ImageJoyVH(ViewGroup parent) { 31 | super(parent, R.layout.item_joy_image); 32 | ButterKnife.bind(this, itemView); 33 | } 34 | 35 | @Override 36 | public void setData(ImageJoy data) { 37 | title.setText(data.getTitle()); 38 | Glide.clear(image); 39 | Glide.with(getContext()) 40 | .load(ImageFilter.filter(data.getImg())) 41 | .into(image); 42 | time.setText(new JTimeTransform().parse("yyyy-MM-dd hh:mm:ss",data.getCt()).toString(new RecentDateFormat())); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/image/PictureActivity.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.image; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.support.v4.app.FragmentManager; 6 | import android.support.v4.app.FragmentStatePagerAdapter; 7 | import android.support.v4.view.ViewPager; 8 | import android.view.MotionEvent; 9 | import android.view.ViewGroup; 10 | 11 | import com.jude.beam.expansion.BeamBaseActivity; 12 | import com.jude.joy.R; 13 | 14 | import java.util.ArrayList; 15 | 16 | 17 | /** 18 | * Created by Mr.Jude on 2015/2/22. 19 | * 展示图片的Activity 20 | */ 21 | public class PictureActivity extends BeamBaseActivity { 22 | public static String KEY_PICTURES = "pictures"; 23 | public static String KEY_PICTURE = "picture"; 24 | public static String KEY_INDEX = "index"; 25 | 26 | private ViewPager mViewPager; 27 | private PictureFragmentAdapter mAdapter; 28 | 29 | private ArrayList mPictures; 30 | 31 | @Override 32 | public void onCreate(Bundle savedInstanceState){ 33 | super.onCreate(savedInstanceState); 34 | mViewPager = new ViewPager(this); 35 | mViewPager.setId(R.id.about); 36 | mViewPager.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 37 | setContentView(mViewPager); 38 | 39 | mAdapter = new PictureFragmentAdapter(getSupportFragmentManager()); 40 | mViewPager.setAdapter(mAdapter); 41 | 42 | mPictures = getIntent().getStringArrayListExtra(KEY_PICTURES); 43 | if (mPictures == null) mPictures = new ArrayList<>(); 44 | String picture = getIntent().getStringExtra(KEY_PICTURE); 45 | if (picture!=null) mPictures.add(picture); 46 | int index = getIntent().getIntExtra(KEY_INDEX,0); 47 | 48 | mAdapter.setPictures(mPictures); 49 | mViewPager.setCurrentItem(index); 50 | } 51 | 52 | 53 | @Override 54 | public boolean dispatchTouchEvent(MotionEvent ev) { 55 | return super.dispatchTouchEvent(ev); 56 | } 57 | 58 | static class PictureFragmentAdapter extends FragmentStatePagerAdapter { 59 | ArrayList mPictures; 60 | 61 | public PictureFragmentAdapter(FragmentManager fm) { 62 | super(fm); 63 | } 64 | 65 | public void setPictures(ArrayList pictures){ 66 | mPictures = pictures; 67 | notifyDataSetChanged(); 68 | } 69 | 70 | @Override 71 | public Fragment getItem(int position) { 72 | Fragment fragment = new PictureFragment(); 73 | Bundle bundle = new Bundle(); 74 | bundle.putString("picture",mPictures.get(position)); 75 | fragment.setArguments(bundle); 76 | return fragment; 77 | } 78 | 79 | @Override 80 | public int getCount() { 81 | return mPictures==null?0:mPictures.size(); 82 | } 83 | } 84 | 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/image/PictureFragment.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.image; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v7.widget.Toolbar; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.FrameLayout; 11 | 12 | import com.bumptech.glide.Glide; 13 | import com.jude.joy.R; 14 | import com.jude.joy.utils.ImageFilter; 15 | import com.jude.utils.JUtils; 16 | import com.pnikosis.materialishprogress.ProgressWheel; 17 | 18 | import butterknife.BindView; 19 | import butterknife.ButterKnife; 20 | import uk.co.senab.photoview.PhotoView; 21 | 22 | /** 23 | * Created by zhuchenxi on 16/6/2. 24 | */ 25 | 26 | public class PictureFragment extends Fragment { 27 | String mPicture; 28 | @BindView(R.id.wheel) 29 | ProgressWheel wheel; 30 | @BindView(R.id.photoview) 31 | PhotoView photoview; 32 | @BindView(R.id.container) 33 | FrameLayout container; 34 | 35 | @BindView(R.id.toolbar) 36 | Toolbar toolbar; 37 | 38 | 39 | @Override 40 | public void onCreate(@Nullable Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | mPicture = getArguments().getString("picture"); 43 | JUtils.Log("PictureFragment onCreate " + mPicture); 44 | } 45 | 46 | @Nullable 47 | @Override 48 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 49 | View view = inflater.inflate(R.layout.fragment_picture, container, false); 50 | ButterKnife.bind(this, view); 51 | 52 | return view; 53 | } 54 | 55 | @Override 56 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 57 | super.onActivityCreated(savedInstanceState); 58 | 59 | Glide.with(getContext()) 60 | .load(ImageFilter.filter(mPicture)) 61 | .into(photoview); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/main/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.main; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.design.widget.AppBarLayout; 6 | import android.support.design.widget.CoordinatorLayout; 7 | import android.support.design.widget.TabLayout; 8 | import android.support.v4.app.Fragment; 9 | import android.support.v4.app.FragmentManager; 10 | import android.support.v4.app.FragmentStatePagerAdapter; 11 | import android.support.v4.view.ViewPager; 12 | import android.view.Menu; 13 | import android.view.MenuItem; 14 | 15 | import com.jude.beam.bijection.RequiresPresenter; 16 | import com.jude.beam.expansion.BeamBaseActivity; 17 | import com.jude.joy.R; 18 | import com.jude.joy.module.image.ImageJoyFragment; 19 | import com.jude.joy.module.setting.AboutUsActivity; 20 | import com.jude.joy.module.text.TextJoyFragment; 21 | 22 | import butterknife.BindView; 23 | import butterknife.ButterKnife; 24 | 25 | @RequiresPresenter(MainPresenter.class) 26 | public class MainActivity extends BeamBaseActivity { 27 | 28 | @BindView(R.id.viewPager) 29 | ViewPager viewpager; 30 | @BindView(R.id.app_bar_layout) 31 | AppBarLayout appBarLayout; 32 | @BindView(R.id.coordinator_layout) 33 | CoordinatorLayout coordinatorLayout; 34 | @BindView(R.id.tab_layout) 35 | TabLayout tabLayout; 36 | private MainPagerAdapter mMainPagerAdapter; 37 | @Override 38 | protected void onCreate(Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | setContentView(R.layout.activity_main); 41 | getSupportActionBar().setTitle("豆逼 — 给你纯粹的欢乐"); 42 | ButterKnife.bind(this); 43 | getSupportActionBar().setDisplayHomeAsUpEnabled(false); 44 | getSupportActionBar().setDisplayShowHomeEnabled(true); 45 | tabLayout.setTabTextColors(getResources().getColor(R.color.whiteTrans80), getResources().getColor(R.color.white)); 46 | viewpager.setAdapter(mMainPagerAdapter = new MainPagerAdapter(getSupportFragmentManager())); 47 | tabLayout.setupWithViewPager(viewpager); 48 | } 49 | 50 | public class MainPagerAdapter extends FragmentStatePagerAdapter { 51 | 52 | public MainPagerAdapter(FragmentManager fm) { 53 | super(fm); 54 | } 55 | 56 | @Override 57 | public Fragment getItem(int position) { 58 | switch (position) { 59 | case 0: 60 | return new TextJoyFragment(); 61 | default: 62 | return new ImageJoyFragment(); 63 | } 64 | } 65 | 66 | @Override 67 | public CharSequence getPageTitle(int position) { 68 | switch (position) { 69 | case 0: 70 | return "段子"; 71 | default: 72 | return "图片"; 73 | } 74 | } 75 | 76 | @Override 77 | public int getCount() { 78 | return 2; 79 | } 80 | } 81 | 82 | @Override 83 | public boolean onCreateOptionsMenu(Menu menu) { 84 | // Inflate the menu; this adds items to the action bar if it is present. 85 | getMenuInflater().inflate(R.menu.menu_main, menu); 86 | return true; 87 | } 88 | 89 | @Override 90 | public boolean onOptionsItemSelected(MenuItem item) { 91 | // Handle action bar item clicks here. The action bar will 92 | // automatically handle clicks on the Home/Up button, so long 93 | // as you specify a parent activity in AndroidManifest.xml. 94 | int id = item.getItemId(); 95 | 96 | //noinspection SimplifiableIfStatement 97 | if (id == R.id.about) { 98 | startActivity(new Intent(this, AboutUsActivity.class)); 99 | return true; 100 | } 101 | 102 | return super.onOptionsItemSelected(item); 103 | } 104 | 105 | 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/main/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.main; 2 | 3 | import com.jude.beam.bijection.Presenter; 4 | 5 | /** 6 | * Created by Mr.Jude on 2015/8/20. 7 | */ 8 | public class MainPresenter extends Presenter { 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/setting/AboutUsActivity.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.setting; 2 | 3 | import android.os.Bundle; 4 | import android.widget.TextView; 5 | 6 | import com.jude.beam.bijection.RequiresPresenter; 7 | import com.jude.beam.expansion.BeamBaseActivity; 8 | import com.jude.joy.R; 9 | import com.jude.utils.JUtils; 10 | 11 | import butterknife.BindView; 12 | import butterknife.ButterKnife; 13 | 14 | /** 15 | * Created by Mr.Jude on 2015/8/14. 16 | */ 17 | 18 | @RequiresPresenter(AboutUsPresenter.class) 19 | public class AboutUsActivity extends BeamBaseActivity { 20 | 21 | @BindView(R.id.version) 22 | TextView version; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_about); 28 | ButterKnife.bind(this); 29 | version.setText("v"+ JUtils.getAppVersionName()); 30 | } 31 | 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/setting/AboutUsPresenter.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.setting; 2 | 3 | 4 | import com.jude.beam.bijection.Presenter; 5 | 6 | /** 7 | * Created by Mr.Jude on 2015/8/14. 8 | */ 9 | public class AboutUsPresenter extends Presenter { 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/text/TextJoyFragment.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.text; 2 | 3 | import android.view.ViewGroup; 4 | 5 | import com.jude.beam.bijection.RequiresPresenter; 6 | import com.jude.beam.expansion.list.BeamListFragment; 7 | import com.jude.beam.expansion.list.ListConfig; 8 | import com.jude.easyrecyclerview.adapter.BaseViewHolder; 9 | import com.jude.joy.model.bean.TextJoy; 10 | 11 | /** 12 | * Created by Mr.Jude on 2015/8/20. 13 | */ 14 | @RequiresPresenter(TextJoyPresenter.class) 15 | public class TextJoyFragment extends BeamListFragment { 16 | @Override 17 | public BaseViewHolder getViewHolder(ViewGroup viewGroup, int i) { 18 | return new TextJoyVH(viewGroup); 19 | } 20 | 21 | @Override 22 | public ListConfig getConfig() { 23 | return super.getConfig() 24 | .setLoadmoreAble(true) 25 | .setRefreshAble(true) 26 | .setNoMoreAble(true) 27 | .setErrorAble(true) 28 | .setErrorTouchToResumeAble(true); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/text/TextJoyPresenter.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.text; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.jude.beam.expansion.list.BeamListFragmentPresenter; 6 | import com.jude.joy.model.bean.TextJoy; 7 | import com.jude.joy.model.bean.TextJoyPage; 8 | import com.jude.joy.model.server.DaggerServiceModelComponent; 9 | import com.jude.joy.model.server.SchedulerTransform; 10 | import com.jude.joy.model.server.ServiceAPI; 11 | 12 | import javax.inject.Inject; 13 | 14 | /** 15 | * Created by Mr.Jude on 2015/8/20. 16 | */ 17 | public class TextJoyPresenter extends BeamListFragmentPresenter { 18 | @Inject 19 | ServiceAPI mServer; 20 | 21 | @Override 22 | protected void onCreate(TextJoyFragment view, Bundle savedState) { 23 | super.onCreate(view, savedState); 24 | DaggerServiceModelComponent.builder().build().inject(this); 25 | onRefresh(); 26 | } 27 | 28 | @Override 29 | public void onRefresh() { 30 | mServer.getTextJoyList(1) 31 | .compose(new SchedulerTransform<>()) 32 | .map(TextJoyPage::getContentlist) 33 | .doAfterTerminate(()-> setCurPage(2)) 34 | .unsafeSubscribe(getRefreshSubscriber()); 35 | } 36 | 37 | @Override 38 | public void onLoadMore() { 39 | mServer.getTextJoyList(getCurPage()) 40 | .compose(new SchedulerTransform<>()) 41 | .map(TextJoyPage::getContentlist) 42 | .unsafeSubscribe(getMoreSubscriber()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/module/text/TextJoyVH.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.module.text; 2 | 3 | import android.view.ViewGroup; 4 | import android.widget.TextView; 5 | 6 | import com.jude.easyrecyclerview.adapter.BaseViewHolder; 7 | import com.jude.joy.R; 8 | import com.jude.joy.model.bean.TextJoy; 9 | import com.jude.joy.utils.RecentDateFormat; 10 | import com.jude.joy.utils.TextFilter; 11 | import com.jude.utils.JTimeTransform; 12 | 13 | import butterknife.BindView; 14 | import butterknife.ButterKnife; 15 | 16 | /** 17 | * Created by Mr.Jude on 2015/8/20. 18 | */ 19 | public class TextJoyVH extends BaseViewHolder { 20 | @BindView(R.id.content) 21 | TextView content; 22 | @BindView(R.id.time) 23 | TextView time; 24 | 25 | public TextJoyVH(ViewGroup parent) { 26 | super(parent, R.layout.item_joy_text); 27 | ButterKnife.bind(this,itemView); 28 | } 29 | 30 | @Override 31 | public void setData(TextJoy data) { 32 | content.setText(TextFilter.filter(data.getText())); 33 | time.setText(new JTimeTransform().parse("yyyy-MM-dd hh:mm:ss",data.getCt()).toString(new RecentDateFormat())); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/utils/ImageFilter.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.utils; 2 | 3 | /** 4 | * Created by Mr.Jude on 2015/8/24. 5 | */ 6 | public class ImageFilter { 7 | public static String filter(String original){ 8 | return original.split("\"")[0]; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/utils/RecentDateFormat.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.utils; 2 | 3 | import com.jude.utils.JTimeTransform; 4 | 5 | public class RecentDateFormat implements JTimeTransform.DateFormat{ 6 | private String lastFormat; 7 | 8 | public RecentDateFormat() { 9 | this("MM-dd"); 10 | } 11 | 12 | public RecentDateFormat(String lastFormat) { 13 | this.lastFormat = lastFormat; 14 | } 15 | 16 | @Override 17 | public String format(JTimeTransform date, long delta) { 18 | if (delta>0){ 19 | if (delta / JTimeTransform.SECOND < 1){ 20 | return delta +"秒前"; 21 | }else if (delta / JTimeTransform.HOUR < 1){ 22 | return delta / JTimeTransform.SECOND+"分钟前"; 23 | }else if (delta / JTimeTransform.DAY < 2 && new JTimeTransform().getDay() == date.getDay()){ 24 | return delta / JTimeTransform.HOUR+"小时前"; 25 | }else if (delta / JTimeTransform.DAY < 3 && new JTimeTransform().getDay() == new JTimeTransform(date.getTimestamp()+JTimeTransform.DAY).getDay()){ 26 | return "昨天"+date.toString("HH:mm"); 27 | }else if (delta / JTimeTransform.DAY < 4 && new JTimeTransform().getDay() == new JTimeTransform(date.getTimestamp()+JTimeTransform.DAY*2).getDay()){ 28 | return "前天"+date.toString("HH:mm"); 29 | }else{ 30 | return date.toString(lastFormat); 31 | } 32 | }else{ 33 | delta = -delta; 34 | if (delta / JTimeTransform.SECOND < 1){ 35 | return delta +"秒后"; 36 | }else if (delta / JTimeTransform.HOUR < 1){ 37 | return delta / JTimeTransform.SECOND+"分钟后"; 38 | }else if (delta / JTimeTransform.DAY > -2 && new JTimeTransform().getDay() == date.getDay()){ 39 | return delta / JTimeTransform.HOUR+"小时后"; 40 | }else if (delta / JTimeTransform.DAY > -3 && new JTimeTransform().getDay() == new JTimeTransform(date.getTimestamp()-JTimeTransform.DAY).getDay()){ 41 | return "明天"+date.toString("HH:mm"); 42 | }else if (delta / JTimeTransform.DAY > -4 && new JTimeTransform().getDay() == new JTimeTransform(date.getTimestamp()-JTimeTransform.DAY*2).getDay()){ 43 | return "后天"+date.toString("HH:mm"); 44 | }else{ 45 | return date.toString(lastFormat); 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jude/joy/utils/TextFilter.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy.utils; 2 | 3 | import com.jude.utils.JUtils; 4 | 5 | /** 6 | * Created by Mr.Jude on 2015/8/24. 7 | */ 8 | public class TextFilter { 9 | public static String[] FilterStrings = { 10 | "

", 11 | "

", 12 | " ", 13 | "</pstyle=\\\"text-indent:2em;text-align:left;\\\">" 14 | }; 15 | 16 | public static String filter(String original){ 17 | JUtils.Log("index"+original.indexOf(FilterStrings[1])); 18 | for (String filterString : FilterStrings) { 19 | original = original.replace(filterString, ""); 20 | } 21 | return original; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 21 | 27 | 31 | 36 | 37 | 38 | 46 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 8 | 14 | 19 | 24 | 25 | 26 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_picture.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 19 | 20 | 24 | 25 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_joy_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 18 | 19 | 24 | 25 | 28 | 36 | 42 | 43 | 44 | 50 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_joy_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 19 | 20 | 26 | 32 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 |

4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jude95/Joy/c6a1992e7ef343b6b8270cb5ec7ae22ceaa1fc12/app/src/main/res/mipmap-hdpi/logo.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jude95/Joy/c6a1992e7ef343b6b8270cb5ec7ae22ceaa1fc12/app/src/main/res/mipmap-mdpi/logo.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jude95/Joy/c6a1992e7ef343b6b8270cb5ec7ae22ceaa1fc12/app/src/main/res/mipmap-xhdpi/logo.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jude95/Joy/c6a1992e7ef343b6b8270cb5ec7ae22ceaa1fc12/app/src/main/res/mipmap-xxhdpi/logo.png -------------------------------------------------------------------------------- /app/src/main/res/values-v19/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ff9800 4 | #ffffff 5 | #AFFF 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 豆逼 3 | 4 | Hello world! 5 | Settings 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 14 | 23 | 24 | 27 | 28 | 29 | 30 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/test/java/com/jude/joy/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.jude.joy; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.0-alpha4' 9 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | plugins { 16 | id "me.tatarka.retrolambda" version "3.2.0" 17 | } 18 | allprojects { 19 | repositories { 20 | jcenter() 21 | maven { url "https://jitpack.io" } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jude95/Joy/c6a1992e7ef343b6b8270cb5ec7ae22ceaa1fc12/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 20 15:30:39 CST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------