一、Git Svn:
1.冲突怎么解决?
Git解决冲突:
1、拉去最新代码,将更新的工程文件内容,替换到本地的工程文件
2、将本地项目的文件删除一遍引用,再重新拖入(在工程打开后去删除引用,而不是在本地项目里删除)
SVN解决冲突办法:
1、删除本地.Xcodeproj.
2、再次从svn更新一遍(工程文件会重新下载到本地)
3、将本地项目的文件删除一遍引用,再重新拖入(在工程打开后去删除引用,而不是在本地项目里删除)
Git创建分支以及合并:
1、获取主分支代码(点击check out project from version control)
2、导入代码后需要创建新的分支(VCS->Git->Branches)
3、点击New Branch,在新的弹窗中输入新的分支名点击ok保存之后,就会切换到新创建的分支里,然后在这个分支上进行开发和push,push成功后就可以看到新的分支
合并:
1.分支切换,选中需要切换到的新分支A然后checkout即可切换到分支A。
2.分支合并,A合并到B。先切换到分支B,然后选择merge的分支A进行合并。
SVN创建分支以及合并:
1、创建测试项目并使其和SVN进行关联
2、提交本地新增或改变的文件(创建新分支前最好先将本地修改的文件提升至SVN,SVN每一次提交操作时,都会有一个对应的Revision.创建分支前最后一次提交修改文件时,该操作对应的Revision以供后续合并分支时使用)
3、创建新分支.将项目切换至Project目录,选中项目后点击右键依此选择Subversion->Branch or Tag
4、根据需要选择拷贝源、新分支目录、修改分支项目文件名等,然后填写Comment,点击OK。分支创建成功后,在SVN仓库branches目录对应的文件下选择SVN Update拉取分支代码
5、在branches文件目录下出现一个新的文件夹new_branch时,新分支创建彻底完成
合并:
1、将分支的改动合并到主干(在Android Studio中打开主干项目,切换至Project目录,选中项目并点击右键,依次选择Subversion-> Integrate Directory)
注:Revision默认选中的都是HEAD(即:最新版),此时若点击OK,主干新创建的类会被删除,主干和分支同时修改的类会被分支覆盖,主干中的文件及其内容将变成和分支一模一样;
获取该Revision的方式:
(1)、选中Source 1右侧的Revision为Specified,然后点击其右侧的 ... 按钮
(2)、我们还可以通过查看提交日志的方式,来查看最后一次提交修改所对应的Revision。打开本地从SVN更新到的文件的根目录下,在空白处点击右键,依次选择TortoiseSVN->Show log
通过上面的两种方式得到修改分支合并时的配置后点击OK
2、将主干大改动合并到分支
首先在Android Studio中打开分支项目,从SVN更新代码,保证分支对应的本地代码是最新的。
从主干合并至分支时的其他过程与上述合并过程基本一致,只需将合并配置页的Source 1和Source 2对应的分支路径进行调换,Source 1(即:分支路径)对应的Revision选择创建该分支时,该操作所对应的Revision即可
2.分支怎么创建?
在Androidstudio上直接创建分支,通过git命令创建分支,在GitHub上创建分支
3.分支是干什么的?
SVN的分支是一个完整的目录,这个目录拥有完整的实际文件,你如果修改一个分支其他人也得重新切分支重新下载;Git分支可以在任意自己的本地版本库开启无线分支,自己可以在自己的分支做自己想做的不用管其他分支影响自己,分支名可以使用不同名字
分支是用来做版本更新的
4.怎么合并分支?
在Android studio中选择主分支,然后点击Merge into Current进行子分支与主分支的合并,然后切换到子分支,同上合并主分支与子分支。
二、gradle:
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言来声明项目设置,而不是传统的XML。支持的语言限于Java、Groovy和Scala。
Gradle就是工程的管理,帮我们做了依赖,打包,部署,发布,各种渠道的差异管理等工作。
1.buildscript
buildscript中的声明是gradle脚本自身需要使用的资源。可以声明的资源包括依赖项、第三方插件、maven仓库地址等。
3.repositories
jcenter()、maven()和google()就是托管第三方插件的平台
4.dependencies
当然配置了仓库还不够,我们还需要在dependencies{}里面的配置里,把需要配置的依赖用classpath配置上,因为这个dependencies在buildscript{}里面,所以代表的是Gradle需要的插件。
allprojects
allprojects块的repositories用于多项目构建,为所有项目提供共同所需依赖包。而子项目可以配置自己的repositories以获取自己独需的依赖包。
buildscript和allprojects的作用和区别
buildscript中的声明是gradle脚本自身需要使用的资源,就是说他是管家自己需要的资源,跟你这个大少爷其实并没有什么关系。而allprojects声明的却是你所有module所需要使用的资源,就是说如果大少爷你的每个module都需要用同一个第三库的时候,你可以在allprojects里面声明。
apply plugin:'×××':叫做二进制插件,二进制插件一般都是被打包在一个jar里独立发布的,比如我们自定义的插件,再发布的时候我们也可以为其指定plugin id,这个plugin id最好是一个全限定名称,就像你的包名一样;
apply from:'×××':叫做应用脚本插件,其实这不能算一个插件,它只是一个脚本。应用脚本插件,其实就是把这个脚本加载进来,和二进制插件不同的是它使用的是from关键字.后面紧跟的坫一个脚本文件,可以是本地的,也可以是网络存在的,如果是网络上的话要使用HTTP URL.虽然它不是一个真正的插件,但是不能忽视它的作用.它是脚本文件模块化的基础,我们可以把庞大的脚本文件.进行分块、分段整理.拆分成一个个共用、职责分明的文件,然后使用apply from来引用它们,比如我们可以把常用的函数放在一个Utils.gradle脚本里,供其他脚本文件引用。示例中我们把 App的版本名称和版本号单独放在一个脚本文件里,清晰、简单、方便、快捷.我们也可以使用自动化对该文件自动处理,生成版本。
Gradle插件的作用
1.可以添加任务到你的项目中,帮你完成一些亊情,比如测试、编译、打包。
2.可以添加依赖配置到你的项目中,我们可以通过它们配置我们项目在构建过程中需要的依赖.比 如我们编译的时候依赖的第三方库等。
3.可以向项目中现有的对象类型添加新的扩展属性、 方法等,让你可以使用它们帮助我们配置、优化构建,比如android{}这个配置块就是Android Gradle插件为Project对象添加的一个扩展。
4. 可以对项目进行一些约定,比如应用Java插 件之后,约定src/main/java目录下是我们的源代码存放位置,在编译的时候也是编译这个目录下的Java源代码文件。
1.App插件id:com.android.application.
2.Library插件id:com.android.library.
3.Test插件id:com.android.test.
一般一个项目只会设置一个App插件,而module一般是会设置为Library插
配置签名文件:release()
首先,在菜单栏中,点击 Build > Generate Signed APK,新建一个密钥库
Key store path:选择创建密钥库的位置 + 密钥库名字+jks。
Password:为您的密钥库创建并确认一个安全的密码。
Alias:为您的密钥输入一个标识名。
Password:为您的密钥创建并确认一个安全的密码。此密码应当与您为密钥库选择的密码不同
Validity (years):以年为单位设置密钥的有效时长。密钥的有效期应至少为 25 年,以便您可以在应用的整个生命期内使用相同的密钥签署应用更新。默认为25
Certificate:为证书输入一些关于您自己的信息。此信息不会显示在应用中,但会作为 APK 的一部分包含在您的证书中。
1.在 Project 窗口中,右键点击您的应用并点击 Open Module Settings。
2.在 Project Structure 窗口左面板中的 Modules 下,点击您想要签署的模块。
3.点击 Signing 标签,然后点击 ‘+’ 。
4.选择您的密钥库文件,为此签署配置输入一个名称(随意起一个),然后输入所需的信息。
三、性能优化:
内存优化
在 Android 系统中有个垃圾内存回收机制,在虚拟机层自动分配和释放内存,因此不需要在代码中分配和释放某一块内存,从应用层面上不容易出现内存泄漏和内存溢出等问题,但是需要内存管理。
Android 系统在内存管理上有一个 Generational Heap Memory 模型,内存回收的大部分压力不需要应用层关心, Generational Heap Memory 有自己一套管理机制,当内存达到一个阈值时,系统会根据不同的规则自动释放系统认为可以释放的内存,也正是因为 Android 程序把内存控制的权力交给了 Generational Heap
Memory,一旦出现内存泄漏和溢出方面的问题,排查错误将会成为一项异常艰难的工作。
除此之外,部分 Android 应用开发人员在开发过程中并没有特别关注内存的合理使用,也没有在内存方面做太多的优化,当应用程序同时运行越来越多的任务,加上越来越复杂的业务需求时,完全依赖 Android 的内存管理机制就会导致一系列性能问题逐渐呈现,对应用的稳定性和性能带来不可忽视的影响,因此,解决内存问题和合理优化内存是非常有必要的。
常见内存泄漏场景
handler耗时引发的内存泄漏
当activity当中存在handler接收耗时的消息时,比如我们一般在网络请求切换线程时,经常使用到handler,假设消息还没有发送完成,但是页面已经被关闭,也就说activity已经执行了ondestroy方法。当gc回收时,会出现改activity不能被回收的情况,到时内存泄漏。
解决办法:当activity销毁的时候,调用handler的removeCallbacksAndMessages方法,移除消息任务,然后将handler对象及线程置空。
内部类引发的内存泄漏(当然handler或子线程一般也作为内部类使用)
因为java当中,内部类默认持有外部类的引用,当外部类销毁后,一旦gc回收该实例,发现内部类持有他的引用而导致不能回收该实例,出现内存泄漏的情况。
解决方法:将内部类改为静态内部类,因为静态内部类生命周期和应用一样长,所以当退出程序的时候会一同回收该实例,并不会影响外部类的回收。
单例导致的内存泄漏
因为在使用单例的时候,经常会传入一个本类的上下文对象,而单例是静态的,生命周期和application一样长,当activity销毁的时候,该单例持有activity的引用导致其不能被回收,出现内存泄漏。
解决方法:在使用上下文的时候,传全局上下文。
资源未关闭
Cursor,stream,database,Butterknife,broadcastreciver,bindservice,eventBus
比如这些东西在使用完成后,需要进行close或者Unbind处理,以节省内存
Bitmap对象不在使用时调用recycle()释放内存
Timer计时器、动画,因为这些涉及耗时问题,如果activity销毁,而该任务并未执行完成,会导致内存泄漏,所以一般在activity中如果使用到这些耗时任务,需要在activity销毁时,做对应处理,比如调用timer的cancel方法,或者动画的cancel方法并将对象置空
一些监听器的内存泄漏,比如说我们给edittext设置输入文字监听时,当监听到文字发生变化,我们通过获取变化后的文字执行了耗时任务(比如获取到edittext里的内容上传服务器),当耗时任务未执行完成activity销毁了,会引发内存泄漏,所以在onDestory时,取消注册,比如说editText调用removeTextChangedListener方法
Rxjava的内存泄漏:因为rxjava采用的是观察者模式,当请求到数据后会根据订阅关系将数据发送个订阅者,而如果这时订阅者已经销毁,就会出现引用该对象导致其不能被回收的情况,出现内存泄漏,rxjava2发布的时候也发现了这个问题,所以在回调当中,新增加了onSubcribe回调,同时返回了一个disposable对象,可以通过判断disposable里的isDisposed来确定当前的订阅关系,如果订阅关系中的订阅者已经不存在且当前订阅关系存在,解除订阅关系,并终止数据的发送。
webView引发的内存泄漏:因为webview在使用的时候一般持有activity的引用,我们一般在activity的onDestroy方法中调用mWebView.destroy();来释放webview。如果在onDetachedFromWindow之前调用了destroy那就肯定会无法正常反注册了,也就会导致内存泄漏。所以在销毁webview前一定要先在onDetachedFromWindow中将webview从它的父view中移除,再调用destroy方法中调用webview的destroy,我开发的时候在5.1以上的手机上发现这种问题比较多,因为现在5.1以下适配的比较少了,基本没咋注意。
线程导致的内存泄漏:一般使用子线程都会创建一个内部类对象,而创建线程一般执行耗时任务,所以这个内部类默认持有外部类的引用,如果耗时任务在activity销毁的时候未执行完成,会因为持有外部类引用导致外部类不能被回收。
布局优化
减少层级。合理使用 RelativeLayout 和 LinerLayout,合理使用Merge。
提高显示速度。使用 ViewStub,它是一个看不见的、不占布局位置、占用资源非常小的视图对象。
布局复用。可以通过 标签来提高复用。
尽可能少用wrap_content。wrap_content 会增加布局 measure 时计算成本,在已知宽高为固定值时,不用wrap_content 。
删除控件中无用的属性
电量优化
在移动设备中,电池的重要性不言而喻,没有电什么都干不成。对于操作系统和设备开发商来说,耗电优化一致没有停止,去追求更长的待机时间,而对于一款应用来说,并不是可以忽略电量使用问题,特别是那些被归为“电池杀手”的应用,最终的结果是被卸载。因此,应用开发者在实现需求的同时,需要尽量减少电量的消耗。
在Android5.0 以前,在应用中测试电量消耗比较麻烦,也不准确,5.0之后专门引入了一个获取设备上电量消耗信息的API:Battery Historian。Battery
Historian 是一款由 Google 提供的 Android 系统电量分析工具,和Systrace 一样,是一款图形化数据分析工具,直观地展示出手机的电量消耗过程,通过输入电量分析文件,显示消耗情况,最后提供一些可供参考电量优化的方法。
除此之外,还有一些常用方案可提供:
[if !supportLists]· [endif]计算优化,避开浮点运算等。
[if !supportLists]· [endif]避免 WaleLock使用不当。
[if !supportLists]· [endif]使用 Job
Scheduler。
流量
应用提供检索用户的流量节省程序偏好和监控偏好变化的途径。
在 Android 7.0( API 级别 24)中,应用可以使用 ConnectivityManager API 来确定正在应用的是哪些流量消耗限制。getRestrictBackgroundStatus() 方法返回下列值之一:
RESTRICT_BACKGROUND_STATUS_DISABLED
流量节省程序已停用。
RESTRICT_BACKGROUND_STATUS_ENABLED
用户已为此应用启用流量节省程序。应用应努力限制前台流量消耗,并妥善处理后台流量消耗限制。
RESTRICT_BACKGROUND_STATUS_WHITELISTED
用户已启用流量节省程序,但应用在白名单中。应用应努力限制前台和后台流量消耗。
这被认为是在设备连接到按流量计费的网络时限制流量消耗的有效方法,即使流量节省程序遭到停用或应用在白名单中也是如此。以下示例代码使用 ConnectivityManager.isActiveNetworkMetered() 和 ConnectivityManager.getRestrictBackgroundStatus() 来确定应用应使用多少数据。
应用可以通过创建 BroadcastReceiver 侦听 ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED,以及使用 Context.registerReceiver() 动态注册接收器来监控流量节省程序偏好变化。当应用接收到这条广播时,应通过调用 ConnectivityManager.getRestrictBackgroundStatus() 来检查新的流量节省程序偏好是否会影响其权限。
启动
优化启动逻辑,提高应用的启动速度。启动主要完成三件事:UI 布局、绘制和数据准备。因此启动速度优化就是需要优化这三个过程:
UI 布局。应用一般都有闪屏页,优化闪屏页的 UI 布局,可以通过 Profile GPU Rendering 检测丢帧情况。
启动加载逻辑优化。可以采用分布加载、异步加载、延期加载策略来提高应用启动速度。
数据准备。数据初始化分析,加载数据可以考虑用线程初始化等策略
内存抖动
内存抖动是指在短时间内有大量的对象被创建或被回收的现象,导致频繁GC,而开发时由于不注意,频繁在循环里创建局部对象会导致大量对象在短时间内被创建和回收,如果频繁程度不够严重的话,不会造成内存抖动;如果内存抖动的特别频繁,会导致短时间内产生大量对象,需要大量内存,而且还频繁回收创建。总之,频繁GC会导致内存抖动。
解决:尽量避免在循环体或者频繁调用的函数内创建对象,应该把对象创建移到循环体外。总之就是尽量避免频繁GC。
检测内存:studio自带工具:直观的看到内存变化,需要到他对应的