gcoder.io

记录此时此刻


  • 首页

  • 归档

  • 标签

  • 关于

  • 搜索

成长的四个阶段,你在哪里?

发表于 2017-06-04 | 分类于 思考 | 阅读次数
字数统计 291

专业能力

做当前工作最基本的能力,反映在你做大部分任务是得心应手还是很吃力。而当你每次都很吃力的时候,你是否有想过去改变?

执行力

做事必须有具体的Deadline,而相对立的是懒散的、无目标的去执行。当任务延期时,去思考是专业能力、时间安排、任务细节的反复修改、琐碎任务的穿插打断对计划的影响。

主动

主动做事、沟通。当发现问题时,去主动协调资源解决而不是等待、抱怨,甚至是无为。当你主动解决一些问题后,你会发现你是任务的推动者而不是纯粹的执行者,而赋予自己更大的成就感,从而形成一个良性的循环。逐步消除惰性思维,遇到问题不要只反映,思考并解决会让你成长的更快。

信任

信任是一个渐进的过程,是对长期具体事务交付结果认可的累积。长期不断的成长会逐步取得信任的量变。

Android MVP

发表于 2017-05-06 | 分类于 Andorid | 阅读次数
字数统计 1,397

MVP,抽取Controller中业务逻辑独立到Presenter,解决Controller臃肿,View与Presenter间通过Interface交互,代码逻辑更加清晰,同时Presenter更方便写单元测试;

架构设计:

阅读全文 »

Android 开发常见问题集锦

发表于 2017-04-23 | 分类于 Android | 阅读次数
字数统计 912

Fragment常见问题

  • 自己构造Fragment一定要把数据存起来;
  • DialogFragment show()方法会有大量的崩溃,现在都改成showAllowingStateLoss啦,后面不要再用show()方法啦;
  • 同样所有Fragment的commit也会存在大量的崩溃,需要都改成commitAllowingStateLoss;
  • Fragment中getContext getActivity都不要用,崩溃概率很大,请在onAttach方法中获取Activity使用;
  • 所有基于MVP的Fragment都需要处理Activity重启后Presenter的恢复;

Activity

  • Activity Theme不统一,应该使用Application中配置;

第三方服务

  • 所有第三方服务初始化必须try catch并异常上报;

Intent

  • 涉及到系统的intent一定要trycatch,这个兼容性问题比较大,很容易crash

Application

  • Application onCreate在多进程场景下的处理;
阅读全文 »

Android 持续集成实践(一):打包流程优化

发表于 2017-04-15 | 分类于 Android | 阅读次数
字数统计 1,955

打包流程

具体实现

Gradle配置文件归类

分类需要同步和不需要同步的配置文件,解决多分支模型下切换分支更改版本号等不需要同步的操作,gralde仍提示同步的问题,让真正需要同步的变更才提示。

  • 新建version.gradle文件,添加变更时不需要同步的参数;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ext {
    // 打生产包命令:./gradlew assembleReleaseChannels
    // 打patch包命令:./gradlew buildTinkerPatchRelease
    // 当前编译状态,生产环境必须配置为false
    isDebug=true
    // 标识是否为补丁模式
    isPatchModel=false
    // 是否上传符号表
    uploadMappingEnable=false
    // 补丁模式,补丁文件对应的基准apk文件夹
    patchBaseApkDir=""
    version_name="1.1.0.100"
    // 规则,年+月+日+当日发版次数
    version_code=17041501
    }
  • 将version.gradle添加到项目根目录build.gradle顶部;

    1
    apply from: 'version.gradle'
阅读全文 »

GoogleAnalytics在电商场景下的实践

发表于 2017-04-03 | 分类于 电商 | 阅读次数
字数统计 3,434

GA提供了多个维度的数据分析,覆盖了电商场景下所有的统计需求;

行为

屏幕

一级屏幕

二级屏幕

名词解释

  • 二级屏幕:在一级屏幕基础上细分的二级屏幕;
  • 屏幕名称:屏幕统计埋点,key的名字;
  • 屏幕浏览量:屏幕pv,等于当前屏幕所有二级屏幕pv总和;
  • 唯一屏幕浏览量:屏幕浏览会话数量(默认30分钟),等于当前屏幕所有二级屏幕会话数量的总和;
阅读全文 »

Android 网络层Library设计

发表于 2017-03-26 | 分类于 Android | 阅读次数
字数统计 1,950

网络层Library是App最常用的库,需要考虑稳定性,后期的扩展性,更换核心网络库后对项目的影响,ZZNet采用okhttp作为核心网络库。

需求描述:

  • 支持HTTP/HTTPS;
  • 请求支持取消;
  • 支持校验器,可用于统一的JSON校验;
  • 支持拦截器,可用于缓存的处理;
  • 支持重试次数和自定义重试规则;
  • 支持文件上传,上传进度,多文件上传,取消上传;
  • 支持文件下载,下载进度,断点续传,取消下载;
  • 自动处理错误描述和详细的错误类型;

架构设计:

阅读全文 »

ZAOZUO Android代码规范

发表于 2017-02-26 | 分类于 Android | 阅读次数
字数统计 712

规范是提高团队开发协作效率的前提,请大家务必重视;
规范主要解决两个问题:1.提高协作效率;2.绕过已知的问题;

命名规范:

Bundle命名规范:

  • 工程名:
    • 业务Bundle:biz_xxx
    • Library Bundle:lib_xxx
    • jar或aar Bundle:zzbin_xxx
  • 包名:
    • 业务Bundle:com.zaozuo.biz.xxx
    • Library Bundle:com.zaozuo.lib.xxx

包名命名规范:

  • com.zaozuo.[biz/lib].[模块名].[业务名]

    1
    2
    3
    4
    5
    6
    com.zaozuo.biz.show.home
    entity :实体类
    presenter
    view:Activity/Fragment
    widget:自定义控件
    viewholder:item/itemGroup

资源文件命名:

  • 所有在R文件中生成资源文件必须添加模块前缀和业务前缀,规则:[业务模块名] _ [业务名] _ [具体名字];

    1
    2
    3
    4
    5
    layout命名:
    activity/fragment对应的xml:biz_order_orderlist.xml
    item对应的xml:biz_order_orderlist_item_topview.xml
    drawable命名:
    biz_order_orderlist_btn_camera.xml
  • xml中id对应的控件名字采用缩写:[业务模块名字] _ [业务名] _ [按钮名字] _ [控件简称];

    1
    2
    biz_order_orderlist_avatar_iv
    biz_order_orderlist_confirm_btn
  • style也需要添加前缀:例如Biz_Show_SplashTheme

    阅读全文 »

Android Activity生命周期和启动模式你不知道的那些事

发表于 2016-10-05 | 分类于 Android | 阅读次数
字数统计 2,387

此文是根据官方文档、图书资料及demo测试得出的结论,包括Activity多个页面间跳转的生命周期,各个启动模式的不同,flag的常见用法及对activity任务栈的影响。

Activity生命周期需要注意的地方

  • 当Activity长时间在后台运行时,可能会被杀死,再次启动时Activity会被重建,此情况和横竖屏切换场景类似,开发者应该在开发环境下打开横竖屏切换测试,防止异常发生;
  • 如果新的Activity是透明主题,则当前Activity不会执行onStop;
  • onSaveInstanceState在onStop之前执行,onRestoreInstanceState在onStart之后执行;
  • 为防止Activity横竖屏切换时Activity重启,可添加 android:configChanges=”orientation|screenSize”
  • onStart和onStop,判断Activity是否可见,onResume和onPause,判断Activity是否在前台;
  • A启动B,A、B生命周期执行顺序:A会先进入后台,B创建进入前台,A不可见;

    1
    A(onPause) --> B(onCreate) --> B(onStart) --> B(onResume) --> A(onSaveInstanceState) ->A(onStop)

Activity启动模式

Standard:标准模式

  • 每次都会新创建Activity,并添加到对应的任务栈中;

SingleTop:栈顶复用

  • 如果要启动的Activity已经在栈顶,该Activity不会被创建;

    1
    2
    3
    * A --> B(SingleTop)
    * 再次启动B后生命周期:
    onPause --> onNewIntent --> onResume
  • 如果要启动的Activity不在栈顶,跟标准模式完全一致;

    1
    2
    3
    * A --> B(SingleTop) --> C
    * 再次启动B后栈:
    A --> B(SingleTop) --> C --> B(SingleTop)

SingleTask:栈内复用模式

  • 特别注意,配置此模式的Activity并不会位于一个新的任务栈中,只是如果要启动的Activity已经在栈中,会clearTop,让自己置为栈顶;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    * A --> B(SingleTask) --> C
    TaskRecord{ed93b47 #259 A=test.gcoder.io.testactivity, isShadow:false U=0 sz=4}
    Run #3: ActivityRecord{c1f4817 u0 test.gcoder.io.testactivity/.CActivity, isShadow:false t259}
    Run #2: ActivityRecord{59e1a72 u0 test.gcoder.io.testactivity/.BActivity, isShadow:false t259}
    Run #1: ActivityRecord{d7ae33c u0 test.gcoder.io.testactivity/.AActivity, isShadow:false t259}
    * 再次启动B后任务栈:
    A --> B(SingleTask)
    此时C会被销毁
    此时B的生命周期:onPause --> onNewIntent --> onResume
    TaskRecord{ed93b47 #259 A=test.gcoder.io.testactivity, isShadow:false U=0 sz=3}
    Run #2: ActivityRecord{59e1a72 u0 test.gcoder.io.testactivity/.BActivity, isShadow:false t259}
    Run #1: ActivityRecord{d7ae33c u0 test.gcoder.io.testactivity/.AActivity, isShadow:false t259}

SingleInstance:单实例模式

  • 此模式的Activity只能位于一个独立任务栈中;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    * A --> B(SingleInstance) --> C
    此时,A、C位于同一个任务栈,B位于独立的任务栈;
    TaskRecord{c37f244 #253 A=test.gcoder.io.testactivity, isShadow:false U=0 sz=3}
    Run #3: ActivityRecord{8d06468 u0 test.gcoder.io.testactivity/.CActivity, isShadow:false t253}
    TaskRecord{10b2e56 #257 A=test.gcoder.io.testactivity, isShadow:false U=0 sz=1}
    Run #2: ActivityRecord{eeb0317 u0 test.gcoder.io.testactivity/.BActivity, isShadow:false t257}
    TaskRecord{c37f244 #253 A=test.gcoder.io.testactivity, isShadow:false U=0 sz=3}
    Run #1: ActivityRecord{e25c532 u0 test.gcoder.io.testactivity/.AActivity, isShadow:false t253}
    * 再次启动B后栈:
    A --> C --> B(SingleInstance)
    此时,B调整为前台任务栈,A、C的任务栈调整为后台任务栈;
    此时,B的生命周期:onPause --> onNewIntent --> onResume
    TaskRecord{10b2e56 #257 A=test.gcoder.io.testactivity, isShadow:false U=0 sz=1}
    Run #3: ActivityRecord{eeb0317 u0 test.gcoder.io.testactivity/.BActivity, isShadow:false t257}
    TaskRecord{c37f244 #253 A=test.gcoder.io.testactivity, isShadow:false U=0 sz=3}
    Run #2: ActivityRecord{8d06468 u0 test.gcoder.io.testactivity/.CActivity, isShadow:false t253}
    Run #1: ActivityRecord{e25c532 u0 test.gcoder.io.testactivity/.AActivity, isShadow:false t253}
阅读全文 »

Android HotPatch在线热补丁方案

发表于 2015-08-12 | 分类于 Android | 阅读次数
字数统计 815

本教程采用阿里dexposed开源库实现。
https://github.com/alibaba/dexposed

主APP实现:

主程序Application onCreate方法中初始化dexposed

1
DexposedBridge.canDexposed(context);

Patch apk下载及修复:

  1. 为保证修复patch的及时性,使用push推送patch,客户端收到消息后立即完成patch的下载及修复;
  2. 客户端版本管理模块在程序入口Activity中检测是否有需要修复的patch;
  3. 下载完patch apk到程序私有目录,即/data/data/packageName/files目录,同时可在xml中保存patch apk本地存储路径、方便下载启动app时加载补丁patch。
阅读全文 »

iOS Swift开发中需要注意的问题

发表于 2015-07-25 | 分类于 iOS | 阅读次数
字数统计 762
  • 普通block和lazy底层是闭包,必须注意self指针泄露,解决方案同block:

    1
    2
    3
    private lazy var oneButtonView : OneButtonView? = {[weak self] in
    return self?.instanceOneButtonView()
    }()
  • 判断字符串相等时必须先校验是否为nil,否则崩溃

    1
    2
    if name != nil && name == "UserName"{
    }
  • 超级坑,View的名字不可于VC相似
    例如:BuyPresellView BuyPresellViewController,会造成BuyPresellViewController自动从BuyPresellView.xib加载;

  • UITextLabel text设置为nil或””时该控件的高度为0,如果想正常显示可设为” “

  • 可选值不可与非可选值进行比较,例如String?和String,必须转换为相同类型才可比较mobile != nil && mobile! == text,注意判断非空;
  • 点击事件触发网络操作,需要用到index时,可使用id替换,防止非阻塞对话框导致用户继续操作,造成index改变;
  • 所有涉及到数组、集合index取值、删除等操作必须校验Index范围保证不会越界;
  • switch中case必须加break,避免养成习惯在其它编程语言中造成问题;
  • 禁止在layoutSubviews编写任何AutoLayout代码,会造成在iOS7.X崩溃;
  • 字符串拼接的时候,如果是可选型必须强制转换,否则string会带Optional字符串;
  • 系统api重写时必须调用super;
  • 添加NSNotification监听的类必须是NSObject的子类,并且响应函数不能使用private修饰,否则崩溃;
阅读全文 »
12
gcoder.io

gcoder.io

14 日志
5 分类
26 标签
GitHub Weibo
© 2015 - 2017 gcoder.io
由 Hexo 强力驱动
主题 - NexT.Pisces
0%