value) {
92 | mIntent.putExtra(key, value);
93 | return this;
94 | }
95 |
96 | public IntentBuilder putStringArrayListExtra(String key, boolean value) {
97 | mIntent.putExtra(key, value);
98 | return this;
99 | }
100 |
101 | public IntentBuilder putCharSequenceArrayListExtra(String key, boolean value) {
102 | mIntent.putExtra(key, value);
103 | return this;
104 | }
105 |
106 | public IntentBuilder putExtra(String key, Serializable value) {
107 | mIntent.putExtra(key, value);
108 | return this;
109 | }
110 |
111 | public IntentBuilder putExtra(String key, boolean[] value) {
112 | mIntent.putExtra(key, value);
113 | return this;
114 | }
115 |
116 | public IntentBuilder putExtra(String key, byte[] value) {
117 | mIntent.putExtra(key, value);
118 | return this;
119 | }
120 |
121 | public IntentBuilder putExtra(String key, short[] value) {
122 | mIntent.putExtra(key, value);
123 | return this;
124 | }
125 |
126 | public IntentBuilder putExtra(String key, char[] value) {
127 | mIntent.putExtra(key, value);
128 | return this;
129 | }
130 |
131 | public IntentBuilder putExtra(String key, int[] value) {
132 | mIntent.putExtra(key, value);
133 | return this;
134 | }
135 |
136 | public IntentBuilder putExtra(String key, long[] value) {
137 | mIntent.putExtra(key, value);
138 | return this;
139 | }
140 |
141 | public IntentBuilder putExtra(String key, float[] value) {
142 | mIntent.putExtra(key, value);
143 | return this;
144 | }
145 |
146 | public IntentBuilder putExtra(String key, double[] value) {
147 | mIntent.putExtra(key, value);
148 | return this;
149 | }
150 |
151 | public IntentBuilder putExtra(String key, String[] value) {
152 | mIntent.putExtra(key, value);
153 | return this;
154 | }
155 |
156 | public IntentBuilder putExtra(String key, CharSequence[] value) {
157 | mIntent.putExtra(key, value);
158 | return this;
159 | }
160 |
161 | public IntentBuilder putExtra(String key, Bundle value) {
162 | mIntent.putExtra(key, value);
163 | return this;
164 | }
165 |
166 | public IntentBuilder putExtras(Intent value) {
167 | mIntent.putExtras(value);
168 | return this;
169 | }
170 |
171 | public IntentBuilder putExtras(Bundle value) {
172 | mIntent.putExtras(value);
173 | return this;
174 | }
175 |
176 | public IntentBuilder replaceExtras(Intent value) {
177 | mIntent.replaceExtras(value);
178 | return this;
179 | }
180 |
181 | public IntentBuilder replaceExtras(Bundle value) {
182 | mIntent.replaceExtras(value);
183 | return this;
184 | }
185 |
186 | public IntentBuilder removeExtra(String key) {
187 | mIntent.removeExtra(key);
188 | return this;
189 | }
190 |
191 | public Intent build() {
192 | return mIntent;
193 | }
194 |
195 | private IntentBuilder() {
196 | mIntent = new Intent();
197 | }
198 |
199 | private IntentBuilder(Context context, Class> clazz) {
200 | mIntent = new Intent(context, clazz);
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/library/src/main/java/prototypez/github/io/sq/fragment/SupportActivityResultFragment.java:
--------------------------------------------------------------------------------
1 | package prototypez.github.io.sq.fragment;
2 |
3 | import android.content.Intent;
4 | import android.support.v4.app.Fragment;
5 | import android.support.v4.app.FragmentManager;
6 | import android.support.v7.app.AppCompatActivity;
7 |
8 | import io.reactivex.Observable;
9 | import io.reactivex.subjects.PublishSubject;
10 | import prototypez.github.io.sq.ActivityResult;
11 |
12 | /**
13 | * Encapsulate startActivityForResult and onActivityResult with Fragment
14 | *
15 | * Created by zhounl on 2017/6/19.
16 | */
17 |
18 | public class SupportActivityResultFragment extends Fragment {
19 |
20 | private final PublishSubject mActivityResultSubject = PublishSubject.create();
21 |
22 |
23 | @Override
24 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
25 | super.onActivityResult(requestCode, resultCode, data);
26 | mActivityResultSubject.onNext(new ActivityResult(requestCode, resultCode, data));
27 | }
28 |
29 | // region getActivityResultObservable
30 |
31 | public static Observable getActivityResultObservable(AppCompatActivity activity) {
32 | FragmentManager fragmentManager = activity.getSupportFragmentManager();
33 | SupportActivityResultFragment fragment = (SupportActivityResultFragment) fragmentManager.findFragmentByTag(
34 | SupportActivityResultFragment.class.getCanonicalName());
35 | if (fragment == null) {
36 | fragment = new SupportActivityResultFragment();
37 | fragmentManager.beginTransaction()
38 | .add(fragment, SupportActivityResultFragment.class.getCanonicalName())
39 | .commit();
40 | fragmentManager.executePendingTransactions();
41 | }
42 | return fragment.mActivityResultSubject;
43 | }
44 |
45 | public static Observable getActivityResultObservable(Fragment f) {
46 | FragmentManager fragmentManager = f.getChildFragmentManager();
47 | SupportActivityResultFragment fragment = (SupportActivityResultFragment) fragmentManager.findFragmentByTag(
48 | SupportActivityResultFragment.class.getCanonicalName());
49 | if (fragment == null) {
50 | fragment = new SupportActivityResultFragment();
51 | fragmentManager.beginTransaction()
52 | .add(fragment, SupportActivityResultFragment.class.getCanonicalName())
53 | .commit();
54 | fragmentManager.executePendingTransactions();
55 | }
56 | return fragment.mActivityResultSubject;
57 | }
58 |
59 | // endregion
60 |
61 | // region insertActivityResult
62 |
63 | public static void insertActivityResult(AppCompatActivity activity, ActivityResult activityResult) {
64 | FragmentManager fragmentManager = activity.getSupportFragmentManager();
65 | SupportActivityResultFragment fragment = (SupportActivityResultFragment) fragmentManager.findFragmentByTag(
66 | SupportActivityResultFragment.class.getCanonicalName());
67 | if (fragment == null) {
68 | fragment = new SupportActivityResultFragment();
69 | fragmentManager.beginTransaction()
70 | .add(fragment, SupportActivityResultFragment.class.getCanonicalName())
71 | .commit();
72 | fragmentManager.executePendingTransactions();
73 | }
74 | fragment.mActivityResultSubject.onNext(activityResult);
75 | }
76 |
77 | public static void insertActivityResult(Fragment f, ActivityResult activityResult) {
78 | FragmentManager fragmentManager = f.getChildFragmentManager();
79 | SupportActivityResultFragment fragment = (SupportActivityResultFragment) fragmentManager.findFragmentByTag(
80 | SupportActivityResultFragment.class.getCanonicalName());
81 | if (fragment == null) {
82 | fragment = new SupportActivityResultFragment();
83 | fragmentManager.beginTransaction()
84 | .add(fragment, SupportActivityResultFragment.class.getCanonicalName())
85 | .commit();
86 | fragmentManager.executePendingTransactions();
87 | }
88 | fragment.mActivityResultSubject.onNext(activityResult);
89 | }
90 |
91 | // endregion
92 |
93 | // region startActivityForResult
94 |
95 | public static void startActivityForResult(AppCompatActivity activity, Intent intent, int requestCode) {
96 | FragmentManager fragmentManager = activity.getSupportFragmentManager();
97 | SupportActivityResultFragment fragment = (SupportActivityResultFragment) fragmentManager.findFragmentByTag(
98 | SupportActivityResultFragment.class.getCanonicalName());
99 | if (fragment == null) {
100 | fragment = new SupportActivityResultFragment();
101 | fragmentManager.beginTransaction()
102 | .add(fragment, SupportActivityResultFragment.class.getCanonicalName())
103 | .commit();
104 | fragmentManager.executePendingTransactions();
105 | }
106 | fragment.startActivityForResult(intent, requestCode);
107 | }
108 |
109 | public static void startActivityForResult(Fragment f, Intent intent, int requestCode) {
110 | FragmentManager fragmentManager = f.getChildFragmentManager();
111 | SupportActivityResultFragment fragment = (SupportActivityResultFragment) fragmentManager.findFragmentByTag(
112 | SupportActivityResultFragment.class.getCanonicalName());
113 | if (fragment == null) {
114 | fragment = new SupportActivityResultFragment();
115 | fragmentManager.beginTransaction()
116 | .add(fragment, SupportActivityResultFragment.class.getCanonicalName())
117 | .commit();
118 | fragmentManager.executePendingTransactions();
119 | }
120 | fragment.startActivityForResult(intent, requestCode);
121 | }
122 |
123 | // endregion
124 | }
125 |
--------------------------------------------------------------------------------
/app/src/main/java/prototypez/github/io/sq/demo/processes/login/LoginActivity.kt:
--------------------------------------------------------------------------------
1 | package prototypez.github.io.sq.demo.processes.login
2 |
3 | import android.app.Activity
4 | import android.content.Context
5 | import android.content.Intent
6 | import android.os.Bundle
7 | import android.support.v7.app.AppCompatActivity
8 | import io.reactivex.ObservableTransformer
9 | import prototypez.github.io.sq.ActivityResult
10 | import prototypez.github.io.sq.Sq
11 | import prototypez.github.io.sq.activity.SqActivity
12 | import prototypez.github.io.sq.demo.processes.login.steps.LoginByPwdFragment
13 | import prototypez.github.io.sq.demo.processes.login.steps.LoginBySmsFragment
14 | import prototypez.github.io.sq.demo.util.LoginInfo
15 | import prototypez.github.io.sq.util.IntentBuilder
16 |
17 | /**
18 | * 登陆流程
19 | */
20 | class LoginActivity : SqActivity() {
21 |
22 | private lateinit var loginByPwdFragment: LoginByPwdFragment
23 | private lateinit var loginBySmsFragment: LoginBySmsFragment
24 |
25 | override fun onCreate(savedInstanceState: Bundle?) {
26 | super.onCreate(savedInstanceState)
27 |
28 | loginByPwdFragment = findOrCreateFragment(LoginByPwdFragment::class.java)
29 | loginBySmsFragment = findOrCreateFragment(LoginBySmsFragment::class.java)
30 |
31 | if (savedInstanceState == null) {
32 | push(loginByPwdFragment)
33 | }
34 |
35 | // 流程控制逻辑
36 |
37 | // 用户名密码验证
38 | loginByPwdFragment.loginByPwdCallback = { needSmsVerify, user ->
39 | if (needSmsVerify) {
40 | // 进入短信验证流程
41 | loginBySmsFragment.setParams(user)
42 | push(loginBySmsFragment)
43 | } else {
44 | // 直接登录成功
45 | LoginInfo.currentLoginUser = user
46 | Sq.setResult(
47 | this@LoginActivity,
48 | Activity.RESULT_OK,
49 | IntentBuilder.newInstance()
50 | .putExtra("user", user)
51 | .build()
52 | )
53 | finish()
54 | }
55 | }
56 |
57 | // 用户名密码验证 - 短信验证
58 | loginBySmsFragment.loginBySmsCallback = { user ->
59 | LoginInfo.currentLoginUser = user
60 | Sq.setResult(
61 | this@LoginActivity,
62 | Activity.RESULT_OK,
63 | IntentBuilder.newInstance()
64 | .putExtra("user", user)
65 | .build()
66 | )
67 | finish()
68 | }
69 |
70 |
71 |
72 | // 用户名密码验证 - 子流程(直接注册成功)
73 | loginByPwdFragment.registerCallback = { user ->
74 |
75 | // 注册成功也视为登录成功的一种,需要通知流程发起者登录成功
76 | LoginInfo.currentLoginUser = user
77 | Sq.setResult(
78 | this@LoginActivity,
79 | Activity.RESULT_OK,
80 | IntentBuilder.newInstance()
81 | .putExtra("user", user)
82 | .build()
83 | )
84 | finish()
85 | }
86 | }
87 |
88 | companion object {
89 |
90 | private const val REQUEST_LOGIN = 401
91 |
92 | // 默认情况,如果相同页面中只有一处操作需要确保登录可用
93 | fun ensureLoginWithContext(activity: AppCompatActivity): ObservableTransformer {
94 | return ensureLoginWithContext(activity, REQUEST_LOGIN)
95 | }
96 |
97 | // 复杂情况,如果相同页面中有多处操作需要确保登录可用,那么需要通过 requestCode 区分请求由哪个操作发起
98 | fun ensureLoginWithContext(activity: AppCompatActivity, requestCode: Int): ObservableTransformer {
99 | return ObservableTransformer { upstream ->
100 | upstream.subscribe { contextData ->
101 | if (LoginInfo.isLogin) {
102 | Sq.insertActivityResult(activity,
103 | ActivityResult(
104 | requestCode,
105 | Activity.RESULT_OK,
106 | IntentBuilder.newInstance()
107 | .putExtra("user", LoginInfo.currentLoginUser)
108 | .build(), null,
109 | contextData
110 | )
111 | )
112 | } else {
113 | Sq.startActivityForResult(
114 | activity,
115 | makeIntentForLogin(activity),
116 | requestCode,
117 | contextData
118 | )
119 | }
120 | }
121 |
122 | Sq.obtainActivityResult(activity)
123 | .filter { ar -> ar.requestCode == requestCode }
124 | .filter { ar -> ar.resultCode == Activity.RESULT_OK }
125 | .map { it.requestContextData }
126 | }
127 | }
128 |
129 | /**
130 | * 确保已登录,不需要保存流程触发点的上下文的简单情况
131 | */
132 | fun ensureLogin(activity: AppCompatActivity): ObservableTransformer {
133 | return ObservableTransformer { upstream ->
134 | upstream.subscribe { _ ->
135 | if (LoginInfo.isLogin) {
136 | Sq.insertActivityResult(activity,
137 | ActivityResult(
138 | REQUEST_LOGIN,
139 | Activity.RESULT_OK,
140 | IntentBuilder.newInstance()
141 | .putExtra("user", LoginInfo.currentLoginUser)
142 | .build()
143 | )
144 | )
145 | } else {
146 | Sq.startActivityForResult(
147 | activity,
148 | makeIntentForLogin(activity),
149 | REQUEST_LOGIN
150 | )
151 | }
152 | }
153 |
154 | Sq.obtainActivityResult(activity)
155 | .filter { ar -> ar.requestCode == REQUEST_LOGIN }
156 | .filter { ar -> ar.resultCode == Activity.RESULT_OK }
157 | }
158 | }
159 |
160 | private fun makeIntentForLogin(context: Context): Intent {
161 | return Intent(context, LoginActivity::class.java)
162 | }
163 | }
164 | }
165 |
166 |
167 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # Sq
2 | [  ](https://bintray.com/prototypez/maven/sq/_latestVersion)
3 |
4 | 
5 |
6 | 更流畅的方式使用 `startActivityForResult` 和 `onActivityResult`, 以及封装你的业务流程。
7 |
8 | 同时具有更好的健壮性,在 Activity / 应用进程 销毁重建的场景下依然可以正常工作。
9 |
10 | ## 从 Activity 中得到一个结果
11 |
12 | 以登录流程为例,App 中会有很多操作会触发登录流程, 例如点赞操作:
13 |
14 | ```kotlin
15 |
16 | override fun onCreate(savedInstanceState: Bundle?) {
17 | likeBtn.setOnClickListener { _ ->
18 | if (LoginInfo.isLogin()) {
19 | doLike()
20 | } else {
21 | startActivityForResult(
22 | Intent(this, LoginActivity::class.java)
23 | REQUEST_CODE_LOGIN
24 | )
25 | }
26 | }
27 | }
28 |
29 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
30 | super.onActivityResult(requestCode, resultCode, data)
31 | when (requestCode) {
32 | REQUEST_CODE_LOGIN -> {
33 | if (resultCode == Activity.RESULT_OK) {
34 | doLike()
35 | }
36 | }
37 | }
38 | }
39 |
40 | ```
41 |
42 | 上面的写法,虽然可以正常工作,但是显得过于散乱,我们使用 **Sq** 来优化代码。
43 |
44 | ## 使用 Sq 调用登录流程
45 |
46 | 使用 `RxJava` 中的 `compose` 操作符,在点击事件与点赞操作之间插入登录检测操作:
47 |
48 | ```kotlin
49 | RxView.clicks(likeBtn)
50 | .compose(LoginActivity.ensureLogin(this))
51 | .subscribe {_ -> doLike()}
52 | ```
53 |
54 | 登录流程不再变得难以复用,从此可以在任何操作前插入前置登录检测流程。`ensureLogin` 方法的实现:
55 |
56 | ```kotlin
57 | fun ensureLogin(activity: AppCompatActivity): ObservableTransformer {
58 | return ObservableTransformer { upstream ->
59 | upstream.subscribe { _ ->
60 | if (LoginInfo.isLogin()) {
61 | Sq.insertActivityResult(activity, ActivityResult(REQUEST_CODE_LOGIN, Activity.RESULT_OK, null))
62 | } else {
63 | Sq.startActivityForResult(activity, Intent(activity, LoginActivity::class.java), REQUEST_CODE_LOGIN)
64 | }
65 | }
66 | Sq.obtainActivityResult(activity)
67 | .filter { ar -> ar.requestCode == REQUEST_CODE_LOGIN }
68 | .filter { ar -> ar.resultCode == Activity.RESULT_OK }
69 | }
70 | }
71 | ```
72 |
73 | ## 集成
74 |
75 | ```groovy
76 | dependencies {
77 | // other dependencies
78 | // ...
79 | implementation 'io.github.prototypez:sq:${latest_version}'
80 | }
81 |
82 | ```
83 |
84 | 当前最新版本:[  ](https://bintray.com/prototypez/maven/sq/_latestVersion)
85 |
86 | ## 高级用法
87 |
88 | ### 流程组合
89 |
90 | 场景: 用户点击评论,需要依次确保已登录以及已实名认证,如果未登录则带到登录界面,如果未实名认证则带到实名认证界面,完成流程后自动进入后续步骤。
91 |
92 | ```kotlin
93 | btnComment
94 | .compose(LoginActivity.ensureLogin(this))
95 | .compose(AuthActivity.ensureAuth(this))
96 | .subscribe {_ -> startCommentActivity(this)}
97 | ```
98 |
99 | ### 流程发起点上下文保存
100 |
101 | 场景:ListView / RecyclerView 中的点击事件发起流程,需要保存点击事件发起时的上下文(哪个 Item 发起的流程),这样流程完成时才能正常更新发起流程的那个 Item。
102 |
103 | ```kotlin
104 | itemLikeClicks
105 | .map { index -> BundleBuilder.newInstance().putInt("index", index).build() }
106 | .compose(LoginActivity.ensureLoginWithContext(this))
107 | .map { bundle -> bundle.getInt("index") }
108 | .subscribe { index ->
109 | items[index].favCount += 1
110 | adapter.notifyItemChanged(index)
111 | }
112 | ```
113 |
114 | 对应 `ensureLoginWithContext` 的实现:
115 |
116 | ```kotlin
117 | fun ensureLoginWithContext(activity: AppCompatActivity): ObservableTransformer {
118 | return ObservableTransformer { upstream ->
119 | upstream.subscribe { contextData ->
120 | if (LoginInfo.isLogin()) {
121 | Sq.insertActivityResult(activity, ActivityResult(REQUEST_CODE_LOGIN, Activity.RESULT_OK, null, contextData))
122 | } else {
123 | Sq.startActivityForResult(activity, Intent(activity, LoginActivity::class.java), REQUEST_CODE_LOGIN, contextData)
124 | }
125 | }
126 | Sq.obtainActivityResult(activity)
127 | .filter { ar -> ar.requestCode == REQUEST_CODE_LOGIN }
128 | .filter { ar -> ar.resultCode == Activity.RESULT_OK }
129 | .map { it.requestContextData }
130 | }
131 | }
132 | ```
133 |
134 | 与此同时,需要把原来 `LoginActivity` 中的 `Activity.setResult` 方法替换为 `Sq.setResult` 方法。
135 |
136 | ### 区分同一页面中不同事件发起的相同流程
137 |
138 | 场景:某个页面,用户可以进行点赞和评论两个操作,这两个操作都需要确保登录态,直接使用前面的 `ensureLogin` 方法的话会导致登录流程完成以后无法区分具体是由哪个操作出发的登录流程,导致两种事件的回调都会被触发,我们需要重载 `ensureLogin` 方法:
139 |
140 | ```kotlin
141 | fun ensureLogin(activity: AppCompatActivity, requestCode: Int): ObservableTransformer {
142 | return ObservableTransformer { upstream ->
143 | upstream.subscribe { _ ->
144 | if (LoginInfo.isLogin()) {
145 | Sq.insertActivityResult(activity, ActivityResult(requestCode, Activity.RESULT_OK, null))
146 | } else {
147 | Sq.startActivityForResult(activity, Intent(activity, LoginActivity::class.java), requestCode)
148 | }
149 | }
150 | Sq.obtainActivityResult(activity)
151 | .filter { ar -> ar.requestCode == requestCode }
152 | .filter { ar -> ar.resultCode == Activity.RESULT_OK }
153 | }
154 | }
155 | ```
156 |
157 | 这样,我们便可以在两种不同事件上区分触发相同流程的回调了:
158 |
159 | ```kotlin
160 | btnComment
161 | .compose(LoginActivity.ensureLogin(this, REQUEST_CODE_LOGIN_FOR_COMMENT))
162 | .subscribe {_ -> startCommentActivity(this)}
163 |
164 | btnLike
165 | .compose(LoginActivity.ensureLogin(this, REQUEST_CODE_LOGIN_FOR_LIKE))
166 | .subscribe {_ -> doLike()}
167 | ```
168 |
169 | ## 流程内部步骤封装
170 |
171 | 首先约定:
172 | 1. 一个业务流程对应一个 `Activity` , 这个流程内部的所有步骤都由 `Fragment` 来实现;
173 | 2. `Fragment` 负责完成本步骤应该完成的任务,并把本步骤的结果通知 `Activity`;
174 | 3. `Activity` 负责整个流程对外接口,同时负责收集各步骤的结果,进行步骤之间的流转调度以及结束流程;
175 |
176 | `Fragment` 可以由你自己实现, **Sq** 提供了 `SqActivity` 类,帮助你实现上面约定中的 `Activity`,你可以从 `SqActivity` 继承下来, 实现你自己的业务流程的 `Activity` 。下面以一个带短信验证码的两步验证的登录流程为例:
177 |
178 | ```kotlin
179 | class LoginActivity : SqActivity() {
180 |
181 | private lateinit var loginByPwdFragment: LoginByPwdFragment
182 | private lateinit var loginBySmsFragment: LoginBySmsFragment
183 |
184 | override fun onCreate(savedInstanceState: Bundle?) {
185 | super.onCreate(savedInstanceState)
186 |
187 | loginByPwdFragment = findOrCreateFragment(LoginByPwdFragment::class.java)
188 | loginBySmsFragment = findOrCreateFragment(LoginBySmsFragment::class.java)
189 |
190 | // 第一步,进入用户名密码验证界面
191 | if (savedInstanceState == null) {
192 | push(loginByPwdFragment)
193 | }
194 |
195 | // 第一步用户名密码验证的结果回调
196 | loginByPwdFragment.loginByPwdCallback = { needSmsVerify, user ->
197 | if (needSmsVerify) {
198 | // 进入第二步,短信验证步骤
199 | loginBySmsFragment.setParams(user)
200 | push(loginBySmsFragment)
201 | } else {
202 | // 直接登录成功,流程结束
203 | LoginInfo.currentLoginUser = user
204 | Sq.setResult(
205 | this@LoginActivity,
206 | Activity.RESULT_OK,
207 | IntentBuilder.newInstance()
208 | .putExtra("user", user)
209 | .build()
210 | )
211 | finish()
212 | }
213 | }
214 |
215 | // 第二步短信验证的结果回调
216 | loginBySmsFragment.loginBySmsCallback = { user ->
217 | // 验证成功,登录成功,流程结束
218 | LoginInfo.currentLoginUser = user
219 | Sq.setResult(
220 | this@LoginActivity,
221 | Activity.RESULT_OK,
222 | IntentBuilder.newInstance()
223 | .putExtra("user", user)
224 | .build()
225 | )
226 | finish()
227 | }
228 | }
229 | }
230 | ```
231 |
232 | 如果你不希望从 `SqActivity` 继承,你也可以从自己的 `Activity` 继承下来,`SqActivity` 只是提供了 `push` 和 `findOrCreateFragment` 这两个方法以供调用, 这两个方法同样存在于 `Sq` 这个类里,你也可以手动调用。
233 |
234 | 如果你并不想遵守上面的约定来封装业务流程,你可以仅仅只把 **Sq** 当成一个 `startActivityForResult` 的工具类。
235 |
236 | ## 参考资料
237 |
238 | [如何优雅地构建易维护、可复用的 Android 业务流程](http://prototypez.github.io/2018/04/30/best-practices-of-android-process-management/)
239 |
240 | [如何优雅地构建易维护、可复用的 Android 业务流程(二)](http://prototypez.github.io/2018/04/30/best-practices-of-android-process-management-2/)
241 |
242 | ## LICENSE
243 |
244 | Copyright (c) 2016-present, Sq Contributors.
245 |
246 | Licensed under the Apache License, Version 2.0 (the "License");
247 | you may not use this file except in compliance with the License.
248 | You may obtain a copy of the License at
249 |
250 | http://www.apache.org/licenses/LICENSE-2.0
251 |
252 | Unless required by applicable law or agreed to in writing, software
253 | distributed under the License is distributed on an "AS IS" BASIS,
254 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
255 | See the License for the specific language governing permissions and
256 | limitations under the License.
--------------------------------------------------------------------------------
/library/src/main/java/prototypez/github/io/sq/Sq.java:
--------------------------------------------------------------------------------
1 | package prototypez.github.io.sq;
2 |
3 | import android.app.Activity;
4 | import android.app.Fragment;
5 | import android.app.FragmentManager;
6 | import android.content.Intent;
7 | import android.os.Bundle;
8 | import android.support.annotation.AnimRes;
9 | import android.support.annotation.AnimatorRes;
10 | import android.support.annotation.NonNull;
11 | import android.support.v7.app.AppCompatActivity;
12 |
13 | import java.util.List;
14 |
15 | import io.reactivex.Observable;
16 | import prototypez.github.io.sq.fragment.ActivityResultFragment;
17 | import prototypez.github.io.sq.fragment.SupportActivityResultFragment;
18 |
19 | public class Sq {
20 |
21 | @AnimatorRes @AnimRes
22 | private static int enter = R.anim.sq_push_in_left;
23 | @AnimatorRes @AnimRes
24 | private static int exit = R.anim.sq_push_out_left;
25 | @AnimatorRes @AnimRes
26 | private static int popEnter = R.anim.sq_push_in_right;
27 | @AnimatorRes @AnimRes
28 | private static int popExit = R.anim.sq_push_out_right;
29 |
30 | /**
31 | * set Fragment Push-in Pop-out Animation
32 | */
33 | public static void setFragmentAnimation(@AnimatorRes @AnimRes int enter,
34 | @AnimatorRes @AnimRes int exit,
35 | @AnimatorRes @AnimRes int popEnter,
36 | @AnimatorRes @AnimRes int popExit) {
37 | Sq.enter = enter;
38 | Sq.exit = exit;
39 | Sq.popEnter = popEnter;
40 | Sq.popExit = popExit;
41 | }
42 |
43 | // region setResult
44 |
45 | public static void setResult(AppCompatActivity activity, int resultCode) {
46 | setResult(activity, resultCode, null);
47 | }
48 |
49 | public static void setResult(Activity activity, int resultCode) {
50 | setResult(activity, resultCode, null);
51 | }
52 |
53 | public static void setResult(AppCompatActivity activity, int resultCode, Intent resultData) {
54 |
55 | if (resultData == null) {
56 | resultData = new Intent();
57 | }
58 |
59 | Bundle requestData = activity.getIntent().getExtras();
60 |
61 | if (requestData != null) {
62 | resultData.putExtra(SqConstant.KEY_REQUEST_DATA, requestData);
63 | }
64 |
65 | activity.setResult(resultCode, resultData);
66 | }
67 |
68 | public static void setResult(Activity activity, int resultCode, Intent resultData) {
69 |
70 | if (resultData == null) {
71 | resultData = new Intent();
72 | }
73 |
74 | Bundle requestData = activity.getIntent().getExtras();
75 |
76 | if (requestData != null) {
77 | resultData.putExtra(SqConstant.KEY_REQUEST_DATA, requestData);
78 | }
79 |
80 | activity.setResult(resultCode, resultData);
81 | }
82 |
83 | // endregion
84 |
85 | // region obtainActivityResult
86 |
87 | public synchronized static Observable obtainActivityResult(AppCompatActivity activity) {
88 | return SupportActivityResultFragment.getActivityResultObservable(activity);
89 | }
90 |
91 | public synchronized static Observable obtainActivityResult(android.support.v4.app.Fragment v4Fragment) {
92 | return SupportActivityResultFragment.getActivityResultObservable(v4Fragment);
93 | }
94 |
95 |
96 | public synchronized static Observable obtainActivityResult(Activity activity) {
97 | return ActivityResultFragment.getActivityResultObservable(activity);
98 | }
99 |
100 | public synchronized static Observable obtainActivityResult(Fragment fragment) {
101 | return ActivityResultFragment.getActivityResultObservable(fragment);
102 | }
103 |
104 | // endregion
105 |
106 | // region insertActivityResult
107 | public synchronized static void insertActivityResult(AppCompatActivity activity, ActivityResult activityResult) {
108 | SupportActivityResultFragment.insertActivityResult(activity, activityResult);
109 | }
110 |
111 | public synchronized static void insertActivityResult(android.support.v4.app.Fragment v4Fragment, ActivityResult activityResult) {
112 | SupportActivityResultFragment.insertActivityResult(v4Fragment, activityResult);
113 | }
114 |
115 | public synchronized static void insertActivityResult(Activity activity, ActivityResult activityResult) {
116 | ActivityResultFragment.insertActivityResult(activity, activityResult);
117 | }
118 |
119 | public synchronized static void insertActivityResult(Fragment fragment, ActivityResult activityResult) {
120 | ActivityResultFragment.insertActivityResult(fragment, activityResult);
121 | }
122 | // endregion
123 |
124 | // region startActivityForResult
125 |
126 | public static void startActivityForResult(AppCompatActivity activity, Intent intent, int requestCode) {
127 | startActivityForResult(activity, intent, requestCode, null);
128 | }
129 |
130 | public static void startActivityForResult(android.support.v4.app.Fragment v4Fragment, Intent intent, int requestCode) {
131 | startActivityForResult(v4Fragment, intent, requestCode, null);
132 | }
133 |
134 | public static void startActivityForResult(Activity activity, Intent intent, int requestCode) {
135 | startActivityForResult(activity, intent, requestCode, null);
136 | }
137 |
138 | public static void startActivityForResult(Fragment fragment, Intent intent, int requestCode) {
139 | startActivityForResult(fragment, intent, requestCode, null);
140 | }
141 |
142 | public static void startActivityForResult(AppCompatActivity activity, Intent intent, int requestCode, Bundle requestContextData) {
143 | if (requestContextData != null && requestContextData.size() > 0) {
144 | intent.putExtra(SqConstant.KEY_REQUEST_CONTEXT_DATA, requestContextData);
145 | }
146 | SupportActivityResultFragment.startActivityForResult(activity, intent, requestCode);
147 | }
148 |
149 | public static void startActivityForResult(android.support.v4.app.Fragment v4Fragment, Intent intent, int requestCode, Bundle requestContextData) {
150 | if (requestContextData != null && requestContextData.size() > 0) {
151 | intent.putExtra(SqConstant.KEY_REQUEST_CONTEXT_DATA, requestContextData);
152 | }
153 | SupportActivityResultFragment.startActivityForResult(v4Fragment, intent, requestCode);
154 | }
155 |
156 | public static void startActivityForResult(Activity activity, Intent intent, int requestCode, Bundle requestContextData) {
157 | if (requestContextData != null && requestContextData.size() > 0) {
158 | intent.putExtra(SqConstant.KEY_REQUEST_CONTEXT_DATA, requestContextData);
159 | }
160 | ActivityResultFragment.startActivityForResult(activity, intent, requestCode);
161 | }
162 |
163 | public static void startActivityForResult(Fragment fragment, Intent intent, int requestCode, Bundle requestContextData) {
164 | if (requestContextData != null && requestContextData.size() > 0) {
165 | intent.putExtra(SqConstant.KEY_REQUEST_CONTEXT_DATA, requestContextData);
166 | }
167 | ActivityResultFragment.startActivityForResult(fragment, intent, requestCode);
168 | }
169 |
170 | // endregion
171 |
172 | // region findOrCreateFragment
173 |
174 | public static T findOrCreateFragment(@NonNull Class v4FragmentClass, AppCompatActivity activity, String tag) {
175 | android.support.v4.app.FragmentManager v4FragmentManager = activity.getSupportFragmentManager();
176 | T v4Fragment = (T) v4FragmentManager.findFragmentByTag(tag);
177 | if (v4Fragment == null) {
178 | try {
179 | v4Fragment = v4FragmentClass.newInstance();
180 | } catch (InstantiationException e) {
181 | e.printStackTrace();
182 | } catch (IllegalAccessException e) {
183 | e.printStackTrace();
184 | }
185 | }
186 | return v4Fragment;
187 | }
188 |
189 | public static T findOrCreateFragment(@NonNull Class fragmentClass, Activity activity, String tag) {
190 | FragmentManager fragmentManager = activity.getFragmentManager();
191 | T fragment = (T) fragmentManager.findFragmentByTag(tag);
192 | if (fragment == null) {
193 | try {
194 | fragment = fragmentClass.newInstance();
195 | } catch (InstantiationException e) {
196 | e.printStackTrace();
197 | } catch (IllegalAccessException e) {
198 | e.printStackTrace();
199 | }
200 | }
201 | return fragment;
202 | }
203 |
204 | // endregion
205 |
206 | // region push
207 |
208 | public static void push(AppCompatActivity activity, android.support.v4.app.Fragment v4Fragment, String tag) {
209 | List currentFragments = activity.getSupportFragmentManager().getFragments();
210 | android.support.v4.app.FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
211 | if (currentFragments.size() != 0) {
212 | transaction.setCustomAnimations(
213 | enter,
214 | exit,
215 | popEnter,
216 | popExit
217 | );
218 | }
219 | transaction.add(R.id.fragment_container, v4Fragment, tag);
220 | if (currentFragments.size() != 0) {
221 | transaction
222 | .hide(currentFragments.get(currentFragments.size() - 1))
223 | .addToBackStack(tag);
224 | }
225 | transaction.commit();
226 | }
227 |
228 | public static void push(AppCompatActivity activity, android.support.v4.app.Fragment v4Fragment) {
229 | push(activity, v4Fragment, v4Fragment.getClass().getCanonicalName());
230 | }
231 |
232 | // TODO Support Plain Activity
233 | public static void push(Activity activity, Fragment fragment, String tag) {
234 | throw new RuntimeException("Not supported currently, Please use AppCompatActivity as host instead.");
235 | }
236 |
237 | public static void push(Activity activity, Fragment fragment) {
238 | push(activity, fragment, fragment.getClass().getCanonicalName());
239 | }
240 |
241 | // endregion
242 | }
243 |
--------------------------------------------------------------------------------