bindOnDestroy() {
75 | return bindUntilEvent(ActivityEvent.onDestory);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/rxlifecycle2/src/main/java/com/dhh/rxlifecycle2/RxLifecycle.java:
--------------------------------------------------------------------------------
1 | package com.dhh.rxlifecycle2;
2 |
3 | import android.app.Activity;
4 | import android.app.Application;
5 | import android.app.Fragment;
6 | import android.app.FragmentManager;
7 | import android.content.Context;
8 | import android.content.ContextWrapper;
9 | import android.support.v4.app.FragmentActivity;
10 | import android.support.v7.app.AppCompatActivity;
11 | import android.view.View;
12 |
13 | import java.lang.reflect.Field;
14 |
15 | /**
16 | * Created by dhh on 2017/9/25.
17 | */
18 |
19 | public final class RxLifecycle {
20 | private static final String FRAGMENT_TAG = "lifecycle2_tag";
21 |
22 | private RxLifecycle() {
23 | throw new RuntimeException("No instances");
24 | }
25 |
26 | /**
27 | * use in {@link Activity} onCreate
28 | * {@code
29 | * public class BaseActivity extends AppCompatActivity {
30 | * protected void onCreate(Bundle savedInstanceState) {
31 | * super.onCreate(savedInstanceState);
32 | * RxLifecycle.injectRxLifecycle(this);
33 | * }
34 | * }
35 | * }
36 | *
37 | * @param activity
38 | */
39 | public static void injectRxLifecycle(Activity activity) {
40 | with(activity);
41 | }
42 |
43 | /**
44 | * use in {@link Application} oncreate
45 | * {@code
46 | * public class RxLifecycleAPP extends Application {
47 | * public void onCreate() {
48 | * super.onCreate();
49 | * RxLifecycle.injectRxLifecycle(this);
50 | * }
51 | * }
52 | * }
53 | *
54 | * @param application
55 | */
56 | public static void injectRxLifecycle(Application application) {
57 | application.registerActivityLifecycleCallbacks(new ActivityRxLifecycleCallbacks());
58 | }
59 |
60 | public static LifecycleManager with(Activity activity) {
61 | if (activity instanceof FragmentActivity) {
62 | return with((FragmentActivity) activity);
63 | }
64 | FragmentManager fm = activity.getFragmentManager();
65 | Fragment fragment = fm.findFragmentByTag(FRAGMENT_TAG);
66 | if (fragment == null) {
67 | fragment = new LifecycleFragment();
68 | fm.beginTransaction().add(fragment, FRAGMENT_TAG).commitAllowingStateLoss();
69 | fm.executePendingTransactions();
70 | }
71 | return (LifecycleManager) fragment;
72 | }
73 |
74 | private static LifecycleManager with(FragmentActivity activity) {
75 | android.support.v4.app.FragmentManager fm = activity.getSupportFragmentManager();
76 | android.support.v4.app.Fragment fragment = fm.findFragmentByTag(FRAGMENT_TAG);
77 | if (fragment == null) {
78 | fragment = new LifecycleV4Fragment();
79 | fm.beginTransaction().add(fragment, FRAGMENT_TAG).commitNowAllowingStateLoss();
80 | }
81 |
82 | return (LifecycleManager) fragment;
83 | }
84 |
85 | public static LifecycleManager with(Fragment fragment) {
86 | return with(fragment.getActivity());
87 | }
88 |
89 | public static LifecycleManager with(android.support.v4.app.Fragment fragment) {
90 | return with(fragment.getActivity());
91 | }
92 |
93 | /**
94 | * @param context ensure context can be cast {@link Activity}
95 | */
96 | public static LifecycleManager with(Context context) {
97 | if (context instanceof AppCompatActivity) {
98 | return with((FragmentActivity) context);
99 | }
100 | if (context instanceof Activity) {
101 | return with((Activity) context);
102 | }
103 | if (context instanceof ContextWrapper) {
104 | return with(((ContextWrapper) context).getBaseContext());
105 | }
106 | throw new ClassCastException(context.getClass().getSimpleName() + " can\'t cast Activity !");
107 | }
108 |
109 | public static LifecycleManager with(View view) {
110 | return with(view.getContext());
111 | }
112 |
113 |
114 | private static void injectRxLifecycle(Object object) {
115 | if (object instanceof View) {
116 | with((View) object);
117 | } else {
118 | with(object);
119 | }
120 | }
121 |
122 | private static LifecycleManager with(Object object) {
123 | if (object instanceof Context) {
124 | return with((Context) object);
125 | }
126 | for (Field field : object.getClass().getDeclaredFields()) {
127 | try {
128 | field.setAccessible(true);
129 | Object value = field.get(object);
130 | if (value instanceof Context) {
131 | return with((Context) value);
132 | }
133 |
134 | } catch (IllegalAccessException e) {
135 | e.printStackTrace();
136 | }
137 | }
138 | throw new ClassCastException(object.getClass().getSimpleName() + " can\'t convert Context !");
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/rxlifecycle2/src/main/java/com/dhh/rxlifecycle2/retrofit/HttpHelper.java:
--------------------------------------------------------------------------------
1 | package com.dhh.rxlifecycle2.retrofit;
2 |
3 | import android.support.annotation.Nullable;
4 |
5 | import com.dhh.rxlifecycle2.LifecycleManager;
6 |
7 | import okhttp3.OkHttpClient;
8 | import retrofit2.CallAdapter;
9 | import retrofit2.Converter;
10 | import retrofit2.Retrofit;
11 |
12 | /**
13 | * Created by dhh on 2017/10/11.
14 | */
15 |
16 | public class HttpHelper {
17 | private static HttpHelper instance;
18 | public String baseUrl;
19 | private OkHttpClient client;
20 | private CallAdapter.Factory callAdapterFactory;
21 | private Converter.Factory converterFactory;
22 |
23 | private HttpHelper() {
24 | try {
25 | Class.forName("okhttp3.OkHttpClient");
26 | } catch (ClassNotFoundException e) {
27 | throw new RuntimeException("Must be dependency retrofit2 !");
28 | }
29 | client = new OkHttpClient.Builder()
30 | //other config ...
31 |
32 | .build();
33 | callAdapterFactory = RxJava2LifecycleCallAdapterFactory.create();
34 | }
35 |
36 | public static HttpHelper getInstance() {
37 | if (instance == null) {
38 | synchronized (HttpHelper.class) {
39 | if (instance == null) {
40 | instance = new HttpHelper();
41 | }
42 | }
43 | }
44 | return instance;
45 | }
46 |
47 | /**
48 | * 不带生命周期自动绑定的
49 | *
50 | * @param service
51 | * @param baseUrl
52 | * @param
53 | * @return
54 | */
55 | public T create(Class service, String baseUrl) {
56 | Retrofit retrofit = new Retrofit.Builder()
57 | .baseUrl(baseUrl)
58 | .addCallAdapterFactory(callAdapterFactory)
59 | .addConverterFactory(checkNotNull(converterFactory, "converterFactory == null"))
60 | .client(client)
61 | .build();
62 | return retrofit.create(service);
63 | }
64 |
65 | /**
66 | * 不带生命周期自动绑定的
67 | *
68 | * @param service
69 | * @param
70 | * @return
71 | */
72 | public T create(Class service) {
73 | return create(service, baseUrl);
74 | }
75 |
76 | /**
77 | * 带生命周期自动绑定的
78 | *
79 | * @param service
80 | * @param baseUrl
81 | * @param lifecycleManager
82 | * @param
83 | * @return
84 | */
85 | public T createWithLifecycleManager(Class service, String baseUrl, LifecycleManager lifecycleManager) {
86 | Retrofit retrofit = new Retrofit.Builder()
87 | .baseUrl(baseUrl)
88 | .addCallAdapterFactory(RxJava2LifecycleCallAdapterFactory.createWithLifecycleManager(lifecycleManager))
89 | .addConverterFactory(checkNotNull(converterFactory, "converterFactory == null"))
90 | .client(client)
91 | .build();
92 | return retrofit.create(service);
93 | }
94 |
95 | /**
96 | * 带生命周期自动绑定的
97 | *
98 | * @param service
99 | * @param lifecycleManager
100 | * @param
101 | * @return
102 | */
103 | public T createWithLifecycleManager(Class service, LifecycleManager lifecycleManager) {
104 | return createWithLifecycleManager(service, baseUrl, lifecycleManager);
105 | }
106 |
107 | public void setBaseUrl(String baseUrl) {
108 | this.baseUrl = checkNotNull(baseUrl, "baseUrl == null");
109 | }
110 |
111 | public OkHttpClient getClient() {
112 | return client;
113 | }
114 |
115 | public void setClient(OkHttpClient client) {
116 | this.client = checkNotNull(client, "client == null");
117 | }
118 |
119 | public void setConverterFactory(Converter.Factory converterFactory) {
120 | this.converterFactory = checkNotNull(converterFactory, "converterFactory == null");
121 | }
122 |
123 | static T checkNotNull(@Nullable T object, String message) {
124 | if (object == null) {
125 | throw new NullPointerException(message);
126 | }
127 | return object;
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/rxlifecycle2/src/main/java/com/dhh/rxlifecycle2/retrofit/RxJava2LifecycleCallAdapterFactory.java:
--------------------------------------------------------------------------------
1 | package com.dhh.rxlifecycle2.retrofit;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 |
6 | import com.dhh.rxlifecycle2.LifecycleManager;
7 |
8 | import java.lang.annotation.Annotation;
9 | import java.lang.reflect.Type;
10 |
11 | import io.reactivex.Observable;
12 | import io.reactivex.schedulers.Schedulers;
13 | import retrofit2.Call;
14 | import retrofit2.CallAdapter;
15 | import retrofit2.Retrofit;
16 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
17 |
18 | /**
19 | * Created by dhh on 2017/10/10.
20 | */
21 |
22 | public class RxJava2LifecycleCallAdapterFactory extends CallAdapter.Factory {
23 |
24 | private static CallAdapter.Factory adapterFactory;
25 | private LifecycleManager lifecycleManager;
26 |
27 | private RxJava2LifecycleCallAdapterFactory(LifecycleManager lifecycleManager) {
28 | this.lifecycleManager = lifecycleManager;
29 | try {
30 | Class.forName("retrofit2.Retrofit");
31 | } catch (ClassNotFoundException e) {
32 | throw new RuntimeException("Must be dependency retrofit2 !");
33 | }
34 | if (adapterFactory == null) {
35 | try {
36 | Class.forName("retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory");
37 | } catch (ClassNotFoundException e) {
38 | throw new RuntimeException("Must be dependency RxJava2CallAdapterFactory !");
39 | }
40 | adapterFactory = RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io());
41 | }
42 | }
43 |
44 | public static CallAdapter.Factory create() {
45 | try {
46 | Class.forName("retrofit2.Retrofit");
47 | } catch (ClassNotFoundException e) {
48 | throw new RuntimeException("Must be dependency retrofit2 !");
49 | }
50 | if (adapterFactory == null) {
51 | try {
52 | Class.forName("retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory");
53 | } catch (ClassNotFoundException e) {
54 | throw new RuntimeException("Must be dependency RxJava2CallAdapterFactory !");
55 | }
56 | adapterFactory = RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io());
57 | }
58 | return adapterFactory;
59 | }
60 |
61 | /**
62 | * 确保你注入的factory内部是RxJava2CallAdapterFactory
63 | *
64 | * @param factory
65 | */
66 | public static void injectCallAdapterFactory(CallAdapter.Factory factory) {
67 | RxJava2LifecycleCallAdapterFactory.adapterFactory = factory;
68 | }
69 |
70 | public static CallAdapter.Factory createWithLifecycleManager(LifecycleManager lifecycleManager) {
71 | if (lifecycleManager == null) throw new NullPointerException("lifecycleManager == null");
72 | return new RxJava2LifecycleCallAdapterFactory(lifecycleManager);
73 | }
74 |
75 | @Nullable
76 | @Override
77 | public CallAdapter, ?> get(@NonNull Type returnType, @NonNull Annotation[] annotations, @NonNull Retrofit retrofit) {
78 | return new RxJavaLifecycleCallAdapter<>(adapterFactory.get(returnType, annotations, retrofit), lifecycleManager);
79 | }
80 |
81 | private static final class RxJavaLifecycleCallAdapter implements CallAdapter> {
82 | private CallAdapter callAdapter;
83 | private LifecycleManager lifecycleManager;
84 |
85 | public RxJavaLifecycleCallAdapter(CallAdapter callAdapter, LifecycleManager lifecycleManager) {
86 | this.callAdapter = callAdapter;
87 | this.lifecycleManager = lifecycleManager;
88 | }
89 |
90 | @Override
91 | public Type responseType() {
92 | return callAdapter.responseType();
93 | }
94 |
95 | @Override
96 | public Observable> adapt(@NonNull Call call) {
97 | Observable> observable = (Observable) callAdapter.adapt(call);
98 | return observable
99 | .compose(lifecycleManager.bindOnDestroy())
100 | .subscribeOn(Schedulers.io());
101 | }
102 |
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/rxlifecycle2/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | RxLifecycle2
3 |
4 |
--------------------------------------------------------------------------------
/rxlifecycle2/src/test/java/com/dhh/rxlifecycle2/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.dhh.rxlifecycle2;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/rxliffecycle-retrofit.md:
--------------------------------------------------------------------------------
1 | ## RxLifecycle-Retrofit
2 | ### 首先说明这个方式的实现原理是:通过自定义CallAdapterFactory,将Observable与activity绑定.每一个Activity绑定一个retrofit客户端,在每次创建service接口的时候,都要重新初始化Retrofit客户端,禁止复用.
3 | ### 这个模块只有两个类:
4 | - HttpHelper : 示例工具类,创建和界面绑定的service接口.可以直使用.
5 | - RxJavaLifecycleCallAdapterFactory : RxJavaCallAdapterFactory扩展类,将接口请求绑定到对应Activity的onDestroy.
6 | ### gradle依赖不变:
7 | ```
8 | //RxJava1
9 | compile 'com.dhh:rxlifecycle:1.5'
10 | //RxJava2
11 | compile 'com.dhh:rxlifecycle2:1.5'
12 |
13 | ```
14 | ## How to use
15 |
16 | ### 一. 如果你自己没有自定义RxJavaCallAdapterFactory,直接忽略这条操作.若你已经自定义了一个XXXRxJavaCallAdapterFactory(不是Retrofit自带的那个),又想使用本库提供的RxJavaLifecycleCallAdapterFactory,那么你需要这么做:
17 | ###在你项目的Application的onCreate方法中进行初始化:
18 | ```
19 | //RxJava1
20 | RxJavaLifecycleCallAdapterFactory.injectCallAdapterFactory(yourFactory);
21 | //RxJava2
22 | RxJava2LifecycleCallAdapterFactory.injectCallAdapterFactory(yourFactory);
23 |
24 |
25 | ```
26 | ## ★★★ 如果在你的项目里没有自定义 XXXRxJavaCallAdapterFactory,请忽略第一步的配置.
27 | ### 二. 在使用retrofit将接口实例化的时候,切记一定要一同初始化一个新的Retrofit客户端,在addCallAdapterFactory的时候用项目里提供的RxJavaLifecycleCallAdapterFactory.createWithLifecycleManager(lifecycleManager),你可以在自己的项目里封装一个HttpHelper类,单例模式,将okhttpClient,以及baseUrl等等相关配置的东西都预先处理好,库里提供了一个HttpHelper类,你可以参考这个类,进行扩展,代码如下:
28 | ```
29 |
30 | public class HttpHelper {
31 | private static HttpHelper instance;
32 | public String baseUrl;
33 | private OkHttpClient client;
34 | private CallAdapter.Factory callAdapterFactory;
35 | private Converter.Factory converterFactory;
36 |
37 | public HttpHelper() {
38 | client = new OkHttpClient.Builder()
39 | //other config ...
40 |
41 | .build();
42 | callAdapterFactory = RxJavaLifecycleCallAdapterFactory.create();
43 | }
44 |
45 | public static HttpHelper getInstance() {
46 | if (instance == null) {
47 | synchronized (HttpHelper.class) {
48 | if (instance == null) {
49 | instance = new HttpHelper();
50 | }
51 | }
52 | }
53 | return instance;
54 | }
55 |
56 | /**
57 | * 不带生命周期自动绑定的
58 | *
59 | * @param service
60 | * @param baseUrl
61 | * @param
62 | * @return
63 | */
64 | public T create(Class service, String baseUrl) {
65 | Retrofit retrofit = new Retrofit.Builder()
66 | .baseUrl(baseUrl)
67 | .addCallAdapterFactory(callAdapterFactory)
68 | .addConverterFactory(checkNotNull(converterFactory,"converterFactory == null"))
69 | .client(client)
70 | .build();
71 | return retrofit.create(service);
72 | }
73 |
74 | /**
75 | * 不带生命周期自动绑定的
76 | *
77 | * @param service
78 | * @param
79 | * @return
80 | */
81 | public T create(Class service) {
82 | return create(service, baseUrl);
83 | }
84 |
85 | /**
86 | * 带生命周期自动绑定的
87 | *
88 | * @param service
89 | * @param baseUrl
90 | * @param lifecycleManager
91 | * @param
92 | * @return
93 | */
94 | public T createWithLifecycleManager(Class service, String baseUrl, LifecycleManager lifecycleManager) {
95 | Retrofit retrofit = new Retrofit.Builder()
96 | .baseUrl(baseUrl)
97 | .addCallAdapterFactory(RxJavaLifecycleCallAdapterFactory.createWithLifecycleManager(lifecycleManager))
98 | .addConverterFactory(checkNotNull(converterFactory,"converterFactory == null"))
99 | .client(client)
100 | .build();
101 | return retrofit.create(service);
102 | }
103 |
104 | /**
105 | * 带生命周期自动绑定的
106 | *
107 | * @param service
108 | * @param lifecycleManager
109 | * @param
110 | * @return
111 | */
112 | public T createWithLifecycleManager(Class service, LifecycleManager lifecycleManager) {
113 | return createWithLifecycleManager(service, baseUrl, lifecycleManager);
114 | }
115 |
116 | public void setBaseUrl(String baseUrl) {
117 | this.baseUrl = checkNotNull(baseUrl,"baseUrl == null");
118 | }
119 |
120 | public OkHttpClient getClient() {
121 | return client;
122 | }
123 |
124 | public void setClient(OkHttpClient client) {
125 | this.client = checkNotNull(client,"client == null");
126 | }
127 |
128 | public void setConverterFactory(Converter.Factory converterFactory) {
129 | this.converterFactory = checkNotNull(converterFactory,"converterFactory == null");
130 | }
131 | static T checkNotNull(@Nullable T object, String message) {
132 | if (object == null) {
133 | throw new NullPointerException(message);
134 | }
135 | return object;
136 | }
137 | }
138 |
139 | ```
140 | ### 其中 createWithLifecycleManager方法是核心方法,将LifecycleManager传入.
141 | ### 如果你使用项目提供的HttpHelper,在使用前必须做一些必要的初始化:
142 | ```
143 |
144 | HttpHelper.getInstance().setBaseUrl(baseUrl);
145 | HttpHelper.getInstance().setClient(new OkHttpClient());
146 | HttpHelper.getInstance().setConverterFactory(GsonConverterFactory.create());
147 |
148 | ```
149 | ## 三. 实例化接口
150 | ### 在调用 createWithLifecycleManager 方法的时候,只需要在调用方法的地方能获取到对应Activity的LifecycleManager即可,比如在Activity中实例化接口(准确地说是动态代理出来的):
151 | ```
152 |
153 | LifecycleManager lifecycleManager = RxLifecycle.with(this);
154 | Api api = HttpHelper.getInstance().createWithLifecycleManager(Api.class, lifecycleManager);
155 | api.get("https://github.com/dhhAndroid/RxLifecycle")
156 | .observeOn(AndroidSchedulers.mainThread())
157 | .subscribe(new Action1() {
158 | @Override
159 | public void call(ResponseBody body) {
160 |
161 | }
162 | });
163 |
164 | ```
165 |
166 | ### 这样的话,这个get请求如果在Activity销毁的时候(onDestroy)还没有结束,就会直接结束掉.通过这个api接口发出的网络请求都会在Activity在onDestroy的时候取消订阅,防止内存泄漏.其次,我再内部直接将线程指定在RxJava的io线程,外部不用在重复写 subscribeOn(Schedulers.io()) 这行代码.至于 observeOn(AndroidSchedulers.mainThread()) 这行代码我没有在内部封装是因为用户可能要对数据做一些转化处理,也有可能比较耗时,所以切换主线程,在数据转换做完后比较好.
167 | ### 当然如果你在网络请求之后,又做了比较耗时的操作,比如下载文件和上传文件,为了安全期间,还是可以在调用subscribe之前加入compose(RxLifecycle.with(this).bindOnDestroy()),代码如下:
168 | ```
169 |
170 | api.get("https://github.com/dhhAndroid/RxLifecycle")
171 | .compose(RxLifecycle.with(this).bindOnDestroy())
172 | .observeOn(AndroidSchedulers.mainThread())
173 | .subscribe(new Action1() {
174 | @Override
175 | public void call(ResponseBody body) {
176 |
177 | }
178 | });
179 |
180 | ```
181 | ### HttpHelper调用API完全一样,只是RxJavaCallAdapter不一样.
182 | # 详情请查看demo.
183 | # 详情请查看demo.
184 | # 详情请查看demo.
185 | # 从此就可以对 使用RxJava+Retrofit 导致的内存泄漏说 ( ^_^ )/~~拜拜 !
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':demo', ':rxlifecycle', ':rxlifecycle2'
2 |
--------------------------------------------------------------------------------