1.首先看看TopActivity效果。

  

  2.TopicActivity是一个继承BaseActivity的。前面分析过BaseActivity了。主要有一个标题栏,有返回的图标。

  3.贴一下TopicActivity源代码。

  1. /*
  2. * Copyright 2017 GcsSloop
  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. * Last modified 2017-04-09 19:39:57
  17. *
  18. * GitHub: https://github.com/GcsSloop
  19. * Website: http://www.gcssloop.com
  20. * Weibo: http://weibo.com/GcsSloop
  21. */
  22.  
  23. package com.gcssloop.diycode.activity;
  24.  
  25. import android.content.Context;
  26. import android.content.Intent;
  27. import android.support.v4.app.FragmentManager;
  28. import android.support.v4.app.FragmentTransaction;
  29. import android.view.View;
  30.  
  31. import com.gcssloop.diycode.R;
  32. import com.gcssloop.diycode.base.app.BaseActivity;
  33. import com.gcssloop.diycode.base.app.ViewHolder;
  34. import com.gcssloop.diycode.fragment.NodeTopicListFragment;
  35.  
  36. /**
  37. * 查看不同分类的 Topic
  38. */
  39. public class TopicActivity extends BaseActivity {
  40. private static String Key_Node_ID = "Key_Node_ID";
  41. private static String Key_Node_Name = "Key_Node_Name";
  42.  
  43. public static void newInstance(Context context, int nodeId, String nodeName) {
  44. Intent intent = new Intent(context, TopicActivity.class);
  45. intent.putExtra(Key_Node_ID, nodeId);
  46. intent.putExtra(Key_Node_Name, nodeName);
  47. context.startActivity(intent);
  48. }
  49.  
  50. @Override protected int getLayoutId() {
  51. return R.layout.activity_fragment;
  52. }
  53.  
  54. @Override protected void initViews(ViewHolder holder, View root) {
  55. Intent intent = getIntent();
  56. int NodeId = intent.getIntExtra(Key_Node_ID, 0);
  57. String NodeName = intent.getStringExtra(Key_Node_Name);
  58. setTitle(NodeName);
  59.  
  60. NodeTopicListFragment fragment = NodeTopicListFragment.newInstance(NodeId);
  61. FragmentManager fragmentManager = getSupportFragmentManager();
  62. FragmentTransaction transaction = fragmentManager.beginTransaction();
  63. transaction.add(R.id.fragment, fragment);
  64. transaction.commit();
  65. }
  66. }

  4.首先有一个静态函数newInstance,主要就是方便外部调用打开这个Activity吧。

  

  5.实现在BaseActivity中定义的抽象函数getLayoutId()==>主要作用就是得到一个布局的id。

    这个布局activity_fragment源码贴一下吧。

  1. <LinearLayout
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:id="@+id/activity_topic"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:orientation="vertical"
  8. tools:context="com.gcssloop.diycode.activity.TopicActivity">
  9.  
  10. <android.support.v7.widget.Toolbar
  11. android:id="@+id/toolbar"
  12. android:layout_width="match_parent"
  13. android:layout_height="wrap_content"/>
  14.  
  15. <FrameLayout
  16. android:id="@+id/fragment"
  17. android:layout_width="match_parent"
  18. android:layout_height="match_parent"/>
  19.  
  20. </LinearLayout>

  预览效果就是两个部分,一个是一个Toolbar,大概占了1/8,剩下的是一个FrameLayout

 6.实现在BaseActivity中定义的抽象函数initViews(ViewHolder holder,view root)==>主要是加载一些视图。

  首先是得到外部传过来的NodeName,将ActionBar的标题通过函数setTitle来设置。

  

  这里用了一个NodeTopicListFragment,不知道是什么东西?==>原来自己定义的一个碎片。

  贴一下NodeTopicListFragment的定义。

  1. /*
  2. * Copyright 2017 GcsSloop
  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. * Last modified 2017-04-09 19:30:45
  17. *
  18. * GitHub: https://github.com/GcsSloop
  19. * Website: http://www.gcssloop.com
  20. * Weibo: http://weibo.com/GcsSloop
  21. */
  22.  
  23. package com.gcssloop.diycode.fragment;
  24.  
  25. import android.content.Context;
  26. import android.os.Bundle;
  27. import android.support.annotation.NonNull;
  28. import android.support.v7.widget.RecyclerView;
  29.  
  30. import com.gcssloop.diycode.fragment.base.SimpleRefreshRecyclerFragment;
  31. import com.gcssloop.diycode.fragment.provider.TopicProvider;
  32. import com.gcssloop.diycode_sdk.api.topic.bean.Topic;
  33. import com.gcssloop.diycode_sdk.api.topic.event.GetTopicsListEvent;
  34. import com.gcssloop.recyclerview.adapter.multitype.HeaderFooterAdapter;
  35.  
  36. /**
  37. * 分类 topic 列表
  38. */
  39. public class NodeTopicListFragment extends SimpleRefreshRecyclerFragment<Topic, GetTopicsListEvent> {
  40. private static String Key_Node_ID = "Key_Node_ID";
  41. private int mNodeId = 0;
  42.  
  43. public static NodeTopicListFragment newInstance(int nodeId) {
  44. Bundle args = new Bundle();
  45. args.putInt(Key_Node_ID, nodeId);
  46. NodeTopicListFragment fragment = new NodeTopicListFragment();
  47. fragment.setArguments(args);
  48. return fragment;
  49. }
  50.  
  51. @Override public void initData(HeaderFooterAdapter adapter) {
  52. mNodeId = getArguments().getInt(Key_Node_ID, 0);
  53. loadMore();
  54. }
  55.  
  56. @Override
  57. protected void setAdapterRegister(Context context, RecyclerView recyclerView,
  58. HeaderFooterAdapter adapter) {
  59. adapter.register(Topic.class, new TopicProvider(getContext()));
  60. }
  61.  
  62. @NonNull @Override protected String request(int offset, int limit) {
  63. return mDiycode.getTopicsList(null, mNodeId, offset, limit);
  64. }
  65. }

    6.1但是这个NodeTopicListFragment继承了一个SimpleRefreshRecyclerFragment<Topic,GetTopicListEvent>又不知道什么意思呢!

        贴一下SimpleRefreshRecyclerFragment代码吧。 

  1. /*
  2. * Copyright 2017 GcsSloop
  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. * Last modified 2017-04-09 21:16:47
  17. *
  18. * GitHub: https://github.com/GcsSloop
  19. * Website: http://www.gcssloop.com
  20. * Weibo: http://weibo.com/GcsSloop
  21. */
  22.  
  23. package com.gcssloop.diycode.fragment.base;
  24.  
  25. import android.support.annotation.NonNull;
  26. import android.support.v7.widget.RecyclerView;
  27.  
  28. import com.gcssloop.recyclerview.layoutmanager.SpeedyLinearLayoutManager;
  29. import com.gcssloop.diycode_sdk.api.base.event.BaseEvent;
  30. import com.gcssloop.recyclerview.adapter.multitype.HeaderFooterAdapter;
  31.  
  32. import java.util.List;
  33.  
  34. public abstract class SimpleRefreshRecyclerFragment<T, Event extends BaseEvent<List<T>>> extends
  35. RefreshRecyclerFragment<T, Event> {
  36.  
  37. @NonNull @Override protected RecyclerView.LayoutManager getRecyclerViewLayoutManager() {
  38. return new SpeedyLinearLayoutManager(getContext());
  39. }
  40.  
  41. @Override protected void onRefresh(Event event, HeaderFooterAdapter adapter) {
  42. adapter.clearDatas();
  43. adapter.addDatas(event.getBean());
  44. toast("刷新成功");
  45. }
  46.  
  47. @Override protected void onLoadMore(Event event, HeaderFooterAdapter adapter) {
  48. adapter.addDatas(event.getBean());
  49. }
  50.  
  51. @Override protected void onError(Event event, String postType) {
  52. if (postType.equals(POST_LOAD_MORE)) {
  53. toast("加载更多失败");
  54. } else if (postType.equals(POST_REFRESH)) {
  55. toast("刷新数据失败");
  56. }
  57. }
  58. }

          6.1.1代码中第一段都无法理解:public abstract class SimpleRefreshRecyclerFragment<T,Event extends BaseEvent<List<T>>>  extends RefreshRecyclerFragment<T,Event>。

            首先理解一下这个BaseEvent。

                        /**

               * 所有 Event 的基类
               * <p>
               * T 为对应的实体类
               * <p>
               * HTTP Status
               * -1 - 可能是网络未连接
              * 200, 201 - 请求成功,或执行成功
               * 400 - 参数不符合 API 的要求、或者数据格式验证没有通过,请配合 Response Body 里面的 error 信息确定问题。
              * 401 - 用户认证失败,或缺少认证信息,比如 access_token 过期,或没传,可以尝试用 refresh_token 方式获得新的 access_token。
               * 403 - 当前用户对资源没有操作权限
              * 404 - 资源不存在。
               * 500 - 服务器异常
               */

         然后它继承了一个RefreshRecycleFragment<T,Event>,这个也是在这个项目中的一个类,贴一下这个Fragment代码吧。        

  1. /*
  2. * Copyright 2017 GcsSloop
  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. * Last modified 2017-04-09 21:16:47
  17. *
  18. * GitHub: https://github.com/GcsSloop
  19. * Website: http://www.gcssloop.com
  20. * Weibo: http://weibo.com/GcsSloop
  21. */
  22.  
  23. package com.gcssloop.diycode.fragment.base;
  24.  
  25. import android.content.Context;
  26. import android.support.annotation.NonNull;
  27. import android.support.v4.util.ArrayMap;
  28. import android.support.v4.widget.SwipeRefreshLayout;
  29. import android.support.v7.widget.RecyclerView;
  30. import android.view.View;
  31.  
  32. import com.gcssloop.diycode.R;
  33. import com.gcssloop.diycode.base.app.ViewHolder;
  34. import com.gcssloop.diycode.fragment.bean.Footer;
  35. import com.gcssloop.diycode.fragment.provider.FooterProvider;
  36. import com.gcssloop.diycode_sdk.api.base.event.BaseEvent;
  37. import com.gcssloop.recyclerview.adapter.multitype.HeaderFooterAdapter;
  38.  
  39. import org.greenrobot.eventbus.EventBus;
  40. import org.greenrobot.eventbus.Subscribe;
  41. import org.greenrobot.eventbus.ThreadMode;
  42.  
  43. import java.util.List;
  44.  
  45. import static android.support.v7.recyclerview.R.styleable.RecyclerView;
  46.  
  47. /**
  48. * 具有下拉刷新和上拉加载的 Fragment
  49. */
  50. public abstract class RefreshRecyclerFragment<T, Event extends BaseEvent<List<T>>> extends
  51. BaseFragment {
  52. // 请求状态 - 下拉刷新 还是 加载更多
  53. public static final String POST_LOAD_MORE = "load_more";
  54. public static final String POST_REFRESH = "refresh";
  55. private ArrayMap<String, String> mPostTypes = new ArrayMap<>(); // 请求类型
  56.  
  57. // 当前状态
  58. private static final int STATE_NORMAL = 0; // 正常
  59. private static final int STATE_NO_MORE = 1; // 正在
  60. private static final int STATE_LOADING = 2; // 加载
  61. private static final int STATE_REFRESH = 3; // 刷新
  62. private int mState = STATE_NORMAL;
  63.  
  64. // 分页加载
  65. protected int pageIndex = 0; // 当面页码
  66. protected int pageCount = 20; // 每页个数
  67.  
  68. // View
  69. private SwipeRefreshLayout mRefreshLayout;
  70. protected RecyclerView mRecyclerView;
  71.  
  72. // 状态
  73. private boolean refreshEnable = true; // 是否允许刷新
  74. private boolean loadMoreEnable = true; // 是否允许加载
  75.  
  76. // 适配器
  77. protected HeaderFooterAdapter mAdapter;
  78. protected FooterProvider mFooterProvider;
  79.  
  80. protected boolean isFirstAddFooter = true;
  81.  
  82. @Override
  83. protected int getLayoutId() {
  84. return R.layout.fragment_refresh_recycler;
  85. }
  86.  
  87. @Override
  88. protected void initViews(ViewHolder holder, View root) {
  89. // 适配器
  90. mAdapter = new HeaderFooterAdapter();
  91. mFooterProvider = new FooterProvider(getContext()) {
  92. @Override
  93. public void needLoadMore() {
  94. if (isFirstAddFooter) {
  95. isFirstAddFooter = false;
  96. return;
  97. }
  98. loadMore();
  99. }
  100. };
  101. mFooterProvider.setFooterNormal();
  102. mAdapter.registerFooter(new Footer(), mFooterProvider);
  103. // refreshLayout
  104. mRefreshLayout = holder.get(R.id.refresh_layout);
  105. mRefreshLayout.setProgressViewOffset(false, -20, 80);
  106. mRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.diy_red));
  107. mRefreshLayout.setEnabled(true);
  108. // RecyclerView
  109. mRecyclerView = holder.get(R.id.recycler_view);
  110. mRecyclerView.setHasFixedSize(true);
  111. mRecyclerView.setAdapter(mAdapter);
  112. mRecyclerView.setLayoutManager(getRecyclerViewLayoutManager());
  113. setAdapterRegister(getContext(), mRecyclerView, mAdapter);
  114. // 监听 RefreshLayout 下拉刷新
  115. mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
  116. @Override
  117. public void onRefresh() {
  118. refresh();
  119. }
  120. });
  121. initData(mAdapter);
  122. }
  123.  
  124. protected void refresh() {
  125. if (!refreshEnable) return;
  126. pageIndex = 0;
  127. String uuid = request(pageIndex * pageCount, pageCount);
  128. mPostTypes.put(uuid, POST_REFRESH);
  129. pageIndex++;
  130. mState = STATE_REFRESH;
  131. }
  132.  
  133. protected void loadMore() {
  134. if (!loadMoreEnable) return;
  135. if (mState == STATE_NO_MORE) return;
  136. String uuid = request(pageIndex * pageCount, pageCount);
  137. mPostTypes.put(uuid, POST_LOAD_MORE);
  138. pageIndex++;
  139. mState = STATE_LOADING;
  140. mFooterProvider.setFooterLoading();
  141. }
  142.  
  143. @Subscribe(threadMode = ThreadMode.MAIN)
  144. public void onResultEvent(Event event) {
  145. String postType = mPostTypes.get(event.getUUID());
  146. if (event.isOk()) {
  147. if (postType.equals(POST_LOAD_MORE)) {
  148. onLoadMore(event);
  149. } else if (postType.equals(POST_REFRESH)) {
  150. onRefresh(event);
  151. }
  152. } else {
  153. onError(event);
  154. }
  155. mPostTypes.remove(event.getUUID());
  156. }
  157.  
  158. protected void onRefresh(Event event) {
  159. mState = STATE_NORMAL;
  160. mRefreshLayout.setRefreshing(false);
  161. onRefresh(event, mAdapter);
  162. }
  163.  
  164. protected void onLoadMore(Event event) {
  165. if (event.getBean().size() < pageCount) {
  166. mState = STATE_NO_MORE;
  167. mFooterProvider.setFooterNormal();
  168. } else {
  169. mState = STATE_NORMAL;
  170. mFooterProvider.setFooterNormal();
  171. }
  172. onLoadMore(event, mAdapter);
  173. }
  174.  
  175. protected void onError(Event event) {
  176. mState = STATE_NORMAL; // 状态重置为正常,以便可以重试,否则进入异常状态后无法再变为正常状态
  177. String postType = mPostTypes.get(event.getUUID());
  178. if (postType.equals(POST_LOAD_MORE)) {
  179. mFooterProvider.setFooterError(new View.OnClickListener() {
  180. @Override
  181. public void onClick(View v) {
  182. pageIndex--;
  183. loadMore();
  184. }
  185. });
  186. } else if (postType.equals(POST_REFRESH)) {
  187. mRefreshLayout.setRefreshing(false);
  188. mFooterProvider.setFooterNormal();
  189. }
  190. onError(event, postType);
  191. }
  192.  
  193. public void setRefreshEnable(boolean refreshEnable) {
  194. this.refreshEnable = refreshEnable;
  195. mRefreshLayout.setEnabled(refreshEnable);
  196. }
  197.  
  198. public void setLoadMoreEnable(boolean loadMoreEnable) {
  199. this.loadMoreEnable = loadMoreEnable;
  200. }
  201.  
  202. public void quickToTop() {
  203. mRecyclerView.smoothScrollToPosition(0);
  204. }
  205.  
  206. @Override
  207. public void onStart() {
  208. super.onStart();
  209. EventBus.getDefault().register(this);
  210. }
  211.  
  212. @Override
  213. public void onStop() {
  214. super.onStop();
  215. EventBus.getDefault().unregister(this);
  216. }
  217.  
  218. //--- 需要继承类处理的部分 ----------------------------------------------------------------------
  219.  
  220. /**
  221. * 加载数初始化数据,可以从缓存或者其他地方加载,
  222. * 如果没有初始数据,一般调用 loadMore() 即可。
  223. *
  224. * @param adapter 适配器
  225. */
  226. public abstract void initData(HeaderFooterAdapter adapter);
  227.  
  228. /**
  229. * 为 RecyclerView 的 Adapter 注册数据类型
  230. * 例如: adapter.register(Bean.class, new BeanProvider(getContext()));
  231. *
  232. * @param context 上下文
  233. * @param recyclerView RecyclerView
  234. * @param adapter Adapter
  235. */
  236. protected abstract void setAdapterRegister(Context context, RecyclerView recyclerView,
  237. HeaderFooterAdapter adapter);
  238.  
  239. /**
  240. * 获取 RecyclerView 的 LayoutManager
  241. * 例如: return new LinerLayoutManager(context);
  242. *
  243. * @return LayoutManager
  244. */
  245. @NonNull protected abstract RecyclerView.LayoutManager getRecyclerViewLayoutManager();
  246.  
  247. /**
  248. * 请求数据,并返回请求的 uuid
  249. * 例如:return mDiycode.getTopicsList(null, mNodeId, offset, limit);
  250. *
  251. * @param offset 偏移量
  252. * @param limit 请求数量
  253. * @return uuid
  254. */
  255. @NonNull protected abstract String request(int offset, int limit);
  256.  
  257. /**
  258. * 数据刷新成功的回调,由于不同页面可能要对数据进行处理,例如重新排序,清理掉一些无效数据等,所以由子类自己实现,
  259. * 如果不需要特殊处理,一般像下面这样写就行:
  260. * adapter.clearDatas();
  261. * adapter.addDatas(event.geiBean());
  262. *
  263. * @param event Event
  264. * @param adapter Adapter
  265. */
  266. protected abstract void onRefresh(Event event, HeaderFooterAdapter adapter);
  267.  
  268. /**
  269. * 数据加载成功时调用,如果不需要对数据进行特殊处理,这样写就行:
  270. * adapter.addDatas(event.getBean());
  271. *
  272. * @param event Event
  273. * @param adapter Adapter
  274. */
  275. protected abstract void onLoadMore(Event event, HeaderFooterAdapter adapter);
  276.  
  277. /**
  278. * 数据加载错误时调用,你可以在这里获取错误类型并进行处理,如果不需要特殊处理,弹出一个 toast 提醒用户即可。
  279. * if (postType.equals(POST_LOAD_MORE)) {
  280. * toast("加载更多失败");
  281. * } else if (postType.equals(POST_REFRESH)) {
  282. * toast("刷新数据失败");
  283. * }
  284. *
  285. * @param event
  286. * @param postType
  287. */
  288. protected abstract void onError(Event event, String postType);
  289. }

            然后这个RefreshRecylerFragment<T,Event extends BaseEvent<List<T>>>继承了一个BaseFragment,也是自己写的一个类。贴一下。

  1. /*
  2. * Copyright 2017 GcsSloop
  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. * Last modified 2017-04-09 21:16:47
  17. *
  18. * GitHub: https://github.com/GcsSloop
  19. * Website: http://www.gcssloop.com
  20. * Weibo: http://weibo.com/GcsSloop
  21. */
  22.  
  23. package com.gcssloop.diycode.fragment.base;
  24.  
  25. import android.os.Bundle;
  26. import android.support.annotation.LayoutRes;
  27. import android.support.annotation.Nullable;
  28. import android.support.v4.app.Fragment;
  29. import android.view.LayoutInflater;
  30. import android.view.View;
  31. import android.view.ViewGroup;
  32. import android.widget.Toast;
  33.  
  34. import com.gcssloop.diycode.base.app.ViewHolder;
  35. import com.gcssloop.diycode.utils.Config;
  36. import com.gcssloop.diycode.utils.DataCache;
  37. import com.gcssloop.diycode_sdk.api.Diycode;
  38.  
  39. /**
  40. * 提供基础内容和生命周期控制
  41. */
  42. public abstract class BaseFragment extends Fragment {
  43. private ViewHolder mViewHolder; // View 管理
  44. // 数据
  45. protected Config mConfig; // 配置(状态信息)
  46. protected Diycode mDiycode; // 在线(服务器)
  47. protected DataCache mDataCache; // 缓存(本地)
  48.  
  49. @Override public void onCreate(@Nullable Bundle savedInstanceState) {
  50. super.onCreate(savedInstanceState);
  51. mConfig = Config.getSingleInstance();
  52. mDiycode = Diycode.getSingleInstance();
  53. mDataCache = new DataCache(getContext());
  54. }
  55.  
  56. @LayoutRes
  57. protected abstract int getLayoutId();
  58.  
  59. public ViewHolder getViewHolder() {
  60. return mViewHolder;
  61. }
  62.  
  63. @Nullable
  64. @Override
  65. public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  66. mViewHolder = new ViewHolder(inflater, container, getLayoutId());
  67. return mViewHolder.getRootView();
  68. }
  69.  
  70. protected abstract void initViews(ViewHolder holder, View root);
  71.  
  72. @Override
  73. public void onActivityCreated(Bundle savedInstanceState) {
  74. super.onActivityCreated(savedInstanceState);
  75. initViews(mViewHolder, mViewHolder.getRootView());
  76. }
  77.  
  78. protected void toast(String text) {
  79. Toast.makeText(getContext(), text, Toast.LENGTH_SHORT).show();
  80. }
  81. }

            BaseFragment中定义了4个变量。

            这里有3个重要的类,Config定义在Utils中,DataCache也定义在Utils中,都是自己写的类,比较复杂,先不贴了。

            然后在BaseFragement中还有一个onCreate函数,定义了一些初始化的东西。

      

            然后定义了一个抽象函数,用来获得布局资源的id。

            然后一个onCreateView函数,用来获得mViewHolder的。

            然后又定义了一个抽象函数初始化ViewHolder的。在继承者中必须实现的。

            然后执行到onActivityCreated,在 执行initViews()函数。

            然后这里面定义一个toast函数。

            好了,现在又回到RefreshRecyclerFragment中了。==>其实它的作用就是具有下拉刷新和上拉加载的Fragment。和数据一点耦合也没有。因为是继承BaseFragment的,只要实现BaseFragment的的两个抽象方法,用来处理数据,其实就是获得数据,然后利用这个可以下拉刷新和上拉加载的Fragment来处理即可。

          然后这里面有两个适配器。

            

            ==>主要作用就是刷新的一些视图,比价刷新成功,加载失败,加载完毕等。

            然后实现了BaseFragment中的抽象方法==>getLayoutId(),加载的布局文件为:R.layout.fragment_refresh_recycler==>代码如下:

  1. <LinearLayout
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:orientation="vertical">
  8.  
  9. <android.support.v4.widget.SwipeRefreshLayout
  10. android:id="@+id/refresh_layout"
  11. android:layout_width="match_parent"
  12. android:layout_height="match_parent">
  13.  
  14. <android.support.v7.widget.RecyclerView
  15. android:id="@+id/recycler_view"
  16. android:layout_width="match_parent"
  17. android:layout_height="wrap_content"/>
  18.  
  19. </android.support.v4.widget.SwipeRefreshLayout>
  20. </LinearLayout>

            这里面有一个SwipeRefreshLayout其实就是那个下拉刷新的图标,id为:refresh_layout。           

            然后实现了BaseFragment中的抽象方法==>initViews(ViewHolder holder,View root)从适配器中获得数据。然后在RefreshRecyclerFragment修改了刷新图标的颜色和偏移量。

            这里有布局中id叫做recycler_view的RecyclerView非常关键,如果没有setAdapter,那么所有数据都无法显示了。mAdapter事先注册了一个mFooterProvider数据的。

            然后实现了两个抽象方法:

        

  1.             需要在继承者中实现。然后是监听RefreshLayout下拉刷新:
          

          如何刷新呢?

          

          request函数也是一个抽象函数,在继承者中具体实现。

  1.           然后是加载更多==>loadMore()
            

          好像都是先一个request函数,返回一个字段,然后将这个字段放在本地的一个ArrayMap中,这个是请求类型,第二个字段是请求类型是“load_more”或者“refresh”。

  1.              这里使用了一个注解:@Subscribe(threadMode=ThreadMode.MAIN)==>表示该函数在主线程即UI线程中执行。 
                 这里是返回事件,即成功刷新,或者成功加载,或者刷新失败,加载失败后的结果。 

            其实这里也只是过渡,其实还是没有处理数据,还是交给继承者来处理。真正的刷新和加载要和mAdapter挂钩的呢。

  1.            这里有一个onError方法,先处理一些状态,判断是刷新还是加载更多,真正的出错还要交给继承者来处理。
            
  1.               然后是设置一些基本方法,包括能否刷新,能否加载更多,能否到返回到顶部。

                  然后是进入onStart()和onStop()环节了。
        

              不太了解EventBus?

        ==>EventBus是一个Android事件发布/订阅框架,通过解耦发布者和订阅者简化Android事件传递,这里的事件可以理解为消息。事件传递可以用于Android四大组件间通讯,也可以用于异步线程和主线程间通讯等。传统的事件传递方式包括:Handler,BroadcastReceiver,Interface回调,相比之下EventBus的特点是代码简洁,使用简单,并将事件发布和订阅充分解耦。

  1.         然后是需要继承类处理的部分

                      第一个抽象函数是加载初始化数据。
                      第二个抽象函数是注册数据类型。
              

                   第三个抽象函数获取RecyclerView的LayoutManager。

  1.                   第四个抽象函数是:请求数据了,返回请求的uuid。        

                      第五个抽象函数是onRefresh==>数据刷新成功后的回调。

                          第六个抽象函数是onLoadMore==>数据加载成功是的回调。

    

                      第七个抽象函数是:onError==>数据加载错误时调           

            6.1.2.回到SimpleRefreshRecyclerFragment。其实这三个类是一层接一层            

              ==>BaseFragment->RefreshRecycleFragment->SimpleRefreshRecyclerFragment。

  1.               这个SimpleRefreshRecycleFragment也只是一个抽象类,所以虽然继承了RefreshRecycleFragment,但是并没有时间所有7个抽象方法,只实现了4个。
  2.  
  3.             6.1.3.第一个是getRecyclerViewLayoutManager==>
                这个SpeedyLinearLayoutManager是什么鬼?自己定义的一个类,附上源代码吧!
  1. /*
  2. * Copyright 2017 GcsSloop
  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. * Last modified 2017-04-10 20:16:42
  17. *
  18. * GitHub: https://github.com/GcsSloop
  19. * Website: http://www.gcssloop.com
  20. * Weibo: http://weibo.com/GcsSloop
  21. */
  22.  
  23. package com.gcssloop.recyclerview.layoutmanager;
  24.  
  25. import android.content.Context;
  26. import android.graphics.PointF;
  27. import android.support.v7.widget.LinearLayoutManager;
  28. import android.support.v7.widget.LinearSmoothScroller;
  29. import android.support.v7.widget.RecyclerView;
  30. import android.util.AttributeSet;
  31. import android.util.DisplayMetrics;
  32.  
  33. /**
  34. * 支持快速返回的 LinerLayoutManager
  35. */
  36. public class SpeedyLinearLayoutManager extends LinearLayoutManager {
  37.  
  38. private static final float MILLISECONDS_PER_INCH = 6f; //default is 25f (bigger = slower)
  39.  
  40. public SpeedyLinearLayoutManager(Context context) {
  41. super(context);
  42. }
  43.  
  44. public SpeedyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
  45. super(context, orientation, reverseLayout);
  46. }
  47.  
  48. public SpeedyLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int
  49. defStyleRes) {
  50. super(context, attrs, defStyleAttr, defStyleRes);
  51. }
  52.  
  53. @Override
  54. public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int
  55. position) {
  56.  
  57. final LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView
  58. .getContext()) {
  59.  
  60. @Override
  61. public PointF computeScrollVectorForPosition(int targetPosition) {
  62. return SpeedyLinearLayoutManager.this.computeScrollVectorForPosition
  63. (targetPosition);
  64. }
  65.  
  66. @Override
  67. protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
  68. return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
  69. }
  70. };
  71.  
  72. linearSmoothScroller.setTargetPosition(position);
  73. startSmoothScroll(linearSmoothScroller);
  74. }
  75. }
  1.  

                其实是自定义的LinearLayoutManager,这又是啥? ==>就是一个线性布局管理器,这里用到快速到顶部。

  1.             这里复写3个构造函数,在Override一个smoothScrollToPosition函数即可。这是一个支持快速返回的LinearLayoutManager
                如下图是OverridesmoothSrollToPosition函数。 

                  这里有一个LinearSmoothScroller,作用就是决定视图滑动的一些属性。这里有一个MILLISECONDS_PER_INCH决定了滑动的速度。如果设置得很大的话,滑动的就比较慢,如果设置的值很小,滑动的速度就很快。

  1.  
                6.1.4.然后回到SimpleRefreshRecyclerFragment中,第二个Override的函数是onRefresh(),

                    adapter首先清空,然后添加数据。

                这里先了解一下HeaderFooterAdapter。源代码如下:        

  1. /*
  2. * Copyright 2017 GcsSloop
  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. * Last modified 2017-04-08 16:14:18
  17. *
  18. * GitHub: https://github.com/GcsSloop
  19. * WeiBo: http://weibo.com/GcsSloop
  20. * WebSite: http://www.gcssloop.com
  21. */
  22.  
  23. package com.gcssloop.recyclerview.adapter.multitype;
  24.  
  25. import android.support.annotation.NonNull;
  26. import android.support.v7.widget.RecyclerView;
  27. import android.view.ViewGroup;
  28.  
  29. import com.gcssloop.recyclerview.adapter.base.RecyclerViewHolder;
  30.  
  31. import java.util.ArrayList;
  32. import java.util.List;
  33.  
  34. /**
  35. * 带有头部和底部的适配器
  36. * 使用步骤:
  37. * 1. 创建实体类 Bean
  38. * 2. 创建对应的 provider 并继承自 BaseViewProvider, 在对应的 provider 的 onBindView 里面处理内容
  39. * 3. 使用 adapter.register(bean, provider.class) 来将数据实体和 provider 对应起来
  40. * 4. 注册 Header 或者 Footer
  41. * 5. 将数据 data 使用 ArrayList<Object> 类型存储起来, 使用 adapter.addDatas(data) 添加数据
  42. * 6. 大功告成
  43. */
  44. public class HeaderFooterAdapter extends RecyclerView.Adapter<RecyclerViewHolder>
  45. implements TypePool {
  46. private List<Object> mItems = new ArrayList<>();
  47. private MultiTypePool mTypePool;
  48.  
  49. private boolean hasHeader = false;
  50. private boolean hasFooter = false;
  51.  
  52. public HeaderFooterAdapter() {
  53. mTypePool = new MultiTypePool();
  54. }
  55.  
  56. @Override
  57. public int getItemCount() {
  58. assert mItems != null;
  59. return mItems.size();
  60. }
  61.  
  62. @Override
  63. public int getItemViewType(int position) {
  64. assert mItems != null;
  65. Object item = mItems.get(position);
  66. int index = mTypePool.indexOf(item.getClass());
  67. if (index >= 0) {
  68. return index;
  69. }
  70. return mTypePool.indexOf(item.getClass());
  71. }
  72.  
  73. @Override
  74. public void register(@NonNull Class<?> clazz, @NonNull BaseViewProvider provider) {
  75. mTypePool.register(clazz, provider);
  76. }
  77.  
  78. public void registerHeader(@NonNull Object object, @NonNull BaseViewProvider provider) {
  79. if (hasHeader) return;
  80. mTypePool.register(object.getClass(), provider);
  81. mItems.add(0, object);
  82. hasHeader = true;
  83. notifyDataSetChanged();
  84. }
  85.  
  86. public void unRegisterHeader() {
  87. if (!hasHeader) return;
  88. mItems.remove(0);
  89. hasHeader = false;
  90. notifyDataSetChanged();
  91. }
  92.  
  93. public void registerFooter(@NonNull Object object, @NonNull BaseViewProvider provider) {
  94. if (hasFooter) return;
  95. mTypePool.register(object.getClass(), provider);
  96. mItems.add(object);
  97. hasFooter = true;
  98. notifyDataSetChanged();
  99. }
  100.  
  101. public void unRegisterFooter() {
  102. if (!hasFooter) return;
  103. mItems.remove(mItems.size() - 1);
  104. hasFooter = false;
  105. notifyDataSetChanged();
  106. }
  107.  
  108. @Override
  109. public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int indexViewType) {
  110. BaseViewProvider provider = getProviderByIndex(indexViewType);
  111. return provider.onCreateViewHolder(parent);
  112. }
  113.  
  114. @Override
  115. public void onBindViewHolder(RecyclerViewHolder holder, int position) {
  116. assert mItems != null;
  117. Object item = mItems.get(position);
  118. BaseViewProvider provider = getProviderByClass(item.getClass());
  119. provider.onBindView(holder, item);
  120. }
  121.  
  122. @Override
  123. public int indexOf(@NonNull Class<?> clazz) {
  124. return mTypePool.indexOf(clazz);
  125. }
  126.  
  127. @Override
  128. public List<BaseViewProvider> getProviders() {
  129. return mTypePool.getProviders();
  130. }
  131.  
  132. @Override
  133. public BaseViewProvider getProviderByIndex(int index) {
  134. return mTypePool.getProviderByIndex(index);
  135. }
  136.  
  137. @Override
  138. public <T extends BaseViewProvider> T getProviderByClass(@NonNull Class<?> clazz) {
  139. return mTypePool.getProviderByClass(clazz);
  140. }
  141.  
  142. public void addDatas(List<?> items) {
  143. if (hasFooter) {
  144. mItems.addAll(mItems.size() - 1, items);
  145. } else {
  146. mItems.addAll(items);
  147. }
  148. notifyDataSetChanged();
  149. }
  150.  
  151. /**
  152. * 获取纯数据 (不包含 Header 和 Footer)
  153. */
  154. public List<Object> getDatas() {
  155. int startIndex = 0;
  156. int endIndex = mItems.size();
  157. if (hasHeader) {
  158. startIndex++;
  159. }
  160. if (hasFooter) {
  161. endIndex--;
  162. }
  163. return mItems.subList(startIndex, endIndex);
  164. }
  165.  
  166. /**
  167. * 获取全部数据 (包含 Header 和 Footer)
  168. */
  169. public List<Object> getFullDatas() {
  170. return mItems;
  171. }
  172.  
  173. public void clearDatas() {
  174. int startIndex = 0;
  175. int endIndex = mItems.size();
  176. if (hasHeader) {
  177. startIndex++;
  178. }
  179. if (hasFooter) {
  180. endIndex--;
  181. }
  182. for (int i = endIndex - 1; i >= startIndex; i--) {
  183. mItems.remove(i);
  184. }
  185. notifyDataSetChanged();
  186. }
  187. }

                     这是一个带有头部和底部的适配器。这个类其实是在另外一个模块中的。现在先不了解了。

                这里之后直接用adapter.addDatas(event.getBean)添加了数据。注意:这里不仅仅只是添加了一个bean,而是一个List<T>,所以可能会有很多数据都放在这里面了。而adapter只要调用一个addDatas方法就行了。

           6.1.5.然后是一个onLoadMore方法。            

              6.1.6.最后是一个onError方法。

        6.2.终于回到NodeTopicListFragment中了。它继承了一个Topic的bean类。看一下Topic的定义吧。   

  1. /*
  2. * Copyright 2017 GcsSloop
  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. * Last modified 2017-03-08 01:01:18
  17. *
  18. * GitHub: https://github.com/GcsSloop
  19. * Website: http://www.gcssloop.com
  20. * Weibo: http://weibo.com/GcsSloop
  21. */
  22.  
  23. package com.gcssloop.diycode_sdk.api.topic.bean;
  24.  
  25. import com.gcssloop.diycode_sdk.api.base.bean.Abilities;
  26. import com.gcssloop.diycode_sdk.api.user.bean.User;
  27.  
  28. import java.io.Serializable;
  29.  
  30. /**
  31. * topic 简略信息
  32. */
  33. public class Topic implements Serializable {
  34. private int id; // 唯一 id
  35. private String title; // 标题
  36. private String created_at; // 创建时间
  37. private String updated_at; // 更新时间
  38. private String replied_at; // 最近一次回复时间
  39. private int replies_count; // 回复总数量
  40. private String node_name; // 节点名称
  41. private int node_id; // 节点 id
  42. private int last_reply_user_id; // 最近一次回复的用户 id
  43. private String last_reply_user_login; // 最近一次回复的用户登录名
  44. private User user; // 创建该话题的用户(信息)
  45. private boolean deleted; // 是否是被删除的
  46. private boolean excellent; // 是否是加精的
  47. private Abilities abilities; // 当前用户对该话题拥有的权限
  48.  
  49. public void setId(int id) {
  50. this.id = id;
  51. }
  52.  
  53. public int getId() {
  54. return this.id;
  55. }
  56.  
  57. public void setTitle(String title) {
  58. this.title = title;
  59. }
  60.  
  61. public String getTitle() {
  62. return this.title;
  63. }
  64.  
  65. public void setCreated_at(String created_at) {
  66. this.created_at = created_at;
  67. }
  68.  
  69. public String getCreated_at() {
  70. return this.created_at;
  71. }
  72.  
  73. public void setUpdated_at(String updated_at) {
  74. this.updated_at = updated_at;
  75. }
  76.  
  77. public String getUpdated_at() {
  78. return this.updated_at;
  79. }
  80.  
  81. public void setReplied_at(String replied_at) {
  82. this.replied_at = replied_at;
  83. }
  84.  
  85. public String getReplied_at() {
  86. return this.replied_at;
  87. }
  88.  
  89. public void setReplies_count(int replies_count) {
  90. this.replies_count = replies_count;
  91. }
  92.  
  93. public int getReplies_count() {
  94. return this.replies_count;
  95. }
  96.  
  97. public void setNode_name(String node_name) {
  98. this.node_name = node_name;
  99. }
  100.  
  101. public String getNode_name() {
  102. return this.node_name;
  103. }
  104.  
  105. public void setNode_id(int node_id) {
  106. this.node_id = node_id;
  107. }
  108.  
  109. public int getNode_id() {
  110. return this.node_id;
  111. }
  112.  
  113. public void setLast_reply_user_id(int last_reply_user_id) {
  114. this.last_reply_user_id = last_reply_user_id;
  115. }
  116.  
  117. public int getLast_reply_user_id() {
  118. return this.last_reply_user_id;
  119. }
  120.  
  121. public void setLast_reply_user_login(String last_reply_user_login) {
  122. this.last_reply_user_login = last_reply_user_login;
  123. }
  124.  
  125. public String getLast_reply_user_login() {
  126. return this.last_reply_user_login;
  127. }
  128.  
  129. public void setUser(User user) {
  130. this.user = user;
  131. }
  132.  
  133. public User getUser() {
  134. return this.user;
  135. }
  136.  
  137. public void setDeleted(boolean deleted) {
  138. this.deleted = deleted;
  139. }
  140.  
  141. public boolean getDeleted() {
  142. return this.deleted;
  143. }
  144.  
  145. public void setExcellent(boolean excellent) {
  146. this.excellent = excellent;
  147. }
  148.  
  149. public boolean getExcellent() {
  150. return this.excellent;
  151. }
  152.  
  153. public void setAbilities(Abilities abilities) {
  154. this.abilities = abilities;
  155. }
  156.  
  157. public Abilities getAbilities() {
  158. return this.abilities;
  159. }
  160.  
  161. @Override
  162. public boolean equals(Object obj) {
  163. if (!(obj instanceof Topic)) {
  164. return false;
  165. }
  166. Topic temp = (Topic) obj;
  167. if (temp.getId() == getId()) {
  168. return true;
  169. }
  170. return false;
  171. }
  172. }

          这个也是在diycode_sdk中的API中定义的。

          总共有14个信息。这里面有一个Override==>判断一个对象是否是Topic。

          6.3.==>T对应Topic,==>GetTopicsListEvent对应BaseEvent<List<Topic>>(其实GetTopicsListEvent就是继承BaseEvent<List<Topic>>的),这些在sdk-API中已经表现,就不深究了。

        6.4.首先一个静态方法==>newInstance(int nodeId)返回一个NodeTopicListFragment。

返回一个fragment,可以知道,这个Fragment已经具备了下拉刷新,上拉加载更多的功能。具备了返回到顶部的功能。具备了toast功能。

           6.5.实现了在RefreshRecycleFragment中定义的抽象方法==>initData()

            6.6.实现了在RefreshRecycleFragment中定义的抽象方法==>setAdapterRegister()

          6.7.实现在RefreshRecycleFragment中定义的抽象方法==>request(),这里是调用API了。

      7.回到TopicActivity中。进入initViews方法。  

        其实NodeTopicListFragment就是一个Fragment,可以刷新和加载更多的Fragment,同时也设置了Adapter的注册数据类型,还利用API调用了请求方法。

      8.Android Fragment动态添加 ==>就是将上面那个碎片添加到topicActivity中。

  总结一下吧:

    1.首先这个TopicActivity是继承一个BaseActivity的。就是一个标题栏中左上角,其实这个BaseActivity就是处理标题栏的吧。

    2.然后又一个关键的静态函数newInstance,就是实例化一个Topic吧。可能是外部函数想调用话题这个活动,这个函数的意义就是跳转到话题这个活动。

    3.然后是得到布局的id,这个也是BaseActivity中定义的抽象函数,就是整个界面的布局函数,有一个Toolbar,然后是一个FrameLayout占据了其他所有空间。

    4.然后是实现了BaseActivity中定义的抽象函数,初始化视图,将多次继承的fragment赋给这个FrameLayout。就是将碎片给到这个FrameLayout。采用了动态添加方法。

    5.其实,事先,要从Intent中获得NodeId,才能利用这个NodeId,获得相应的碎片,调用了NodeTopicListFragment的newInstance方法,NodeId就是里面的参数。然后从Intent从获得的NodeName作为标题栏的Title。

    6.这个NodeTopicListFragment其实是非常复杂的,它首先是继承了SimpleRefreshRecyclerFragment<Topic,GetTopicsListEvent>类的,这个SimpleRefreshRecyclerFragment是有一个静态的newInstanse方法,供别人调用。然后是实现了3个抽象方法,分别是initData(),setAdapterRegister(),request()三个函数。

    7.SimpleRefreshRecyclerFragment继承了RefreshRecyclerFragment<T,Event>这个Event是从它自己的构造函数中的Event extends BaseEvent<List<T>>获得的,然后这个BaseEvent其实是API中定义的。然后这个SimpleRefreshRecyclerFragment实现了4个抽象方法,都是和加载或者刷新有关系的。

    8.RefreshRecyclerFragment<T,Event extends BaseEvent<List<T>>> 继承了BaseFragment。它是一个具有下拉刷新和上拉加载的Fragment。这个类比较关键,定义了很多抽象函数。主要处理刷新和加载的根本逻辑。包括刷新的图标的颜色,一页最多有多少个数据行。刷新后的状态的变更,和加载成功或者失败后状态的变更。以及EventBus的注册和解注册。

    9.BaseFragment就是继承Fragment的了。这个就是最基本的碎片了。里面有一个配置状态信息的Config类。有一个在线服务器Diycode类,有一个DataCache缓存本地数据的类。然后定义了两个抽象方法和一个onCreateView函数获得ViewHolder,一个onCreate函数初始化一些数据,onActivityCreate函数初始化视图。

    10.其实这个TopicActivity和很多东西挂钩,现在了解了最外层的东西,知道了基本流程,但是很多细节还是要深究一下,比如刷新和加载,还有自定义的Adapter都是涉及到的东西比较多的。

DiyCode开源项目 TopicActivity 分析的更多相关文章

  1. Diycode开源项目 BaseApplication分析+LeakCanary第三方+CrashHandler自定义异常处理

    1.BaseApplication整个应用的开始 1.1.看一下代码 /* * Copyright 2017 GcsSloop * * Licensed under the Apache Licens ...

  2. DiyCode开源项目 BaseActivity 分析

    1.首先将这个项目的BaseActivity源码拷贝过来. /* * Copyright 2017 GcsSloop * * Licensed under the Apache License, Ve ...

  3. Diycode开源项目 UserActivity分析

    1.效果预览 1.1.实际界面预览 1.2. 这是MainActivity中的代码 这里执行了跳转到自己的用户界面的功能. 1.3.点击头像或者用户名跳转到别人的页面 UserActivity的结构由 ...

  4. Diycode开源项目 ImageActivity分析

    1.首先看一下效果 1.1做成了一个GIF 1.2.我用格式工厂有点问题,大小无法调到手机这样的大小,目前还没有解决方案. 1.3.网上有免费的MP4->GIF,参考一下这个网站吧. 1.4.讲 ...

  5. Diycode开源项目 TopicContentActivity分析

    1.效果预览以及布局分析 1.1.实际效果预览 左侧话题列表的布局是通过TopicProvider来实现的,所以当初分析话题列表就没有看到布局. 这里的话题内容不是一个ListView,故要自己布局. ...

  6. Diycode开源项目 MyTopicActivity分析

    1.总体浏览效果及布局分析 1.1.看一下我的帖子预览效果 1.2.然后看一下我的收藏预览效果 1.3.归纳一下 所以我的帖子和我的收藏可以共用同一个类. 布局效果几乎一样,只是用户的选择不同. 所以 ...

  7. Diycode开源项目 LoginActivity分析

    1.首先看一下效果 1.1.预览一下真实页面 1.2.分析一下: 要求输入Email或者用户名,点击编辑框,弹出键盘,默认先进入输入Email或用户名编辑框. 点击密码后,密码字样网上浮动一段距离,E ...

  8. Diycode开源项目 MainActivity分析

    1.分析MainActivity整体结构 1.1.首先看一下这个界面的整体效果. 1.2.活动源代码如下 /* * Copyright 2017 GcsSloop * * Licensed under ...

  9. DiyCode开源项目 AboutActivity分析

    1.首先看一下效果 这是手机上显示的效果: 1.1首先是一个标题栏,左侧一个左箭头,然后一个图标. 1.2然后下方是一个可以滑动的页面. 1.3分成了7个部分. 1.4DiyCode的图标. 1.5然 ...

随机推荐

  1. 在JavaScript中同步与异步

    在JavaScript中,一个线程执行的时候不依靠其他线程处理完毕我们称为异步,相反一个线程必须等待直到另一个线程处理完毕我们则称为同步.打个比方: (1)同步就是你在煮方便面的时候必须等水开了,你才 ...

  2. 表格<table>

    <table> <tr> <th>表头1</th> <th>表头2</th> <th>表头3</th> ...

  3. 【ros depthimage_to_laser kinect2】

    kinect2的深度图可以转换成激光来用,使用depthimage_to_laser 这个tf是用来给rviz显示的 1)开启kinect2 rosrun kinect2_bridge kinect2 ...

  4. 本地eclipse启动tomcat后无法访问

    转自博文:http://blog.csdn.net/wqjsir/article/details/7169838/ 症状: tomcat在eclipse里面能正常启动,而在浏览器中访问http://l ...

  5. linux命令 ——目录

    开始详细系统的学习linux常用命令,坚持每天一个命令,所以这个系列为每天一个linux命令.学习的主要参考资料为: 1.<鸟哥的linux私房菜> 2.http://codingstan ...

  6. JS 中的string.lastIndexOf()

    一直转不过来一个弯,就是string.lastIndexOf(searchString,position)  当有position这个参数时,结果是什么 先看代码: var text = 'Missi ...

  7. [转载]AngularJS入门教程04:双向绑定

    在这一步你会增加一个让用户控制手机列表显示顺序的特性.动态排序可以这样实现,添加一个新的模型属性,把它和迭代器集成起来,然后让数据绑定完成剩下的事情. 请重置工作目录: git checkout -f ...

  8. 使ListView控件中的选择项高亮显示

    实现效果: 知识运用: ListView控件的SelectedItems属性 //获取在ListView控件中被选中数据项的集合 public ListView.SelectedListViewIte ...

  9. 2018.5.24 Oracle下的sqlplus编程 块结构

    1.语句结构模板 declare --声明 begin dbms_output.put_line('Legend Hello world'); end; 2.变量使用 & 是输入符号 decl ...

  10. 删除临时文件的bat文件

    @echo offecho 正在清除系统垃圾文件,请稍等......del /f /s /q %systemdrive%\*.tmpdel /f /s /q %systemdrive%\*._mpde ...