{
37 |
38 | protected T presenter;
39 |
40 | private View rootView;
41 |
42 | /**
43 | * Fragment是否可见状态
whether the Fragment is visible
44 | */
45 | private boolean isFragmentVisible;
46 |
47 | /**
48 | * Layout已经初始化完成
Layout has been initialized
49 | */
50 | private boolean isPrepared;
51 |
52 | /**
53 | * 是否第一次加载
whether first load
54 | */
55 | private boolean isFirstLoad = true;
56 |
57 | /**
58 | *
59 | * 忽略isFirstLoad的值,强制刷新数据,但仍要Visible & Prepared
60 | * 一般用于PagerAdapter需要刷新各个子Fragment的场景
61 | * 不要new 新的 PagerAdapter 而采取reset数据的方式
62 | * 所以要求Fragment重新走initData方法
63 | * 故使用 {@link #setForceLoad(boolean)}来让Fragment下次执行initData
64 | *
65 | *
66 | * force load
67 | *
68 | * ignore isFirstLoad value, but still keep Visible & Prepared.
69 | * use this when PagerAdapter need refresh multiple Fragment.
70 | *
71 | *
72 | */
73 | private boolean forceLoad = false;
74 |
75 | @Override
76 | public void onAttach(Context context) {
77 | super.onAttach(context);
78 | try{
79 | presenter = GenericHelper.newPresenter(this);
80 | if (presenter != null) {
81 | presenter.start();
82 | }
83 | }catch (Exception e) {
84 | e.printStackTrace();
85 | }
86 |
87 | onPresenterCircle(presenter);
88 | }
89 |
90 | @Override
91 | public void onCreate(@Nullable Bundle savedInstanceState) {
92 | onBeforeCreateCircle();
93 | super.onCreate(savedInstanceState);
94 |
95 | if (savedInstanceState != null) {
96 | onBundleHandle(savedInstanceState);
97 | }
98 |
99 | Bundle bundle = getArguments();
100 | if (bundle != null && bundle.size() > 0) {
101 | onArgumentsHandle(bundle);
102 | }
103 | }
104 |
105 | @Nullable
106 | @Override
107 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
108 | if (getLayoutId() == 0) {
109 | rootView = inflater.inflate(layoutId(), container, false);
110 | } else {
111 | rootView = inflater.inflate(getLayoutId(), container, false);
112 | }
113 | isFirstLoad = true;
114 | isPrepared = true;
115 | if (!isInViewPager()) {
116 | isFragmentVisible = true;
117 | }
118 | onInitCircle();
119 | onListenerCircle();
120 | onInit();
121 | onListener();
122 | lazyLoad();
123 | return rootView;
124 | }
125 |
126 | /***
127 | * 如果是与ViewPager一起使用,调用的是setUserVisibleHint
If used with ViewPager, the call to setUserVisibleHint
128 | * @param isVisibleToUser 是否显示出来了
129 | */
130 | @Override
131 | public void setUserVisibleHint(boolean isVisibleToUser) {
132 | super.setUserVisibleHint(isVisibleToUser);
133 | if (isVisibleToUser) {
134 | onVisible();
135 | } else {
136 | onInvisible();
137 | }
138 | }
139 |
140 | /**
141 | * 如果是通过FragmentTransaction的show和hide的方法来控制显示,调用的是onHiddenChanged. 此时您因该让 {@link #isInViewPager()} 返回false
142 | * If use by FragmentTransaction show or hide, the call to onHiddenChanged. now you need return false in {@link #isInViewPager()}
143 | *
144 | * @param hidden hidden True if the fragment is now hidden, false if it is not
145 | * visible.
146 | */
147 | @Override
148 | public void onHiddenChanged(boolean hidden) {
149 | super.onHiddenChanged(hidden);
150 | if (hidden) {
151 | onInvisible();
152 | } else {
153 | onVisible();
154 | }
155 | }
156 |
157 | @Override
158 | public void onVisible() {
159 | isFragmentVisible = true;
160 | lazyLoad();
161 | }
162 |
163 | @Override
164 | public void onInvisible() {
165 | isFragmentVisible = false;
166 | }
167 |
168 | @Override
169 | public void onBeforeCreateCircle() { }
170 |
171 | @Override
172 | public void onPresenterCircle(T presenter) {
173 |
174 | }
175 |
176 | @Override
177 | public void onBundleHandle(@NonNull Bundle savedInstanceState) { }
178 |
179 | @Override
180 | public void onArgumentsHandle(@NonNull Bundle bundle) { }
181 |
182 | @Override
183 | public void onListenerCircle() { }
184 |
185 | @Override
186 | public void onLazyLoad() { }
187 |
188 | @Override
189 | public void onInitCircle() { }
190 |
191 | @Override
192 | public int layoutId() { return 0; }
193 |
194 | /**
195 | * 在这里面进行初始化
196 | * @deprecated 将弃用该方法,需尽快改为使用 {@link #onInitCircle()}
197 | * use {@link #onInitCircle()}, now
198 | */
199 | protected void onInit() {}
200 |
201 | /**
202 | * 这里面写监听事件
203 | * @deprecated 将弃用该方法,需尽快改为使用 {@link #onListenerCircle()}
204 | * use {@link #onListenerCircle()}, now
205 | */
206 | protected void onListener() {}
207 |
208 | /**
209 | * 获取布局的id
210 | * @deprecated 将弃用该方法,需尽快改为使用 {@link #layoutId()}
211 | * use {@link #layoutId()}, now
212 | */
213 | protected int getLayoutId() {
214 | return 0;
215 | }
216 |
217 | public View getRootView() {
218 | return this.rootView;
219 | }
220 |
221 | private void lazyLoad() {
222 | if (isPrepared() && isFragmentVisible()) {
223 | if (isForceLoad() || isFirstLoad()) {
224 | forceLoad = false;
225 | isFirstLoad = false;
226 | onLazyLoad();
227 | }
228 | }
229 | }
230 |
231 | @Override
232 | public void onDestroyView() {
233 | super.onDestroyView();
234 | isPrepared = false;
235 | }
236 |
237 | @Override
238 | public void onDetach() {
239 | super.onDetach();
240 | if (presenter != null) {
241 | presenter.end();
242 | }
243 | }
244 |
245 | @Override
246 | public void setForceLoad(boolean forceLoad) {
247 | this.forceLoad = forceLoad;
248 | }
249 |
250 | @Override
251 | public boolean isForceLoad() {
252 | return forceLoad;
253 | }
254 |
255 | @Override
256 | public boolean isPrepared() {
257 | return isPrepared;
258 | }
259 |
260 | @Override
261 | public boolean isFirstLoad() {
262 | return isFirstLoad;
263 | }
264 |
265 | @Override
266 | public boolean isFragmentVisible() {
267 | return isFragmentVisible;
268 | }
269 |
270 | @Override
271 | public boolean isInViewPager() {
272 | return true;
273 | }
274 | }
275 |
--------------------------------------------------------------------------------
/xmvp/src/main/java/io/xujiaji/xmvp/view/base/v4/XBaseFragment.java:
--------------------------------------------------------------------------------
1 | package io.xujiaji.xmvp.view.base.v4;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 | import androidx.fragment.app.Fragment;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 |
12 | import io.xujiaji.xmvp.presenters.XBasePresenter;
13 | import io.xujiaji.xmvp.utils.GenericHelper;
14 | import io.xujiaji.xmvp.view.interfaces.XFragViewCycle;
15 |
16 |
17 | /**
18 | *
19 | * 项目中Fragment的基类
base Fragment class
20 | * 部分代码参照(reference):https://github.com/xmagicj/LazyFragment/blob/master/app/src/main/java/com/xmagicj/android/lazyfragment/BaseFragment.java
21 | */
22 | public abstract class XBaseFragment extends Fragment implements XFragViewCycle {
23 |
24 | protected T presenter;
25 |
26 | private View rootView;
27 |
28 | /**
29 | * Fragment是否可见状态
whether the Fragment is visible
30 | */
31 | private boolean isFragmentVisible;
32 |
33 | /**
34 | * Layout已经初始化完成
Layout has been initialized
35 | */
36 | private boolean isPrepared;
37 |
38 | /**
39 | * 是否第一次加载
whether first load
40 | */
41 | private boolean isFirstLoad = true;
42 |
43 | /**
44 | *
45 | * 忽略isFirstLoad的值,强制刷新数据,但仍要Visible & Prepared
46 | * 一般用于PagerAdapter需要刷新各个子Fragment的场景
47 | * 不要new 新的 PagerAdapter 而采取reset数据的方式
48 | * 所以要求Fragment重新走initData方法
49 | * 故使用 {@link #setForceLoad(boolean)}来让Fragment下次执行initData
50 | *
51 | *
52 | * force load
53 | *
54 | * ignore isFirstLoad value, but still keep Visible & Prepared.
55 | * use this when PagerAdapter need refresh multiple Fragment.
56 | *
57 | *
58 | */
59 | private boolean forceLoad = false;
60 |
61 | @Override
62 | public void onAttach(Context context) {
63 | super.onAttach(context);
64 | try{
65 | presenter = GenericHelper.newPresenter(this);
66 | if (presenter != null) {
67 | presenter.start();
68 | }
69 | }catch (Exception e) {
70 | e.printStackTrace();
71 | }
72 |
73 | onPresenterCircle(presenter);
74 | }
75 |
76 | @Override
77 | public void onCreate(@Nullable Bundle savedInstanceState) {
78 | onBeforeCreateCircle();
79 | super.onCreate(savedInstanceState);
80 |
81 | if (savedInstanceState != null) {
82 | onBundleHandle(savedInstanceState);
83 | }
84 |
85 | Bundle bundle = getArguments();
86 | if (bundle != null && bundle.size() > 0) {
87 | onArgumentsHandle(bundle);
88 | }
89 | }
90 |
91 | @Nullable
92 | @Override
93 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
94 | if (getLayoutId() == 0) {
95 | rootView = inflater.inflate(layoutId(), container, false);
96 | } else {
97 | rootView = inflater.inflate(getLayoutId(), container, false);
98 | }
99 | isFirstLoad = true;
100 | isPrepared = true;
101 | if (!isInViewPager()) {
102 | isFragmentVisible = true;
103 | }
104 | onInitCircle();
105 | onListenerCircle();
106 | onInit();
107 | onListener();
108 | lazyLoad();
109 | return rootView;
110 | }
111 |
112 | /***
113 | * 如果是与ViewPager一起使用,调用的是setUserVisibleHint
If used with ViewPager, the call to setUserVisibleHint
114 | * @param isVisibleToUser 是否显示出来了
115 | */
116 | @Override
117 | public void setUserVisibleHint(boolean isVisibleToUser) {
118 | super.setUserVisibleHint(isVisibleToUser);
119 | if (isVisibleToUser) {
120 | onVisible();
121 | } else {
122 | onInvisible();
123 | }
124 | }
125 |
126 | /**
127 | * 如果是通过FragmentTransaction的show和hide的方法来控制显示,调用的是onHiddenChanged. 此时您因该让 {@link #isInViewPager()} 返回false
128 | * If use by FragmentTransaction show or hide, the call to onHiddenChanged. now you need return false in {@link #isInViewPager()}
129 | *
130 | * @param hidden hidden True if the fragment is now hidden, false if it is not
131 | * visible.
132 | */
133 | @Override
134 | public void onHiddenChanged(boolean hidden) {
135 | super.onHiddenChanged(hidden);
136 | if (hidden) {
137 | onInvisible();
138 | } else {
139 | onVisible();
140 | }
141 | }
142 |
143 | @Override
144 | public void onVisible() {
145 | isFragmentVisible = true;
146 | lazyLoad();
147 | }
148 |
149 | @Override
150 | public void onInvisible() {
151 | isFragmentVisible = false;
152 | }
153 |
154 | @Override
155 | public void onBeforeCreateCircle() { }
156 |
157 | @Override
158 | public void onPresenterCircle(T presenter) {
159 |
160 | }
161 |
162 | @Override
163 | public void onBundleHandle(@NonNull Bundle savedInstanceState) { }
164 |
165 | @Override
166 | public void onArgumentsHandle(@NonNull Bundle bundle) { }
167 |
168 | @Override
169 | public void onListenerCircle() { }
170 |
171 | @Override
172 | public void onLazyLoad() { }
173 |
174 | @Override
175 | public void onInitCircle() { }
176 |
177 | @Override
178 | public int layoutId() { return 0; }
179 |
180 | /**
181 | * 在这里面进行初始化
182 | * @deprecated 将弃用该方法,需尽快改为使用 {@link #onInitCircle()}
183 | * use {@link #onInitCircle()}, now
184 | */
185 | protected void onInit() {}
186 |
187 | /**
188 | * 这里面写监听事件
189 | * @deprecated 将弃用该方法,需尽快改为使用 {@link #onListenerCircle()}
190 | * use {@link #onListenerCircle()}, now
191 | */
192 | protected void onListener() {}
193 |
194 | /**
195 | * 获取布局的id
196 | * @deprecated 将弃用该方法,需尽快改为使用 {@link #layoutId()}
197 | * use {@link #layoutId()}, now
198 | */
199 | protected int getLayoutId() {
200 | return 0;
201 | }
202 |
203 | public View getRootView() {
204 | return this.rootView;
205 | }
206 |
207 | private void lazyLoad() {
208 | if (isPrepared() && isFragmentVisible()) {
209 | if (isForceLoad() || isFirstLoad()) {
210 | forceLoad = false;
211 | isFirstLoad = false;
212 | onLazyLoad();
213 | }
214 | }
215 | }
216 |
217 | @Override
218 | public void onDestroyView() {
219 | super.onDestroyView();
220 | isPrepared = false;
221 | }
222 |
223 | @Override
224 | public void onDetach() {
225 | super.onDetach();
226 | if (presenter != null) {
227 | presenter.end();
228 | }
229 | }
230 |
231 | @Override
232 | public void setForceLoad(boolean forceLoad) {
233 | this.forceLoad = forceLoad;
234 | }
235 |
236 | @Override
237 | public boolean isForceLoad() {
238 | return forceLoad;
239 | }
240 |
241 | @Override
242 | public boolean isPrepared() {
243 | return isPrepared;
244 | }
245 |
246 | @Override
247 | public boolean isFirstLoad() {
248 | return isFirstLoad;
249 | }
250 |
251 | @Override
252 | public boolean isFragmentVisible() {
253 | return isFragmentVisible;
254 | }
255 |
256 | @Override
257 | public boolean isInViewPager() {
258 | return true;
259 | }
260 | }
261 |
--------------------------------------------------------------------------------
/xmvp/src/main/java/io/xujiaji/xmvp/view/interfaces/XActivityCycle.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 XuJiaji
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.xujiaji.xmvp.view.interfaces;
18 |
19 | import android.content.Intent;
20 | import androidx.annotation.NonNull;
21 |
22 | import io.xujiaji.xmvp.presenters.XBasePresenter;
23 |
24 | /**
25 | * author: xujiaji
26 | * created on: 2018/9/11 15:05
27 | * description: 定义Activity View相关周期
Define Activity View related Cycle
28 | */
29 | public interface XActivityCycle extends XViewCycle {
30 | /**
31 | * 处理上个页面传递过来的数据
Handle the data passed from the previous page
32 | */
33 | void onIntentHandle(@NonNull Intent intent);
34 | }
35 |
--------------------------------------------------------------------------------
/xmvp/src/main/java/io/xujiaji/xmvp/view/interfaces/XFragViewCycle.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 XuJiaji
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.xujiaji.xmvp.view.interfaces;
18 |
19 | import android.app.Fragment;
20 | import android.os.Bundle;
21 | import androidx.annotation.NonNull;
22 |
23 | import io.xujiaji.xmvp.presenters.XBasePresenter;
24 |
25 | /**
26 | * author: xujiaji
27 | * created on: 2018/9/4 10:57
28 | * description: 定义Fragment View相关周期
Define Fragment View related Cycle
29 | */
30 | public interface XFragViewCycle extends XViewCycle {
31 |
32 | /**
33 | * 处理{@link Fragment#getArguments()} 的值,如果有才会调用
Handle the value of {@link Fragment#getArguments()} , if it is there, it will be called
34 | * @param bundle
35 | */
36 | void onArgumentsHandle(@NonNull Bundle bundle);
37 |
38 | void onVisible();
39 |
40 | void onInvisible();
41 |
42 | void onLazyLoad();
43 |
44 | /**
45 | * 忽略{@link #isFirstLoad() }的值,强制刷新数据,但仍要满足 {@link #isFragmentVisible()} && {@link #isPrepared()}
46 | * Ignore the value of {@link #isFirstLoad() } to force refresh data, but still satisfy {@link #isFragmentVisible()} && {@link #isPrepared()}
47 | */
48 | void setForceLoad(boolean forceLoad);
49 |
50 | boolean isForceLoad();
51 |
52 | boolean isPrepared();
53 |
54 | boolean isFirstLoad();
55 |
56 | boolean isFragmentVisible();
57 |
58 | /**
59 | * 是否是在ViewPager中,默认为true
60 | * whether in ViewPager, default is true
61 | * @return
62 | */
63 | boolean isInViewPager();
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/xmvp/src/main/java/io/xujiaji/xmvp/view/interfaces/XViewCycle.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 XuJiaji
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.xujiaji.xmvp.view.interfaces;
18 |
19 | import android.os.Bundle;
20 | import androidx.annotation.NonNull;
21 |
22 | import io.xujiaji.xmvp.presenters.XBasePresenter;
23 |
24 | /**
25 | * author: xujiaji
26 | * created on: 2018/9/4 10:57
27 | * description: 定义View相关周期
Define View related Cycle
28 | */
29 | public interface XViewCycle {
30 |
31 | /**
32 | * 在 super {@link android.app.Activity#onCreate(Bundle)}之前被调用
will be called before super class {@link android.app.Activity#onCreate(Bundle)} called
33 | */
34 | void onBeforeCreateCircle();
35 |
36 | void onPresenterCircle(T presenter);
37 |
38 | /**
39 | * 在 super {@link android.app.Activity#onCreate(Bundle)}之前被调用,并且有Bundle
will be called before super class {@link android.app.Activity#onCreate(Bundle)} called
40 | * @param savedInstanceState 该参数不可能为null
this parameter cannot be null
41 | */
42 | void onBundleHandle(@NonNull Bundle savedInstanceState);
43 |
44 | /**
45 | * 获取布局的id
get layout id
46 | * 在 {@link #onBeforeCreateCircle }之后被调用
will be called after {@link #onBeforeCreateCircle } called
47 | * @return xml布局id
xml layout id
48 | */
49 | int layoutId();
50 |
51 | /**
52 | * 在这里面进行初始化
initialize here
53 | * 在 {@link #layoutId()} 之后被调用
will be called after {@link #layoutId()} called
54 | */
55 | void onInitCircle();
56 |
57 | /**
58 | * 这里面写监听事件
write listens event here
59 | * 在 {@link #onInitCircle()} 之后被调用
will be called after {@link #onInitCircle()} called
60 | */
61 | void onListenerCircle();
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/xmvp/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | xmvp
3 |
4 |
--------------------------------------------------------------------------------
/xmvp/src/test/java/io/xujiaji/xmvp/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package io.xujiaji.sample;
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 | }
--------------------------------------------------------------------------------