├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── helin │ │ └── rxsample │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── helin │ │ │ └── rxsample │ │ │ ├── MainActivity.java │ │ │ ├── base │ │ │ ├── ActivityLifeCycleEvent.java │ │ │ ├── BaseActivity.java │ │ │ └── BaseApplication.java │ │ │ ├── enity │ │ │ ├── HttpResult.java │ │ │ ├── Subject.java │ │ │ └── UserEntity.java │ │ │ ├── http │ │ │ ├── Api.java │ │ │ ├── ApiException.java │ │ │ ├── ApiService.java │ │ │ ├── HttpUtil.java │ │ │ ├── ProgressCancelListener.java │ │ │ ├── ProgressSubscriber.java │ │ │ ├── RetrofitCache.java │ │ │ ├── RxHelper.java │ │ │ └── Url.java │ │ │ ├── util │ │ │ └── LogUtils.java │ │ │ └── view │ │ │ └── SimpleLoadDialog.java │ └── res │ │ ├── drawable │ │ └── iosstyle_halftransparent_bg.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ └── custom_sload_layout.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── helin │ └── rxsample │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RxSample 2 | RxJava+Retrofit完美封装源码 3 | [Blog](http://www.jianshu.com/p/bd758f51742e) 4 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | defaultConfig { 7 | applicationId "com.helin.rxsample" 8 | minSdkVersion 14 9 | targetSdkVersion 23 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | repositories { 22 | jcenter() 23 | mavenCentral() 24 | maven { url "https://jitpack.io" } 25 | } 26 | configurations.all { 27 | resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0' 28 | } 29 | 30 | dependencies { 31 | compile fileTree(dir: 'libs', include: ['*.jar']) 32 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 33 | exclude group: 'com.android.support', module: 'support-annotations' 34 | }) 35 | compile 'com.android.support:appcompat-v7:23.4.0' 36 | testCompile 'junit:junit:4.12' 37 | compile 'io.reactivex:rxjava:1.1.0' 38 | compile 'io.reactivex:rxandroid:1.1.0' 39 | compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4' 40 | compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4' 41 | compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4' 42 | compile 'com.orhanobut:hawk:2.0.0-Alpha' 43 | compile 'com.github.ybq:Android-SpinKit:1.1.0' 44 | } 45 | -------------------------------------------------------------------------------- /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:\android\adt-bundle-windows-x86_64-20140702\sdk/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 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/helin/rxsample/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.helin.rxsample", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.widget.Button; 6 | import android.widget.TextView; 7 | import android.widget.Toast; 8 | 9 | import com.helin.rxsample.base.ActivityLifeCycleEvent; 10 | import com.helin.rxsample.base.BaseActivity; 11 | import com.helin.rxsample.enity.Subject; 12 | import com.helin.rxsample.http.Api; 13 | import com.helin.rxsample.http.HttpUtil; 14 | import com.helin.rxsample.http.ProgressSubscriber; 15 | import com.helin.rxsample.view.SimpleLoadDialog; 16 | 17 | import java.util.List; 18 | 19 | import rx.Observable; 20 | 21 | public class MainActivity extends BaseActivity { 22 | 23 | private TextView mText; 24 | private SimpleLoadDialog dialogHandler; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_main); 30 | dialogHandler = new SimpleLoadDialog(MainActivity.this, null, true); 31 | mText = (TextView) findViewById(R.id.text); 32 | ((Button) findViewById(R.id.btn)).setOnClickListener(new View.OnClickListener() { 33 | @Override 34 | public void onClick(View v) { 35 | // dialogHandler.obtainMessage(SimpleLoadDialog.SHOW_PROGRESS_DIALOG).sendToTarget(); 36 | doGet(); 37 | } 38 | }); 39 | } 40 | 41 | @Override 42 | public void onTrimMemory(int level) { 43 | super.onTrimMemory(level); 44 | } 45 | 46 | @Override 47 | protected void onPause() { 48 | super.onPause(); 49 | // dialogHandler.obtainMessage(SimpleLoadDialog.DISMISS_PROGRESS_DIALOG).sendToTarget(); 50 | } 51 | 52 | private void doGet() { 53 | //获取豆瓣电影TOP 100 54 | Observable ob = Api.getDefault().getTopMovie(0, 100); 55 | //嵌套请求 56 | // ob.flatMap(new Func1>>() { 57 | // 58 | // @Override 59 | // public Observable> call(String s) { 60 | // return Api.getDefault().getUser("aa"); 61 | // } 62 | // }); 63 | 64 | 65 | HttpUtil.getInstance().toSubscribe(ob, new ProgressSubscriber>(this) { 66 | @Override 67 | protected void _onError(String message) { 68 | Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show(); 69 | } 70 | 71 | @Override 72 | protected void _onNext(List list) { 73 | String str = ""; 74 | for (int i = 0; i < list.size(); i++) { 75 | str += "电影名:" + list.get(i).getTitle() + "\n"; 76 | } 77 | mText.setText(str); 78 | } 79 | }, "cacheKey", ActivityLifeCycleEvent.DESTROY, lifecycleSubject, false, false); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/base/ActivityLifeCycleEvent.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.base; 2 | 3 | /** 4 | * Created by helin on 2016/11/11 10:42. 5 | */ 6 | 7 | public enum ActivityLifeCycleEvent { 8 | CREATE, 9 | START, 10 | RESUME, 11 | PAUSE, 12 | STOP, 13 | DESTROY 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.base; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | 6 | import rx.subjects.PublishSubject; 7 | 8 | /** 9 | * Created by helin on 2016/11/11 10:41. 10 | */ 11 | 12 | public class BaseActivity extends AppCompatActivity { 13 | 14 | public final PublishSubject lifecycleSubject = PublishSubject.create(); 15 | 16 | // @NonNull 17 | // public Observable.Transformer bindUntilEvent(@NonNull final ActivityLifeCycleEvent event) { 18 | // return new Observable.Transformer() { 19 | // @Override 20 | // public Observable call(Observable sourceObservable) { 21 | // Observable compareLifecycleObservable = 22 | // lifecycleSubject.takeFirst(new Func1() { 23 | // @Override 24 | // public Boolean call(ActivityLifeCycleEvent activityLifeCycleEvent) { 25 | // return activityLifeCycleEvent.equals(event); 26 | // } 27 | // }); 28 | // return sourceObservable.takeUntil(compareLifecycleObservable); 29 | // } 30 | // }; 31 | // } 32 | 33 | 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | lifecycleSubject.onNext(ActivityLifeCycleEvent.CREATE); 38 | super.onCreate(savedInstanceState); 39 | } 40 | 41 | @Override 42 | protected void onPause() { 43 | lifecycleSubject.onNext(ActivityLifeCycleEvent.PAUSE); 44 | super.onPause(); 45 | } 46 | 47 | @Override 48 | protected void onStop() { 49 | lifecycleSubject.onNext(ActivityLifeCycleEvent.STOP); 50 | super.onStop(); 51 | } 52 | 53 | @Override 54 | protected void onDestroy() { 55 | super.onDestroy(); 56 | lifecycleSubject.onNext(ActivityLifeCycleEvent.DESTROY); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/base/BaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.base; 2 | 3 | import android.app.Application; 4 | 5 | import com.orhanobut.hawk.Hawk; 6 | 7 | /** 8 | * Created by helin on 2016/11/11 11:15. 9 | */ 10 | 11 | public class BaseApplication extends Application { 12 | @Override 13 | public void onCreate() { 14 | super.onCreate(); 15 | Hawk.init(this).build(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/enity/HttpResult.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.enity; 2 | 3 | /** 4 | * Created by helin on 2016/10/10 11:44. 5 | * 实体的基类 6 | */ 7 | public class HttpResult { 8 | 9 | //用来模仿resultCode和resultMessage 10 | private int count; 11 | //用来模仿Data 12 | private T subjects; 13 | 14 | public int getCount() { 15 | return count; 16 | } 17 | 18 | public void setCount(int count) { 19 | this.count = count; 20 | } 21 | 22 | public int getStart() { 23 | return start; 24 | } 25 | 26 | public void setStart(int start) { 27 | this.start = start; 28 | } 29 | 30 | public int getTotal() { 31 | return total; 32 | } 33 | 34 | public void setTotal(int total) { 35 | this.total = total; 36 | } 37 | 38 | public String getTitle() { 39 | return title; 40 | } 41 | 42 | public void setTitle(String title) { 43 | this.title = title; 44 | } 45 | 46 | public T getSubjects() { 47 | return subjects; 48 | } 49 | 50 | public void setSubjects(T subjects) { 51 | this.subjects = subjects; 52 | } 53 | 54 | private int start; 55 | private int total; 56 | private String title; 57 | 58 | // public T getData() { 59 | // return data; 60 | // } 61 | // 62 | // public void setData(T data) { 63 | // this.data = data; 64 | // } 65 | // 66 | // private int code; 67 | // 68 | // public int getCode() { 69 | // return code; 70 | // } 71 | // 72 | // public void setCode(int code) { 73 | // this.code = code; 74 | // } 75 | // 76 | // public String getMessage() { 77 | // return message; 78 | // } 79 | // 80 | // public void setMessage(String message) { 81 | // this.message = message; 82 | // } 83 | // 84 | // private String message; 85 | // 86 | // private T data; 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/enity/Subject.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.enity; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by liukun on 16/3/5. 7 | */ 8 | public class Subject { 9 | 10 | private String id; 11 | private String alt; 12 | private String year; 13 | private String title; 14 | private String original_title; 15 | private List genres; 16 | private List casts; 17 | private List directors; 18 | private Avatars images; 19 | 20 | @Override 21 | public String toString() { 22 | return "Subject.id=" + id 23 | + " Subject.title=" + title 24 | + " Subject.year=" + year 25 | + " Subject.originalTitle=" + original_title + casts.toString() + directors.toString() + " | "; 26 | } 27 | 28 | public String getId() { 29 | return id; 30 | } 31 | 32 | public void setId(String id) { 33 | this.id = id; 34 | } 35 | 36 | public String getAlt() { 37 | return alt; 38 | } 39 | 40 | public void setAlt(String alt) { 41 | this.alt = alt; 42 | } 43 | 44 | public String getYear() { 45 | return year; 46 | } 47 | 48 | public void setYear(String year) { 49 | this.year = year; 50 | } 51 | 52 | public String getTitle() { 53 | return title; 54 | } 55 | 56 | public void setTitle(String title) { 57 | this.title = title; 58 | } 59 | 60 | public String getOriginal_title() { 61 | return original_title; 62 | } 63 | 64 | public void setOriginal_title(String original_title) { 65 | this.original_title = original_title; 66 | } 67 | 68 | public List getGenres() { 69 | return genres; 70 | } 71 | 72 | public void setGenres(List genres) { 73 | this.genres = genres; 74 | } 75 | 76 | public List getCasts() { 77 | return casts; 78 | } 79 | 80 | public void setCasts(List casts) { 81 | this.casts = casts; 82 | } 83 | 84 | public List getDirectors() { 85 | return directors; 86 | } 87 | 88 | public void setDirectors(List directors) { 89 | this.directors = directors; 90 | } 91 | 92 | public Avatars getImages() { 93 | return images; 94 | } 95 | 96 | public void setImages(Avatars images) { 97 | this.images = images; 98 | } 99 | 100 | private class Cast{ 101 | private String id; 102 | private String name; 103 | private String alt; 104 | private Avatars avatars; 105 | 106 | public String getId() { 107 | return id; 108 | } 109 | 110 | public void setId(String id) { 111 | this.id = id; 112 | } 113 | 114 | public String getName() { 115 | return name; 116 | } 117 | 118 | public void setName(String name) { 119 | this.name = name; 120 | } 121 | 122 | public String getAlt() { 123 | return alt; 124 | } 125 | 126 | public void setAlt(String alt) { 127 | this.alt = alt; 128 | } 129 | 130 | public Avatars getAvatars() { 131 | return avatars; 132 | } 133 | 134 | public void setAvatars(Avatars avatars) { 135 | this.avatars = avatars; 136 | } 137 | 138 | @Override 139 | public String toString() { 140 | return "cast.id=" + id + " cast.name=" + name + " | "; 141 | } 142 | } 143 | 144 | private class Avatars{ 145 | private String small; 146 | private String medium; 147 | private String large; 148 | 149 | public String getSmall() { 150 | return small; 151 | } 152 | 153 | public void setSmall(String small) { 154 | this.small = small; 155 | } 156 | 157 | public String getMedium() { 158 | return medium; 159 | } 160 | 161 | public void setMedium(String medium) { 162 | this.medium = medium; 163 | } 164 | 165 | public String getLarge() { 166 | return large; 167 | } 168 | 169 | public void setLarge(String large) { 170 | this.large = large; 171 | } 172 | } 173 | } -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/enity/UserEntity.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.enity; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | /** 7 | * Created by helin on 2016/11/10 17:10. 8 | */ 9 | 10 | public class UserEntity implements Parcelable { 11 | public String getName() { 12 | return name; 13 | } 14 | 15 | 16 | public void setName(String name) { 17 | this.name = name; 18 | } 19 | 20 | public int getAge() { 21 | return age; 22 | } 23 | 24 | public void setAge(int age) { 25 | this.age = age; 26 | } 27 | 28 | private String name; 29 | private int age; 30 | 31 | @Override 32 | public int describeContents() { 33 | return 0; 34 | } 35 | 36 | @Override 37 | public void writeToParcel(Parcel dest, int flags) { 38 | dest.writeString(this.name); 39 | dest.writeInt(this.age); 40 | } 41 | 42 | public UserEntity() { 43 | } 44 | 45 | protected UserEntity(Parcel in) { 46 | this.name = in.readString(); 47 | this.age = in.readInt(); 48 | } 49 | 50 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 51 | @Override 52 | public UserEntity createFromParcel(Parcel source) { 53 | return new UserEntity(source); 54 | } 55 | 56 | @Override 57 | public UserEntity[] newArray(int size) { 58 | return new UserEntity[size]; 59 | } 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/http/Api.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.http; 2 | 3 | 4 | import java.io.IOException; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import okhttp3.HttpUrl; 8 | import okhttp3.Interceptor; 9 | import okhttp3.OkHttpClient; 10 | import okhttp3.Request; 11 | import retrofit2.Retrofit; 12 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; 13 | import retrofit2.converter.gson.GsonConverterFactory; 14 | 15 | /** 16 | * Created by helin on 2016/11/10 10:28. 17 | */ 18 | 19 | public class Api { 20 | private static ApiService SERVICE; 21 | /** 22 | * 请求超时时间 23 | */ 24 | private static final int DEFAULT_TIMEOUT = 10000; 25 | 26 | public static ApiService getDefault() { 27 | if (SERVICE == null) { 28 | //手动创建一个OkHttpClient并设置超时时间 29 | OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); 30 | httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); 31 | 32 | /** 33 | * 拦截器 34 | */ 35 | httpClientBuilder.addInterceptor(new Interceptor() { 36 | @Override 37 | public okhttp3.Response intercept(Chain chain) throws IOException { 38 | Request request = chain.request(); 39 | 40 | // Request.Builder requestBuilder = request.newBuilder(); 41 | // RequestBody formBody = new FormBody.Builder() 42 | // .add("1","2") 43 | // .build(); 44 | 45 | HttpUrl.Builder authorizedUrlBuilder = request.url() 46 | .newBuilder() 47 | //添加统一参数 如手机唯一标识符,token等 48 | .addQueryParameter("key1","value1") 49 | .addQueryParameter("key2", "value2"); 50 | 51 | Request newRequest = request.newBuilder() 52 | //对所有请求添加请求头 53 | .header("mobileFlag", "adfsaeefe").addHeader("type", "4") 54 | .method(request.method(), request.body()) 55 | .url(authorizedUrlBuilder.build()) 56 | .build(); 57 | 58 | // okhttp3.Response originalResponse = chain.proceed(request); 59 | // return originalResponse.newBuilder().header("mobileFlag", "adfsaeefe").addHeader("type", "4").build(); 60 | return chain.proceed(newRequest); 61 | } 62 | }); 63 | 64 | 65 | SERVICE = new Retrofit.Builder() 66 | .client(httpClientBuilder.build()) 67 | .addConverterFactory(GsonConverterFactory.create()) 68 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 69 | .baseUrl(Url.BASE_URL) 70 | .build().create(ApiService.class); 71 | } 72 | return SERVICE; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/http/ApiException.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.http; 2 | 3 | /** 4 | * Created by helin on 2016/10/10 11:52. 5 | */ 6 | 7 | public class ApiException extends RuntimeException{ 8 | 9 | public static final int USER_NOT_EXIST = 100; 10 | public static final int WRONG_PASSWORD = 101; 11 | private static String message; 12 | 13 | public ApiException(int resultCode) { 14 | this(getApiExceptionMessage(resultCode)); 15 | } 16 | 17 | public ApiException(String detailMessage) { 18 | super(detailMessage); 19 | } 20 | 21 | @Override 22 | public String getMessage() { 23 | return message; 24 | } 25 | 26 | /** 27 | * 由于服务器传递过来的错误信息直接给用户看的话,用户未必能够理解 28 | * 需要根据错误码对错误信息进行一个转换,在显示给用户 29 | * @param code 30 | * @return 31 | */ 32 | private static String getApiExceptionMessage(int code){ 33 | switch (code) { 34 | case USER_NOT_EXIST: 35 | message = "该用户不存在"; 36 | break; 37 | case WRONG_PASSWORD: 38 | message = "密码错误"; 39 | break; 40 | case 1000: 41 | message = "取消dialog"; 42 | break; 43 | default: 44 | message = "未知错误"; 45 | } 46 | return message; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/http/ApiService.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.http; 2 | 3 | 4 | import com.helin.rxsample.enity.HttpResult; 5 | import com.helin.rxsample.enity.Subject; 6 | import com.helin.rxsample.enity.UserEntity; 7 | 8 | import java.util.List; 9 | 10 | import retrofit2.http.GET; 11 | import retrofit2.http.Query; 12 | import rx.Observable; 13 | 14 | /** 15 | * Created by helin on 2016/10/9 17:09. 16 | */ 17 | 18 | public interface ApiService { 19 | @GET("/student/mobileRegister") 20 | Observable> login(@Query("phone") String phone, @Query("password") String psw); 21 | 22 | 23 | @GET("top250") 24 | Observable>> getTopMovie(@Query("start") int start, @Query("count") int count); 25 | 26 | @GET("top250") 27 | Observable> getUser( @Query("touken") String touken); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/http/HttpUtil.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.http; 2 | 3 | import com.helin.rxsample.base.ActivityLifeCycleEvent; 4 | import com.helin.rxsample.enity.HttpResult; 5 | 6 | import rx.Observable; 7 | import rx.functions.Action0; 8 | import rx.subjects.PublishSubject; 9 | 10 | /** 11 | * 12 | * 13 | // ┏┓   ┏┓ 14 | //┏┛┻━━━┛┻┓ 15 | //┃       ┃ 16 | //┃   ━   ┃ 17 | //┃ ┳┛ ┗┳ ┃ 18 | //┃       ┃ 19 | //┃   ┻   ┃ 20 | //┃       ┃ 21 | //┗━┓   ┏━┛ 22 | // ┃   ┃ 神兽保佑 23 | // ┃   ┃ 代码无BUG! 24 | // ┃   ┗━━━┓ 25 | // ┃       ┣┓ 26 | // ┃       ┏┛ 27 | // ┗┓┓┏━┳┓┏┛ 28 | // ┃┫┫ ┃┫┫ 29 | // ┗┻┛ ┗┻┛ 30 | * 31 | * Created by helin on 2016/10/10 11:32. 32 | */ 33 | 34 | public class HttpUtil { 35 | 36 | /** 37 | * 构造方法私有 38 | */ 39 | private HttpUtil() { 40 | //手动创建一个OkHttpClient并设置超时时间 41 | // OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); 42 | // httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); 43 | // /** 44 | // * 对所有请求添加请求头 45 | // */ 46 | // httpClientBuilder.addInterceptor(new Interceptor() { 47 | // @Override 48 | // public okhttp3.Response intercept(Chain chain) throws IOException { 49 | // Request request = chain.request(); 50 | // okhttp3.Response originalResponse = chain.proceed(request); 51 | // return originalResponse.newBuilder().header("mobileFlag", "adfsaeefe").addHeader("type", "4").build(); 52 | // } 53 | // }); 54 | // retrofit = new Retrofit.Builder() 55 | // .client(httpClientBuilder.build()) 56 | // .addConverterFactory(GsonConverterFactory.create()) 57 | // .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 58 | // .baseUrl(Url.BASE_URL) 59 | // .build(); 60 | 61 | } 62 | 63 | /** 64 | * 在访问HttpMethods时创建单例 65 | */ 66 | private static class SingletonHolder { 67 | private static final HttpUtil INSTANCE = new HttpUtil(); 68 | } 69 | 70 | /** 71 | * 获取单例 72 | */ 73 | public static HttpUtil getInstance() { 74 | return SingletonHolder.INSTANCE; 75 | } 76 | 77 | // public void getTopMovie(final ProgressSubscriber> subscriber, int start, int count) { 78 | // movieService = retrofit.create(ApiService.class); 79 | // Api.getDefault().getTopMovie(start, count) 80 | // .map(new HttpResultFunc>()) 81 | // .subscribeOn(Schedulers.io()) 82 | // .unsubscribeOn(Schedulers.io()) 83 | // .doOnSubscribe(new Action0() { 84 | // @Override 85 | // public void call() { 86 | // //显示Dialog 87 | // subscriber.showProgressDialog(); 88 | // } 89 | // }) 90 | // /** 91 | // * 保证doOnSubscribe是在主线程执行 92 | // */ 93 | // .subscribeOn(AndroidSchedulers.mainThread()) 94 | // .observeOn(AndroidSchedulers.mainThread()) 95 | // .subscribe(subscriber); 96 | // 97 | // toSubscribe(Api.getDefault().getTopMovie(start, count), subscriber,"getMove"); 98 | // } 99 | 100 | // public void userLogin(final ProgressSubscriber subscriber, String name, String psw) { 101 | // Observable observer = Api.getDefault().userLogin(name, psw, 4, "aaassdasd"); 102 | // .map(new HttpResultFunc2()); 103 | // .subscribeOn(Schedulers.io()) 104 | // .unsubscribeOn(Schedulers.io()) 105 | // .doOnSubscribe(new Action0() { 106 | // @Override 107 | // public void call() { 108 | // //显示Dialog 109 | // subscriber.showProgressDialog(); 110 | // } 111 | // }) 112 | // /** 113 | // * 保证doOnSubscribe是在主线程执行 114 | // */ 115 | // .subscribeOn(AndroidSchedulers.mainThread()) 116 | // .observeOn(AndroidSchedulers.mainThread()) 117 | // .subscribe(subscriber); 118 | 119 | // toSubscribe(observer, subscriber,"login"); 120 | // } 121 | 122 | 123 | 124 | 125 | /** 126 | * 添加线程管理并订阅 127 | * @param ob 128 | * @param subscriber 129 | * @param cacheKey 缓存kay 130 | * @param event Activity 生命周期 131 | * @param lifecycleSubject 132 | * @param isSave 是否缓存 133 | * @param forceRefresh 是否强制刷新 134 | */ 135 | public void toSubscribe(Observable ob, final ProgressSubscriber subscriber, String cacheKey, final ActivityLifeCycleEvent event, final PublishSubject lifecycleSubject,boolean isSave, boolean forceRefresh) { 136 | //数据预处理 137 | Observable.Transformer, Object> result = RxHelper.handleResult(event,lifecycleSubject); 138 | Observable observable = ob.compose(result) 139 | .doOnSubscribe(new Action0() { 140 | @Override 141 | public void call() { 142 | //显示Dialog和一些其他操作 143 | subscriber.showProgressDialog(); 144 | } 145 | }); 146 | RetrofitCache.load(cacheKey,observable,isSave,forceRefresh).subscribe(subscriber); 147 | 148 | 149 | // ob.subscribeOn(Schedulers.io()) 150 | // .unsubscribeOn(Schedulers.io()) 151 | // .doOnSubscribe(new Action0() { 152 | // @Override 153 | // public void call() { 154 | // //显示Dialog和一些其他操作 155 | // subscriber.showProgressDialog(); 156 | // } 157 | // }) 158 | // //保证doOnSubscribe是在主线程执行 159 | // .subscribeOn(AndroidSchedulers.mainThread()) 160 | // .observeOn(AndroidSchedulers.mainThread()) 161 | // .subscribe(subscriber); 162 | } 163 | 164 | 165 | /** 166 | * 废弃 167 | * @param 168 | */ 169 | // private class HttpResultFunc2 implements Func1, T> { 170 | // @Override 171 | // public T call(HttpResult httpResult) { 172 | // Log.e("error", httpResult.getData().toString() + ""); 173 | // if (httpResult.getCode() != 0) { 174 | // throw new ApiException(httpResult.getCode()); 175 | // } 176 | // return httpResult.getData(); 177 | // } 178 | // } 179 | 180 | /** 181 | * 用来统一处理Http的resultCode,并将HttpResult的Data部分剥离出来返回给subscriber 182 | * 183 | * @param Subscriber真正需要的数据类型,也就是Data部分的数据类型 184 | */ 185 | // private class HttpResultFunc implements Func1, T> { 186 | // 187 | // @Override 188 | // public T call(MoveHttpResult httpResult) { 189 | //// if (httpResult.getResultCode() != 0) { 190 | //// throw new ApiException(httpResult.getResultCode()); 191 | //// } 192 | //// return httpResult.getData(); 193 | // 194 | // if (httpResult.getCount() == 0) { 195 | // throw new ApiException(100); 196 | // } 197 | // return httpResult.getSubjects(); 198 | // 199 | // } 200 | // } 201 | } 202 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/http/ProgressCancelListener.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.http; 2 | 3 | /** 4 | * Created by helin on 2016/10/10 15:50. 5 | */ 6 | 7 | public interface ProgressCancelListener { 8 | void onCancelProgress(); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/http/ProgressSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.http; 2 | 3 | 4 | import android.content.Context; 5 | 6 | import com.helin.rxsample.view.SimpleLoadDialog; 7 | 8 | import rx.Subscriber; 9 | 10 | /** 11 | * Created by helin on 2016/10/10 15:49. 12 | */ 13 | 14 | public abstract class ProgressSubscriber extends Subscriber implements ProgressCancelListener{ 15 | 16 | 17 | private SimpleLoadDialog dialogHandler; 18 | 19 | public ProgressSubscriber(Context context) { 20 | dialogHandler = new SimpleLoadDialog(context,this,true); 21 | } 22 | 23 | @Override 24 | public void onCompleted() { 25 | dismissProgressDialog(); 26 | } 27 | 28 | 29 | /** 30 | * 显示Dialog 31 | */ 32 | public void showProgressDialog(){ 33 | if (dialogHandler != null) { 34 | // dialogHandler.obtainMessage(SimpleLoadDialog.SHOW_PROGRESS_DIALOG).sendToTarget(); 35 | dialogHandler.show(); 36 | } 37 | } 38 | 39 | @Override 40 | public void onNext(T t) { 41 | _onNext(t); 42 | } 43 | 44 | /** 45 | * 隐藏Dialog 46 | */ 47 | private void dismissProgressDialog(){ 48 | if (dialogHandler != null) { 49 | // dialogHandler.obtainMessage(SimpleLoadDialog.DISMISS_PROGRESS_DIALOG).sendToTarget(); 50 | dialogHandler.dismiss();; 51 | dialogHandler=null; 52 | } 53 | } 54 | @Override 55 | public void onError(Throwable e) { 56 | e.printStackTrace(); 57 | if (false) { //这里自行替换判断网络的代码 58 | _onError("网络不可用"); 59 | } else if (e instanceof ApiException) { 60 | _onError(e.getMessage()); 61 | } else { 62 | _onError("请求失败,请稍后再试..."); 63 | } 64 | dismissProgressDialog(); 65 | } 66 | 67 | 68 | @Override 69 | public void onCancelProgress() { 70 | if (!this.isUnsubscribed()) { 71 | this.unsubscribe(); 72 | } 73 | } 74 | protected abstract void _onNext(T t); 75 | protected abstract void _onError(String message); 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/http/RetrofitCache.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.http; 2 | 3 | import com.orhanobut.hawk.Hawk; 4 | 5 | import rx.Observable; 6 | import rx.Subscriber; 7 | import rx.android.schedulers.AndroidSchedulers; 8 | import rx.functions.Func1; 9 | import rx.schedulers.Schedulers; 10 | 11 | /** 12 | * Created by helin on 2016/11/10 10:41. 13 | */ 14 | 15 | public class RetrofitCache { 16 | /** 17 | * @param cacheKey 缓存的Key 18 | * @param fromNetwork 19 | * @param isSave 是否缓存 20 | * @param forceRefresh 是否强制刷新 21 | * @param 22 | * @return 23 | */ 24 | public static Observable load(final String cacheKey, 25 | Observable fromNetwork, 26 | boolean isSave, boolean forceRefresh) { 27 | Observable fromCache = Observable.create(new Observable.OnSubscribe() { 28 | @Override 29 | public void call(Subscriber subscriber) { 30 | T cache = (T) Hawk.get(cacheKey); 31 | if (cache != null) { 32 | subscriber.onNext(cache); 33 | } else { 34 | subscriber.onCompleted(); 35 | } 36 | } 37 | }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); 38 | //是否缓存 39 | if (isSave) { 40 | /** 41 | * 这里的fromNetwork 不需要指定Schedule,在handleRequest中已经变换了 42 | */ 43 | fromNetwork = fromNetwork.map(new Func1() { 44 | @Override 45 | public T call(T result) { 46 | Hawk.put(cacheKey, result); 47 | return result; 48 | } 49 | }); 50 | } 51 | //强制刷新 52 | if (forceRefresh) { 53 | return fromNetwork; 54 | } else { 55 | // return Observable.concat(fromCache, fromNetwork).first(); 56 | return Observable.concat(fromCache, fromNetwork).takeFirst(new Func1() { 57 | @Override 58 | public Boolean call(T t) { 59 | return t!=null; 60 | } 61 | }); 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/http/RxHelper.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.http; 2 | 3 | 4 | import android.support.annotation.NonNull; 5 | 6 | import com.helin.rxsample.base.ActivityLifeCycleEvent; 7 | import com.helin.rxsample.enity.HttpResult; 8 | 9 | import rx.Observable; 10 | import rx.Subscriber; 11 | import rx.android.schedulers.AndroidSchedulers; 12 | import rx.functions.Func1; 13 | import rx.schedulers.Schedulers; 14 | import rx.subjects.PublishSubject; 15 | 16 | /** 17 | * Created by helin on 2016/11/9 17:02. 18 | */ 19 | 20 | public class RxHelper { 21 | 22 | /** 23 | * 利用Observable.takeUntil()停止网络请求 24 | * 25 | * @param event 26 | * @param lifecycleSubject 27 | * @param 28 | * @return 29 | */ 30 | @NonNull 31 | public Observable.Transformer bindUntilEvent(@NonNull final ActivityLifeCycleEvent event, final PublishSubject lifecycleSubject) { 32 | return new Observable.Transformer() { 33 | @Override 34 | public Observable call(Observable sourceObservable) { 35 | Observable compareLifecycleObservable = 36 | lifecycleSubject.takeFirst(new Func1() { 37 | @Override 38 | public Boolean call(ActivityLifeCycleEvent activityLifeCycleEvent) { 39 | return activityLifeCycleEvent.equals(event); 40 | } 41 | }); 42 | return sourceObservable.takeUntil(compareLifecycleObservable); 43 | } 44 | }; 45 | } 46 | 47 | 48 | /** 49 | * @param 50 | * @return 51 | */ 52 | public static Observable.Transformer, T> handleResult(final ActivityLifeCycleEvent event, final PublishSubject lifecycleSubject) { 53 | return new Observable.Transformer, T>() { 54 | @Override 55 | public Observable call(Observable> tObservable) { 56 | Observable compareLifecycleObservable = 57 | lifecycleSubject.takeFirst(new Func1() { 58 | @Override 59 | public Boolean call(ActivityLifeCycleEvent activityLifeCycleEvent) { 60 | return activityLifeCycleEvent.equals(event); 61 | } 62 | }); 63 | return tObservable.flatMap(new Func1, Observable>() { 64 | @Override 65 | public Observable call(HttpResult result) { 66 | if (result.getCount() != 0) { 67 | return createData(result.getSubjects()); 68 | } else { 69 | return Observable.error(new ApiException(result.getCount())); 70 | } 71 | } 72 | }).takeUntil(compareLifecycleObservable).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).subscribeOn(AndroidSchedulers.mainThread()).observeOn(AndroidSchedulers.mainThread()); 73 | } 74 | }; 75 | } 76 | 77 | /** 78 | * 79 | * 80 | */ 81 | 82 | 83 | /** 84 | * 创建成功的数据 85 | * 86 | * @param data 87 | * @param 88 | * @return 89 | */ 90 | private static Observable createData(final T data) { 91 | return Observable.create(new Observable.OnSubscribe() { 92 | @Override 93 | public void call(Subscriber subscriber) { 94 | try { 95 | subscriber.onNext(data); 96 | subscriber.onCompleted(); 97 | } catch (Exception e) { 98 | subscriber.onError(e); 99 | } 100 | } 101 | }); 102 | 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/http/Url.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.http; 2 | 3 | public class Url { 4 | /** 5 | * 请求地址 6 | */ 7 | public static final String BASE_URL = "https://api.douban.com/v2/movie/"; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/util/LogUtils.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.util; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * This class can replace android.util.Log. 7 | * 8 | * @description And you can turn off the log by set DEBUG_LEVEL = Log.ASSERT. 9 | */ 10 | public final class LogUtils { 11 | 12 | /** 13 | * Don't let anyone instantiate this class. 14 | */ 15 | private LogUtils() { 16 | throw new Error("Do not need instantiate!"); 17 | } 18 | 19 | /** 20 | * Master switch.To catch error info you need set this value below Log.WARN 21 | */ 22 | public static final int DEBUG_LEVEL = 0; 23 | 24 | /** 25 | * 'System.out' switch.When it is true, you can see the 'System.out' log. 26 | * Otherwise, you cannot. 27 | */ 28 | public static final boolean DEBUG_SYSOUT = false; 29 | 30 | /** 31 | * Send a {@link Log#VERBOSE} log message. 32 | * 33 | * @param obj 34 | */ 35 | public static void v(Object obj) { 36 | if (Log.VERBOSE > DEBUG_LEVEL) { 37 | String tag = getClassName(); 38 | String msg = obj != null ? obj.toString() : "obj == null"; 39 | Log.v(tag, msg); 40 | } 41 | } 42 | 43 | /** 44 | * Send a {@link #DEBUG_LEVEL} log message. 45 | * 46 | * @param obj 47 | */ 48 | public static void d(Object obj) { 49 | if (Log.DEBUG > DEBUG_LEVEL) { 50 | String tag = getClassName(); 51 | String msg = obj != null ? obj.toString() : "obj == null"; 52 | Log.d(tag, msg); 53 | } 54 | } 55 | 56 | /** 57 | * Send an {@link Log#INFO} log message. 58 | * 59 | * @param obj 60 | */ 61 | public static void i(Object obj) { 62 | if (Log.INFO > DEBUG_LEVEL) { 63 | String tag = getClassName(); 64 | String msg = obj != null ? obj.toString() : "obj == null"; 65 | Log.i(tag, msg); 66 | } 67 | } 68 | 69 | /** 70 | * Send a {@link Log#WARN} log message. 71 | * 72 | * @param obj 73 | */ 74 | public static void w(Object obj) { 75 | if (Log.WARN > DEBUG_LEVEL) { 76 | String tag = getClassName(); 77 | String msg = obj != null ? obj.toString() : "obj == null"; 78 | Log.w(tag, msg); 79 | } 80 | } 81 | 82 | /** 83 | * Send an {@link Log#ERROR} log message. 84 | * 85 | * @param obj 86 | */ 87 | public static void e(Object obj) { 88 | if (Log.ERROR > DEBUG_LEVEL) { 89 | String tag = getClassName(); 90 | String msg = obj != null ? obj.toString() : "obj == null"; 91 | Log.e(tag, msg); 92 | } 93 | } 94 | 95 | /** 96 | * What a Terrible Failure: Report a condition that should never happen. The 97 | * error will always be logged at level ASSERT with the call stack. 98 | * Depending on system configuration, a report may be added to the 99 | * {@link android.os.DropBoxManager} and/or the process may be terminated 100 | * immediately with an error dialog. 101 | * 102 | * @param obj 103 | */ 104 | public static void wtf(Object obj) { 105 | if (Log.ASSERT > DEBUG_LEVEL) { 106 | String tag = getClassName(); 107 | String msg = obj != null ? obj.toString() : "obj == null"; 108 | Log.wtf(tag, msg); 109 | } 110 | } 111 | 112 | /** 113 | * Send a {@link Log#VERBOSE} log message. 114 | * 115 | * @param tag Used to identify the source of a log message. It usually 116 | * identifies the class or activity where the log call occurs. 117 | * @param msg The message you would like logged. 118 | */ 119 | public static void v(String tag, String msg) { 120 | if (Log.VERBOSE > DEBUG_LEVEL) { 121 | Log.v(tag, msg); 122 | } 123 | } 124 | 125 | /** 126 | * Send a {@link #DEBUG_LEVEL} log message. 127 | * 128 | * @param tag Used to identify the source of a log message. It usually 129 | * identifies the class or activity where the log call occurs. 130 | * @param msg The message you would like logged. 131 | */ 132 | public static void d(String tag, String msg) { 133 | if (Log.DEBUG > DEBUG_LEVEL) { 134 | Log.d(tag, msg); 135 | } 136 | } 137 | 138 | /** 139 | * Send an {@link Log#INFO} log message. 140 | * 141 | * @param tag Used to identify the source of a log message. It usually 142 | * identifies the class or activity where the log call occurs. 143 | * @param msg The message you would like logged. 144 | */ 145 | public static void i(String tag, String msg) { 146 | if (Log.INFO > DEBUG_LEVEL) { 147 | Log.i(tag, msg); 148 | } 149 | } 150 | 151 | /** 152 | * Send a {@link Log#WARN} log message. 153 | * 154 | * @param tag Used to identify the source of a log message. It usually 155 | * identifies the class or activity where the log call occurs. 156 | * @param msg The message you would like logged. 157 | */ 158 | public static void w(String tag, String msg) { 159 | if (Log.WARN > DEBUG_LEVEL) { 160 | Log.w(tag, msg); 161 | } 162 | } 163 | 164 | /** 165 | * Send an {@link Log#ERROR} log message. 166 | * 167 | * @param tag Used to identify the source of a log message. It usually 168 | * identifies the class or activity where the log call occurs. 169 | * @param msg The message you would like logged. 170 | */ 171 | public static void e(String tag, String msg) { 172 | if (Log.ERROR > DEBUG_LEVEL) { 173 | Log.e(tag, msg); 174 | } 175 | } 176 | 177 | /** 178 | * What a Terrible Failure: Report a condition that should never happen. The 179 | * error will always be logged at level ASSERT with the call stack. 180 | * Depending on system configuration, a report may be added to the 181 | * {@link android.os.DropBoxManager} and/or the process may be terminated 182 | * immediately with an error dialog. 183 | * 184 | * @param tag Used to identify the source of a log message. 185 | * @param msg The message you would like logged. 186 | */ 187 | public static void wtf(String tag, String msg) { 188 | if (Log.ASSERT > DEBUG_LEVEL) { 189 | Log.wtf(tag, msg); 190 | } 191 | } 192 | 193 | /** 194 | * Send a {@link Log#VERBOSE} log message. And just print method name and 195 | * position in black. 196 | */ 197 | public static void print() { 198 | if (Log.VERBOSE > DEBUG_LEVEL) { 199 | String tag = getClassName(); 200 | String method = callMethodAndLine(); 201 | Log.v(tag, method); 202 | if (DEBUG_SYSOUT) { 203 | System.out.println(tag + " " + method); 204 | } 205 | } 206 | } 207 | 208 | /** 209 | * Send a {@link #DEBUG_LEVEL} log message. 210 | * 211 | * @param object The object to print. 212 | */ 213 | public static void print(Object object) { 214 | if (Log.DEBUG > DEBUG_LEVEL) { 215 | String tag = getClassName(); 216 | String method = callMethodAndLine(); 217 | String content = ""; 218 | if (object != null) { 219 | content = object.toString() + " ---- " 220 | + method; 221 | } else { 222 | content = " ## " + " ---- " + method; 223 | } 224 | Log.d(tag, content); 225 | if (DEBUG_SYSOUT) { 226 | System.out.println(tag + " " + content + " " + method); 227 | } 228 | } 229 | } 230 | 231 | /** 232 | * Send an {@link Log#ERROR} log message. 233 | * 234 | * @param object The object to print. 235 | */ 236 | public static void printError(Object object) { 237 | if (Log.ERROR > DEBUG_LEVEL) { 238 | String tag = getClassName(); 239 | String method = callMethodAndLine(); 240 | String content = ""; 241 | if (object != null) { 242 | content = object.toString() + " ---- " 243 | + method; 244 | } else { 245 | content = " ## " + " ---- " + method; 246 | } 247 | Log.e(tag, content); 248 | if (DEBUG_SYSOUT) { 249 | System.err.println(tag + " " + method + " " + content); 250 | } 251 | } 252 | } 253 | 254 | /** 255 | * Print the array of stack trace elements of this method in black. 256 | * 257 | * @return 258 | */ 259 | public static void printCallHierarchy() { 260 | if (Log.VERBOSE > DEBUG_LEVEL) { 261 | String tag = getClassName(); 262 | String method = callMethodAndLine(); 263 | String hierarchy = getCallHierarchy(); 264 | Log.v(tag, method + hierarchy); 265 | if (DEBUG_SYSOUT) { 266 | System.out.println(tag + " " + method + hierarchy); 267 | } 268 | } 269 | } 270 | 271 | /** 272 | * Print debug log in blue. 273 | * 274 | * @param object The object to print. 275 | */ 276 | public static void printMyLog(Object object) { 277 | if (Log.DEBUG > DEBUG_LEVEL) { 278 | String tag = "MYLOG"; 279 | String method = callMethodAndLine(); 280 | String content = ""; 281 | if (object != null) { 282 | content = object.toString() + " ---- " 283 | + method; 284 | } else { 285 | content = " ## " + " ---- " + method; 286 | } 287 | Log.d(tag, content); 288 | if (DEBUG_SYSOUT) { 289 | System.out.println(tag + " " + content + " " + method); 290 | } 291 | } 292 | } 293 | 294 | private static String getCallHierarchy() { 295 | String result = ""; 296 | StackTraceElement[] trace = (new Exception()).getStackTrace(); 297 | for (int i = 2; i < trace.length; i++) { 298 | result += "\r\t" + trace[i].getClassName() + "." 299 | + trace[i].getMethodName() + "():" 300 | + trace[i].getLineNumber(); 301 | } 302 | return result; 303 | } 304 | 305 | private static String getClassName() { 306 | String result = ""; 307 | StackTraceElement thisMethodStack = (new Exception()).getStackTrace()[2]; 308 | result = thisMethodStack.getClassName(); 309 | return result; 310 | } 311 | 312 | /** 313 | * Realization of double click jump events. 314 | * 315 | * @return 316 | */ 317 | private static String callMethodAndLine() { 318 | String result = "at "; 319 | StackTraceElement thisMethodStack = (new Exception()).getStackTrace()[2]; 320 | result += thisMethodStack.getClassName() + "."; 321 | result += thisMethodStack.getMethodName(); 322 | result += "(" + thisMethodStack.getFileName(); 323 | result += ":" + thisMethodStack.getLineNumber() + ") "; 324 | return result; 325 | } 326 | 327 | } 328 | -------------------------------------------------------------------------------- /app/src/main/java/com/helin/rxsample/view/SimpleLoadDialog.java: -------------------------------------------------------------------------------- 1 | package com.helin.rxsample.view; 2 | 3 | import android.app.Activity; 4 | import android.app.Dialog; 5 | import android.content.Context; 6 | import android.content.DialogInterface; 7 | import android.os.Handler; 8 | import android.os.Message; 9 | import android.view.Gravity; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.Window; 13 | 14 | import com.helin.rxsample.R; 15 | import com.helin.rxsample.http.ProgressCancelListener; 16 | 17 | import java.lang.ref.WeakReference; 18 | 19 | 20 | /** 21 | * 22 | */ 23 | public class SimpleLoadDialog extends Handler{ 24 | 25 | private Dialog load = null; 26 | 27 | public static final int SHOW_PROGRESS_DIALOG = 1; 28 | public static final int DISMISS_PROGRESS_DIALOG = 2; 29 | 30 | private Context context; 31 | private boolean cancelable; 32 | private ProgressCancelListener mProgressCancelListener; 33 | private final WeakReference reference; 34 | 35 | public SimpleLoadDialog(Context context, ProgressCancelListener mProgressCancelListener, 36 | boolean cancelable) { 37 | super(); 38 | this.reference = new WeakReference(context); 39 | this.mProgressCancelListener = mProgressCancelListener; 40 | this.cancelable = cancelable; 41 | } 42 | 43 | private void create(){ 44 | if (load == null) { 45 | context = reference.get(); 46 | 47 | load = new Dialog(context, R.style.loadstyle); 48 | View dialogView = LayoutInflater.from(context).inflate( 49 | R.layout.custom_sload_layout, null); 50 | load.setCanceledOnTouchOutside(false); 51 | load.setCancelable(cancelable); 52 | load.setContentView(dialogView); 53 | load.setOnCancelListener(new DialogInterface.OnCancelListener() { 54 | @Override 55 | public void onCancel(DialogInterface dialog) { 56 | if(mProgressCancelListener!=null) 57 | mProgressCancelListener.onCancelProgress(); 58 | } 59 | }); 60 | Window dialogWindow = load.getWindow(); 61 | dialogWindow.setGravity(Gravity.CENTER_VERTICAL 62 | | Gravity.CENTER_HORIZONTAL); 63 | } 64 | if (!load.isShowing()&&context!=null) { 65 | load.show(); 66 | } 67 | } 68 | 69 | public void show(){ 70 | create(); 71 | } 72 | 73 | 74 | public void dismiss() { 75 | context = reference.get(); 76 | if (load != null&&load.isShowing()&&!((Activity) context).isFinishing()) { 77 | String name = Thread.currentThread().getName(); 78 | load.dismiss(); 79 | load = null; 80 | } 81 | } 82 | 83 | @Override 84 | public void handleMessage(Message msg) { 85 | switch (msg.what) { 86 | case SHOW_PROGRESS_DIALOG: 87 | create(); 88 | break; 89 | case DISMISS_PROGRESS_DIALOG: 90 | dismiss(); 91 | break; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/iosstyle_halftransparent_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 |