多看多学涨姿势

最近学习了一个开源项目,感觉收获颇多,这里做下简要的记录,首先感谢作者的开源。先看个大概图

感觉框架非常简单,界面也很一般,不过底层的处理的一些处理还是有很多可圈可点之处,代码的处理一看就是有工作经验的,下面将细细道来。项目在github传送门

启动

很经典的使用handler+子线程的延时加载方式,多了一个权限检查,应该是6.0系统中权限限制后需要用户手动设置,主要使用到一些系统intent的使用如启动应用设置的如

  1. // 启动应用的设置
  2. private void startAppSettings() {
  3. Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
  4. intent.setData(Uri.parse(PACKAGE_URL_SCHEME + getPackageName()));
  5. startActivity(intent);
  6. }

需要在6.0系统做权限检查的可以去参考一下,顺便说一下,这里作者的处理方式是将相应的权限放置数组中检查权限,若是缺少通过startActivityForResult方式启动权限处理Actvity,处理完回调继续进行流程。

基类

稍微有点的经验的小伙伴写一个app时候都会先写上BaseActvity、BaseFragment,这里体现出很好的代码重用的思想。比如目前最常见的titlebar,每个Actvity都有,但是不同的Actvity的titlebar字段是不一样的,为了干掉冗余的代码可以都集成到基类中;Activity的入站管理等等,这些全局或者公共部分都可以放入一个基类

来看下作者的BaseActvity部分代码

  1. public abstract class BaseActivity extends AppCompatActivity {
  2. protected Toolbar toolbar;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. onBeforeSetContentLayout();
  7. //禁止横屏省去在配置文件中逐个设置
  8. setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
  9. //base类中都会有App管理,将activity统一入栈,可以在退出时全局退出
  10. AppManager.getAppManager().addActivity(this);
  11. // 隐藏ToolBar
  12. // hideToolBar();
  13. Logger.d("当前Activity 栈中有:" + AppManager.getAppManager().getActivityCount() + "个Activity");
  14. }
  15. /**
  16. * 隐藏ToolBar
  17. */
  18. public void hideToolBar() {
  19. if (getSupportActionBar() != null) {
  20. getSupportActionBar().hide();
  21. }
  22. }
  23. ……
  24. ……
  25. }

作者在基类中封装了titleBar、Actvity的入栈管理、禁止横屏。

  • titlebar

    这个就不多说了

  • Activty全局管理,

    一般都是用一个工具类来分装AppManager.getAppManager().addActivity(this); 将每个启动的Actvity加入到一个队列中管理,便于两次back全局退出或者按安全退出按钮。这个工具类后面会有分析

  • 禁止横屏

    通常都是这样的,横屏之后actvity都会销毁重建处理起来不方面,直接禁止横屏得了,还有一种方式就是在配置文件中对需要禁止横屏的单独配置,这里通过代码全局禁止了横屏。

其他的部分一看作者就是从以前的项目中copy来的,那个TDevice关闭软键盘、状态栏兼容性,其实还可以在BaseAcivty中假如一些字体设置、actvity完结后的换场动画,actvity的透明度等等

再来看看作者的BaseFragment部分代码

只完成一件事,懒加载 重写了fragment中的setUserVisibleHint

  1. public abstract class BaseFragment extends Fragment {
  2. /**
  3. * Fragment当前状态是否可见
  4. */
  5. protected boolean isVisible;
  6. protected boolean isCreate = true;
  7. protected BaseActivity mActivity;
  8. @Override
  9. public void onAttach(Activity activity) {
  10. this.mActivity = (BaseActivity) activity;
  11. super.onAttach(activity);
  12. }
  13. @Override
  14. public void onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. }
  17. /**
  18. * 实现该方法即可实现可见再加载。不可见不加载的效果!!!
  19. *
  20. * @param isVisibleToUser
  21. */
  22. @Override
  23. public void setUserVisibleHint(boolean isVisibleToUser) {
  24. super.setUserVisibleHint(isVisibleToUser);
  25. isCreate = false;
  26. if (getUserVisibleHint()) {
  27. isVisible = true;
  28. onVisible();
  29. } else {
  30. isVisible = false;
  31. onInvisible();
  32. }
  33. }
  34. ……
  35. ……

在继承的fragment中的onccreateView中还会配合使用缓存来判断是否需要再次加载

  1. @Override
  2. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  3. if (mRootView == null) {
  4. mRootView = getRootView();
  5. initArguments();//初始化参数
  6. creatBaseViews();
  7. createViewsOrListener();
  8. }
  9. //缓存的mRootView需要判断是否已经被加过parent, 如果有parent需要从parent删除,要不然会发生这个mRootView已经有parent的错误。
  10. ViewGroup parent = (ViewGroup) mRootView.getParent();
  11. if (parent != null) {
  12. parent.removeView(mRootView);
  13. }
  14. return mRootView;
  15. }

这里多说一句,其实还有一种防止fragment每次重新加载方式,就是使用viewpager+fragment方式,在viewpager中 pager.setOffscreenPageLimit(2);这里表示每次缓存俩个fragmengt,作者这里采用 FragmentTabHost方式搭建底部tab,只能对每个fragment进行处理

框架

这里作者采用的是 FragmentTabHost搭建的方式,个人比较不喜欢这种方式,首先,需要手动消除Tab切换时候按钮之间的分割线,而且不能够滑动切换比较僵硬,推荐radiobutton+viewpager+fragment,可以看看我早期写的一个demo简单app框架,不过作者使用枚举类处理fragment的方式让我眼前一亮,原谅我的少见多怪吧。

Indicator.actvity

  1. public enum Indicator {
  2. REVIEW(0, R.string.main_tab_name_review, R.drawable.tab_icon_review,
  3. ReviewFragment.class),
  4. TEST(1, R.string.main_tab_name_test, R.drawable.tab_icon_test,
  5. TestFragment.class),
  6. SETTING(2, R.string.main_tab_name_setting, R.drawable.tab_icon_other,
  7. SettingFragment.class);
  8. private int idx;
  9. private int resName;
  10. private int resIcon;
  11. private Class<?> clz;
  12. private Indicator(int idx, int resName, int resIcon, Class<?> clz) {
  13. this.idx = idx;
  14. this.resName = resName;
  15. this.resIcon = resIcon;
  16. this.clz = clz;
  17. }
  18. public int getIdx() {
  19. return idx;
  20. }
  21. public void setIdx(int idx) {
  22. this.idx = idx;
  23. }
  24. public int getResName() {
  25. return resName;
  26. }
  27. public void setResName(int resName) {
  28. this.resName = resName;
  29. }
  30. public int getResIcon() {
  31. return resIcon;
  32. }
  33. public void setResIcon(int resIcon) {
  34. this.resIcon = resIcon;
  35. }
  36. public Class<?> getClz() {
  37. return clz;
  38. }
  39. public void setClz(Class<?> clz) {
  40. this.clz = clz;
  41. }
  42. }

在MainActivity中通过Indicator[] indicators = Indicator.values();就将枚举放到数组中了,这里values()方法是编译器添加的静态方法,Enum类中并没有该方法,该方法可以遍历枚举的实例。

再按一次退出应用

大家在使用App时经常会看到这个toast,这个项目中也可以学到,主要是在MainActivity中重写onKeyDown方法,再加上俩个工具类,DoubleClickExitHelper,AppManager(堆栈式管理Actvity)

MainActivity中重写onKeyDown方法

  1. @Override
  2. public boolean onKeyDown(int keyCode, KeyEvent event) {
  3. if (keyCode == KeyEvent.KEYCODE_BACK) {
  4. return mDoubleClickExit.onKeyDown(keyCode, event);
  5. }
  6. return super.onKeyDown(keyCode, event);
  7. }

如果你的app是侧滑式的需要判断一下抽屉是否打开,要是抽屉打开就关闭抽屉而不是退出

  1. @Override
  2. public boolean onKeyDown(int keyCode, KeyEvent event) {
  3. if (keyCode == KeyEvent.KEYCODE_BACK) {
  4. if(mDrawerLayout.isDrawerOpen(GravityCompat.START)){
  5. mDrawerLayout.closeDrawers();
  6. return true;
  7. }
  8. return DoubleClickExit.onKeyDown(keyCode, event);
  9. }
  10. return super.onKeyDown(keyCode, event);
  11. }

DoubleClickExitHelper工具类主要是使用handler方式获取到主线程的消息队列new Handler(Looper.getMainLooper());然后再onKyDown方法中延时处理,选择再按一次也许是防止用户点击出错吧。

关于网络

这里采用的bmob的云后台来管理数据,bmob提供一个云的数据库来存储我们的数据,传送门 已经弄了一个demo来玩了,挺不错的。下篇再继续介绍各个tab中的比较好的技术点。

开源项目AndroidReview学习小结(1)的更多相关文章

  1. 开源项目AndroidReview学习小结(2)

    读书破万卷下笔如有神 作为入门级的android码农的我,还是需要多多研读开源代码 下面继续接着上一篇的分析,这一篇主要介绍第一个tab,ReviewFragment的分析,界面看起来简单,背后的逻辑 ...

  2. Android 开源项目及其学习

    Android 系统研究:http://blog.csdn.net/luoshengyang/article/details/8923485 Android 腾讯技术人员博客 http://hukai ...

  3. 开源项目live555学习心得

      推荐:伊朗美女找丈夫比找工作难女人婚前一定要看清三件事 × 登录注册   疯狂少男-IT技术的博客 http://blog.sina.com.cn/crazyboyzhaolei [订阅][手机订 ...

  4. 一个toolkit或者一个开源项目如何学习它并使用它

    一个toolkit或者一个开源项目如何学习它并使用它 一般一个流行的toolkit和开源项目,一般都会被广泛地被应用: 那么,我们如何学习它,如何应用它在自己的业务场景中呢? 答案就是:学习源码并借鉴 ...

  5. iOS及Mac开源项目和学习资料【超级全面】

    UI 下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITable ...

  6. iOS开发--iOS及Mac开源项目和学习资料

    文/零距离仰望星空(简书作者)原文链接:http://www.jianshu.com/p/f6cdbc8192ba著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 原文出处:codecl ...

  7. Android开源项目SlidingMenu学习(二)

    前一篇SlidingMenu学习(一)文章中了解了导入SlidingMenu到我们项目经常出现的问题,下面我们正式学习. 先看一个效果: 看到两幅图片的差别了吗,左边的一栏时可以滑动的,可以隐藏掉,现 ...

  8. 分享海量 iOS 及 Mac 开源项目和学习资料

    UI 下拉刷新 EGOTableViewPullRefresh - 最早的下拉刷新控件. SVPullToRefresh - 下拉刷新控件. MJRefresh - 仅需一行代码就可以为UITable ...

  9. Github搭建属于自己的开源项目-androd学习之旅(72)

    Github是一个基于的git的版本控制工具,分为私人代码管理和开源代码管理,下面我们简单的介绍一下 首先登陆官网https://github.com 完成注册,随后首页会有四个模块,第一个是安装的指 ...

随机推荐

  1. nfc开发

    很多Android设备已经支持NFC(近距离无线通讯技术)了.本文就以实例的方式,为大家介绍如何在Android系统中进行NFC开发. Android NFC开发环境 使用硬件:Google Nexu ...

  2. ROS讲座 关于ROS2和Gazebo C++ in Open Source Robotics

    分享一个不错的介绍ROS2和Gazebo的视频讲座. Gazebo中的云彩飘动起来了!!!! 超清视频分享网址:    http://v.youku.com/v_show/id_XMTcyMzY0Nz ...

  3. Android系统剪切板

    Android系统剪贴板 复制字符串到系统剪切板 /** * 复制文本到剪切板 * * @param text * @return */ @SuppressWarnings("depreca ...

  4. Oracle使用游标删除所有用户数据表中的所有记录脚本

    应用场景:因为数据库中的数据涉及机密信息,希望一次性能删除掉所有数据,只保留数据表结构,供新项目开发程序用 测试结果:经查询已删除所有数据 存在问题:数据表如果存在外键的话下面脚本可能执行不成功,请自 ...

  5. 开源项目——小Q聊天机器人V1.0

    小Q聊天机器人V1.0 http://blog.csdn.net/baiyuliang2013/article/details/51386281 小Q聊天机器人V1.1 http://blog.csd ...

  6. Android:ADB server didn't ACK或者adb server is out of date. killing解决办法

    欢迎关注公众号,每天推送Android技术文章,二维码如下:(可扫描) 出现这个原因我个人感觉有两个.一.5037端口被别的程序或者进程占用:二.adb占用的不是5037端口.很多人仅仅知道第一种二忽 ...

  7. Java进阶(三十三)java基础-filter

    java基础-filter 我们先看看没有filter的时候,整个web客户端-服务端的一个流程. 接下来我们再看看引入了filter之后的Uml图.尝试分析这两者之间的差别. filter从哪里来? ...

  8. MO_GLOBAL包中一些过程和函数的使用

    DECLARE V_CURRENT_ORG_ID NUMBER; V_ACCESS_MODE VARCHAR2(2); V_OU_COUNT NUMBER; V_ORG_ID NUMBER; V_MO ...

  9. 08_Android中的SimpleAdapter的使用

     1 目的界面 2.编写Android清单文件 <?xml version="1.0" encoding="utf-8"?> <manif ...

  10. Hive操作语句实例讲解(帮助你了解 桶 bucket)

    http://blog.sina.com.cn/s/blog_66474b16010182yu.html这篇可以较好地理解什么是外部表external #创建表人信息表  person(String ...