多媒体流处理,安卓进阶之路

package com.totoo.touhou;
 
import android.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import com.totoo.touhou.GameView;
import com.totoo.TouhouMassLight.creature.Hero;
import com.totoo.TouhouMassLight.creature.SuperShow;
 
public class FullscreenActivity extends Activity implements OnGestureListener {
static Canvas GameCan = null;
 
static int TouchX = -1;
static int TouchY = -1;
public static int SW = 480;
public static int SH = 768;
public static final Double UITpersent = 0.25;
public static final Double UIpersent2 = 0.2;
public static final int StepLength = 34;
public static int EarthLine = (int) (SH * 0.62);
static int TouchArceH = (int) (SH * UITpersent);
static int TouchArceW = (int) (SW * UITpersent);
static int LeftDivede = (int) (SW * UITpersent);
static int RightDivede = (int) (SW * UITpersent * 3);
static int HighDivede = (int) (SH * UIpersent2);
static int MiddleDivede = (int) (SH * UIpersent2 * 2);
static int Center = (int) (SH * 0.8);
static int LowDivede = (int) (SH * UIpersent2 * 3);
DisplayMetrics dm;
GameView gv = null;
String AlretString;
static Paint drawSome = null;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initGameSource();
initUI();
}
 
private void initUI() {// 啟動系統
gv = new GameView(this);
setContentView(gv);
new Thread(new GameThread()).start();
}
 
boolean TouchArce() {// 分區域捕捉系統
if (TouchX < LeftDivede) {// 右边
if (TouchY < HighDivede) {// 強射擊
tz("強射擊");
SSA();
} else if (TouchY < MiddleDivede) {// 弱射擊
tz("弱射擊");
WSA();
} else if (TouchY < LowDivede) {// 飛行鍵
tz("飛行鍵");
PF();
} else {// 向左
tz("向左");
PL();
}
} else if (TouchX < RightDivede) {// 中间
if (TouchY > Center) {// 向下
tz("向下");
PD();
} else {// 向上
tz("向上");
PU();
}
} else {// 左边
 
if (TouchY < HighDivede) {// 符卡1
tz("符卡1");
SC1();
} else if (TouchY < MiddleDivede) {// 符卡2
tz("符卡2");
SC2();
} else if (TouchY < LowDivede) {// 攻擊
tz("攻擊");
A();
} else {// 向右
tz("向右");
PR();
}
}
 
return false;
}
 
private void A() {
 
}
 
private void SC2() {
 
}
 
private void SC1() {
 
}
 
private void PU() {
// molisha.setDescription(3);// 向上
// mapCache = molisha.moveUp(WorldMap, MapBodderX, MapBodderY);
// comfrimMap();
}
 
private void PD() {
// molisha.setDescription(1);// 向下
// mapCache = molisha.moveDown(WorldMap, MapBodderX, MapBodderY);
// comfrimMap();
}
 
private void PL() {
// molisha.setDescription(2);// 向左
//
// mapCache = molisha.moveLeft(WorldMap, MapBodderX, MapBodderY);
// comfrimMap();
}
 
private void PR() {
// molisha.setDescription(0);// 向右
// mapCache = molisha.moveRight(WorldMap, MapBodderX, MapBodderY);
// comfrimMap();
}
 
private void PF() {
 
}
 
private void WSA() {
 
}
 
private void SSA() {
 
}
 
private void initGameSource() {// 初始化遊戲資源
dm = new DisplayMetrics();
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindowManager().getDefaultDisplay().getMetrics(dm);
SH = dm.heightPixels;
SW = dm.widthPixels;
EarthLine = (int) (SH * 0.62);
Center = (int) (SH * 0.7);
TouchArceH = (int) (SH * UITpersent);
TouchArceW = (int) (SW * UITpersent);
LeftDivede = (int) (SW * UITpersent);
RightDivede = (int) (SW * UITpersent * 3);
HighDivede = (int) (SH * UIpersent2);
MiddleDivede = (int) (SH * UIpersent2 * 2);
Center = (int) (SH * 0.8);
LowDivede = (int) (SH * UIpersent2 * 3);
// MapBodderX = (int) SW / 4;
// MapBodderY = (int) SH / 4;
// WorldMap = new int[MapBodderX][MapBodderY];
// drawSome = new Paint();
// drawSome.setColor(Color.RED);
// tagetXY=new int[]{0,0};
 
}
 
// void comfrimMap() {// 更新地圖存根
// if (null != mapCache) {
// WorldMap = mapCache;
// }
// }
 
boolean PressKey(int x, int y) {// 按鍵響應
TouchArce();
return false;
}
 
private void tz(String str) {
AlretString = str;
drawSome.setColor(Color.RED);
}
 
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
 
void ShootTip(String str) {
Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
return false;
}
 
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
 
}
 
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// TODO Auto-generated method stub
return false;
}
 
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
 
}
 
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
 
@Override
public boolean onTouchEvent(MotionEvent event) {// 按下捕捉
int ia = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
TouchX = x;
TouchY = y;
PressKey(x, y);
return super.onTouchEvent(event);
}
 
class GameThread implements Runnable {
@Override
public void run() {// 遊戲線程
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
gv.postInvalidate();
}
}
}
 
}
图片
 介绍音视频的基础概念,其中包括音视频的基础数据格式、编码后的数据格式以及不同格式之间的相互转换等。
第2章,从零开始讲解如何搭建一个iOS项目和一个Android项目,并且添加C++支持,因为在音视频领域的开发中,有相当一部分的代码需要用C++来编写,这样就可以做到两个平台(Android和iOS平台)共用一套代码仓库,以提升开发效率。然后讲解交叉编译,因为在音视频开发过程中会用到很多第三方开源库,如果将这些库编译到我们的项目中,势必要进行交叉编译,因此本章会重点讲解这些内容。
第3章,探讨FFmpeg开源库。对于音视频开发来讲,FFmpeg开源库是众所周知也是普遍使用的。本章首先从编译开始,接着是命令行使用,再到源码结构,最后是API调用,以层层递进的方式对FFmpeg开源库展开介绍。
第4章,讲解如何利用各自平台的API进行声音与画面的渲染以及解码,对于画面的渲染,推荐使用OpenGL ES,两个平台可以使用同一个代码仓库。
第5章,实现一款视频播放器。有了前四章的基础,我们已经完全可以构建起一个视频播放器了。本书最大的特点就是经过几章基础知识的学习立即开始一个项目的实践,通过本章的视频播放器项目,我们将会熟悉播放器是如何工作的。
第6章,重点介绍音视频的采集与编码器。特别是硬件编解码器在各个平台上的使用,使得应用能够更高效(耗电更少、发热更少、界面更流畅)地运行在用户的手机上。
第7章,继续开发一个视频录制的新项目,该项目可以使我们更加熟悉音视频应用在各个平台下的实现。
第8章,讲解如何处理音频流。毕竟让别人听采集出来的干声是很不礼貌的,本章将利用各种特效来美化采集的声音。
第9章,讲解如何处理视频流,使视频中的颜值变得更高,毕竟爱美之心人皆有之。
第10章,在第7章的项目基础之上,增加第8章的音频特效和第9章的视频特效,从而构建一个实际生产过程中的多媒体应用。
第11章,继续以项目作为驱动,详细讲解如何基于之前学习的内容构建一个直播的应用,重点介绍推流以及拉流端,同时还涉及礼物特效、聊天以及第三方云服务的内容。
第12章,由于直播应用很难用一章的篇幅讲完,所以本章针对一些核心的处理进行讲解。
第13章,介绍常用的工具和排错方法,说明在日常开发中如何更有效率地解决问题,本章内容并不仅限于音视频的开发领域。
附录给出一些参考内容。
勘误和支持
由于作者水平有限,编写时间仓促,书中难免会出现一些错误或者不准确的地方,恳请读者批评指正。为此,我特意创建了一个在线支持与应急方案的二级站点本地图片,请重新上传http://music-video.cn ;

。你可以将书中的错误发布在Bug勘误表页面中,同时如果你遇到问题,也可以访问Q&A页面,我将尽量在线上为你提供最满意的解答。书中的全部源代码文件都将发布在这个网站上,我也会及时地进行相应的功能更新。如果你有更多的宝贵意见,也欢迎发送邮件至我的邮箱zhanxiaokai2008@126.com,我很期待听到你们的真挚反馈 

 
 根据二○○二年一月一日《计算机软件保护条例》规定:为了学习和研究软件内含的
 设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经
 软件著作权人许可,不向其支付报酬!
 鉴于此,也希望大家按此说明研究软件!谢谢
 
移动开发
 
Android应用性能优化最佳实践
 
罗彧成 著
 
 
 
 
图书在版编目(CIP)数据
Android应用性能优化最佳实践 / 罗彧成著. —北京:机械工业出版社,2017.1
(移动开发)
ISBN 978-7-111-55616-9
I. A… II. 罗… III. 移动终端-应用程序-程序设计 IV. TN929.53
中国版本图书馆CIP数据核字(2016)第315986号
 
 
 
 
 
 
 
 
 
Android应用性能优化最佳实践
出版发行:机械工业出版社(北京市西城区百万庄大街22号 邮政编码:100037)
责任编辑:李 艺责任校对:董纪丽
印  刷:中国电影出版社印刷厂版  次:2017年2月第1版第1次印刷
开  本:186mm×240mm 1/16印  张:13.75
书  号:ISBN 978-7-111-55616-9定  价:59.00元
凡购本书,如有缺页、倒页、脱页,由本社发行部调换
客服热线:(010)88379426 88361066投稿热线:(010)88379604
购书热线:(010)68326294 88379649 68995259读者信箱:hzit@hzbook.com
版权所有 ? 侵权必究
封底无防伪标均为盗版
本书法律顾问:北京大成律师事务所 韩光/邹晓东
 
 
 
 
 
Preface?前  言
为什么写这本书
一个好的应用,除了要有吸引人的功能和交互之外,在性能上也应该有高的要求,即使应用非常具有特色,或者功能和业务具有唯一性,在产品前期可能吸引了部分用户,但用户体验不好的话,也会给产品带来很差的口碑,如果有在体验上更好的竞品,用户也会很快转移。那么一个好的应用应该如何定义呢?主要有三方面:
业务/功能
符合逻辑的交互
优秀的性能
众所周知,Android系统作为以移动设备为主的一款操作系统,硬件配置有一定的限制,虽然配置现在越来越高级,但仍然无法和PC相比,在CPU和内存上的使用不合理或者耗费资源多时,就会碰到内存不足导致的稳定性问题、CPU消耗太多导致的卡顿问题等。例如,我们发布一款产品后会收到很多的反馈,这些反馈来自很多渠道,有用户反馈,有应用发布平台的反馈通道等。
面对这些问题时,大家想到的都是联系用户,然后看日志,特别是有关性能类问题的反馈,原因也非常难找,日志大多用处不大,为什么呢?因为性能问题大部分是非必现的问题,定位时很难复现,而又没有关键的日志,当然就无法找到原因了。这些问题非常影响用户的体验和功能的使用,所以解决这些问题是非常重要的。当前市场上讲解性能优化的书太少,即使有些书讲到,很多也是一笔带过,没有深入分析和寻找解决方案,所以有必要用一本书来从多个维度讲解在性能上我们面临了什么问题,如何解决这些问题,并在实际的项目中来优化我们的应用,以提高用户体验。
本书面向的读者
本书适合所有Android应用开发从业人员及在校学生,特别是有一定Android应用开发经验的开发人员,高级开发人员也可以通过本书了解更多的性能调优知识。
本书特色
本书为进阶类图书,对于一些基础技术和基础理论知识不会做过多的阐述,特别是入门类的知识点,大家可以从其他书籍获取相关的知识。书中以性能优化为核心,深入剖析性能优化具体涉及的技术背景与优化方案,同时提供典型案例,帮助读者更深入地掌握Android应用开发技术,理解Android的运行机制和原理,掌握Android性能优化的思想,让开发者快速成长,打造高质量的Android应用。
本书的主要内容
可以把用户能体验到的性能问题主要总结为4个类别:
流畅
稳定
省电
省流量
性能问题的主要原因是什么,原因有相同的,也有不同的,但归根结底,不外乎内存使用、代码效率、合适的策略逻辑、代码质量这一类问题。本书讲解内容的目标和方向如下图所示。
 
从上图可以看到,打造一个高质量的应用应该以4个方向为目标:快、稳、省、小。
快:使用时避免出现卡顿,响应速度快,减少用户的等待时间,满足用户预期。
稳:降低crash率和ANR率,不要在用户使用过程中崩溃和无响应。
省:节省流量和耗电,减小用户使用成本,避免使用时导致手机发烫。
小:安装包小可以降低用户的安装成本。
这4类问题需要从根源上解决,也就是要解决图中第二个框里的问题:卡顿、内存使用不合理、代码质量差、代码逻辑不优秀、安装包过大。这些问题也是在开发过程中碰到最多的问题,在实现业务需求的同时,也需要考虑到这些点,多花时间去思考,避免功能完成后再来做优化和修复Bug,这个时候带来的成本会增加。如果是维护之前的代码,就需要使用一系列工具来发现问题点。
性能优化不是更新一两个版本可以解决的,是持续性的需求,结合到实际中,在一个新产品/项目开始时,由于人力和上线时间的限制,可以把优先级放低,但有些点是在写代码时就要考虑的,这就体现出程序员的技术功底。
本书强调性能调优的核心思想和方向如下:
发现问题→分析问题原因及背景→寻找最优解决方案→解决问题。
本书一共7章,在简单介绍了Android Studio的使用指南后,分别从绘制(UI)、内存、存储、稳定性、耗电以及安装包6个方面进行优化,从系统上深入分析绘制和内存的原理,一步步深入了解导致性能问题的本质原因,同时讲述了多种性能优化工具的使用,通过分析典型案例,得到有效的优化方案,从而实现更高质量的应用。书中所讲述的内容均基于Android 6.0系统。
勘误和资源下载
由于写作时间实在有限,在书稿交付时仍有些许不安,为此先为此书可能存在的错误或者描述不清楚的地方致以真诚的歉意,如果你发现此书存在瑕疵或者有任何建议,请发邮件到5482586@qq.com,我会尽快回复,非常期待大家的反馈。
本书代码的下载地址:https://github.com/lyc7898/AndroidTech
致谢
由于时间的问题,本书写作时间非常长,非常感谢杨福川编辑对我的鼓励和宽容,并且分享了非常有用的碎片化写作方法,使我一直坚持把本书写完。同时感谢李艺编辑的校对和勘误,才完成了这本图文并茂、格式清晰的技术书籍。
感谢我的妻子李萍女士对我的理解和支持,在我几乎将所有的时间投入工作中时一直给予最大的宽容和鼓励,使我每天即使再忙再累时仍然可以回到温馨的家。同时感谢我的父母和岳父母,感谢他们对我无私的帮助,他们都是伟大的父母。
特别感谢我的爷爷罗志华老先生,在我的学习生涯中给予的无私帮助,在工作和生活上的谆谆教诲。还要感谢刘景瑜老师,在求学阶段的鼓励和教诲,告诉我有很多需要去做的事情。
最后感谢我现在工作的公司,在这里我得到了最快的成长,学习到非常多的东西,感谢公司领导及所有同事,在这里工作,能感受到大家每天都在成长。
 
 
 
 
 
Contents?目  录
前 言
第1章 Android Studio使用指南  1
1.1 Android Studio的优势  1
1.2 Android Studio使用入门  2
1.2.1 Android Studio安装  2
1.2.2 创建一个Android Studio工程  3
1.2.3 从Eclipse项目迁移到Android Studio  5
1.3 Android Studio实用技巧  7
1.3.1 代码管理  7
1.3.2 代码编辑技巧  8
1.3.3 调试技巧  10
1.4 本章小结  11
第2章 绘制优化  12
2.1 Android系统显示原理  13
2.1.1 绘制原理  13
2.1.2 刷新机制  16
2.1.3 卡顿的根本原因  20
2.2 性能分析工具  21
2.2.1 卡顿检测工具  22
2.2.2 TraceView  23
2.2.3 Systrace UI性能分析  26
2.3 布局优化  29
2.3.1 常用布局优化工具  30
2.3.2 布局优化方法  34
2.4 避免过度绘制  43
2.4.1 过度绘制检测工具  44
2.4.2 如何避免过度绘制  44
2.4.3 案例:无过度绘制View的实现  45
2.5 启动优化  49
2.5.1 应用启动流程  49
2.5.2 启动耗时监测  52
2.5.3 启动优化方案  56
2.6 合理的刷新机制  58
2.6.1 减少刷新次数  58
2.6.2 避免后台线程影响  59
2.6.3 缩小刷新区域  59
2.7 提升动画性能  60
2.7.1 帧动画  60
2.7.2 补间动画  60
2.7.3 属性动画  62
2.7.4 硬件加速  63
2.8 卡顿监控方案与实现  66
2.8.1 监控原理  67
2.8.2 代码实现  68
2.9 本章小结  79
第3章 内存优化  80
3.1 Android内存管理机制  81
3.1.1 Java对象生命周期  81
3.1.2 内存分配  82
3.1.3 内存回收机制  84
3.1.4 GC类型  86
3.2 优化内存的意义  87
3.3 内存分析工具  90
3.3.1 Memory Monitor  90
3.3.2 Heap Viewer  91
3.3.3 Allocation Tracker  94
3.4 避免内存泄漏  96
3.4.1 内存泄漏定义  97
3.4.2 使用MAT查找内存泄漏  97
3.4.3 常见内存泄漏场景  103
3.4.4 内存泄漏监控  106
3.5 优化内存空间  109
3.5.1 对象引用  109
3.5.2 减少不必要的内存开销  110
3.5.3 使用最优的数据类型  112
3.5.4 图片内存优化  117
3.6 图片管理模块设计与实现  120
3.6.1 实现异步加载功能  121
3.6.2 实现三重缓存  130
3.6.3 开源图片组件  140
3.7 本章小结  142
第4章 存储优化  144
4.1 存储方式  144
4.1.1 SharedPreferences  145
4.1.2 文件存储  145
4.1.3 SQLite(需要扩展)  146
4.1.4 ContentProvider  147
4.2 序列化  147
4.2.1 Serializable与Parcelable  148
4.2.2 Gson实现JSON的序列化和反序列化  148
4.2.3 Nano Proto Buffers  149
4.2.4 FlatBuffers  149
4.2.5 小结  150
4.3 SharedPreferences优化  150
4.4 数据库使用及优化  151
4.4.1 数据库实现  152
4.4.2 数据库优化  157
4.5 本章小结  161
第5章 稳定性优化  162
5.1 提高代码质量  162
5.1.1 代码审查  163
5.1.2 代码静态扫描工具  166
5.2 Crash监控  168
5.2.1 Java层Crash监控  168
5.2.2 Native层Crash监控  171
5.2.3 Crash上报机制  173
5.3 ANR剖析  173
5.3.1 ANR介绍  173
5.3.2 ANR分析  174
5.3.3 ANR监控  176
5.4 提高后台进程存活率  178
5.4.1 应用进程优先级  178
5.4.2 利用SyncAdapter提高进程优先级  180
5.5 本章小结  183
第6章 耗电优化  184
6.1 耗电检测工具  184
6.2 三大模块省电优化  187
6.2.1 显示  187
6.2.2 网络  188
6.2.3 CPU  189
6.3 应用常用优化方案  191
6.3.1 计算优化  191
6.3.2 避免WakeLock使用不当  192
6.3.3 使用Job Scheduler  193
6.4 Doze模式  197
6.4.1 Doze模式介绍  197
6.4.2 Doze模式应用策略  198
6.4.3 测试Doze模式应用工作状态  199
6.5 本章小结  199
第7章 安装包大小优化  200
7.1 应用装包的构成  200
7.2 减少安装包大小的常用方案  203
7.2.1 代码混淆  203
7.2.2 资源优化  204
7.2.3 其他优化  206
7.3 本章小结  207
结束语  208
 
第1章
Android Studio使用指南
假设我们要选择一个IDE来开发应用,目前主流的IDE有Eclipse、Android Studio、Idea,在2015年前,这三个IDE各有优缺点,但现在,Android Studio是首选,因为随着Google对Android Studio的大力完善和支持,优势已经越来越明显,但目前仍有不少开发人员在使用Eclipse。为什么要首选Android Studio,它有什么优势,具体要如何使用,本章将逐一揭示。
本书的例子都是使用Android Studio开发的。
1.1 Android Studio的优势
为什么本书要推荐使用Android Studio呢,Android Studio的核心是一个智能代码编辑器,可进行高级代码完成、重构和调试。这款功能强大的代码编辑器可以帮助你成为更高产的Android应用开发人员。虽然Android发布初期有很多bug,功能也不完善,但随着版本的更新,已经在各方面领先其他IDE,下面列出了Android Studio的几点优势。
稳定速度快:使用Eclipse的开发人员都会碰到突然假死、卡顿、内存占用高等一系列影响开发效率的老问题,Android Studio在这块性能上得到了明显的提升,并且Android Studio使用了单项目管理模式,在启动速度上明显比Eclipse快。
功能强大的UI编辑器:集合了Eclipse+ADT的优点,并且能更实时地展示界面布局效果。
完善的插件管理:Android Studio支持了多种插件,可直接在插件管理中下载所需的插件。
完善地支持多种代码管理工具:不需要任何操作,直接支持SVN、Git等主流的代码管理工具。
整合了Gradle构建工具:Gradle继承了Ant的灵活性和Maven的生命周期管理,不使用XML作为配置文件格式,采用了DSL格式,使得脚本更加灵活简洁。
智能:智能保存,智能补齐,在实际的编辑代码中熟练使用后,可极大提高代码编写效率。
内置终端:不需要自己打开一个终端来使用ADB等工具。
谷歌官方支持:是Google官方专门为Android应用开发打造的利器,也是目前Google官方唯一推荐,并且不再支持其他IDE。
Android Studio的更多优势会在开发工作的细节中体现出来,可以参考一些Android Studio的使用书籍和文档,以便了解它的强大之处。
1.2 Android Studio使用入门
1.2.1 Android Studio安装
这里我们以在Windows系统上安装Android Studio为例,具体的安装步骤如下:
1)安装JDK,且为JDK 1.6及以上版本。
2)下载Android Studio安装包:developer.android.com/sdk/installing/studio.html。
3)单击安装包开始安装,首先进入选择组件界面,如图1-1所示。
 
图1-1 选择安装组件
一般已经安装Eclipse或其他Android开发环境的,只需要安装默认的选项(Android Studio)即可。
4)单击Next,如果已经下载过SDK,并且在前面的组件没有选择安装SDK,会弹出一个设置本地SDK的界面,选择本地SDK目录,如图1-2所示。
 
图1-2 选择SDK目录
5)一直单击Next,直到安装完成,单击Finish,首次启动Android Studio会有一个配置的过程,需要等待一下。
因为本书主要是讲性能优化,所以这里只是简单地介绍下基本的安装。需要了解更多安装细节,可以参考Android开发官网的详细介绍文档:
如果首次启动出现错误导致启动失败,一般来说是因为联网下载一些配置文件失败,可以使用记事本打开studio的安装目录下/bin中的idea.properties文件,在最后一行添加disable.android.f?irst.run=true。
1.2.2 创建一个Android Studio工程
又到熟悉的HelloWold环节了,安装完成后,如果没有新建过项目,会出现一个欢迎对话框,选择新建项目。如果已经有项目,则可以通过File→New→New Project来新建一个项目,填写相关名称,包括应用名(Application name)、公司名(Company Domain)、包名(Package name)、项目本地路径(Project Location),如图1-3所示。
下一步选择开发平台,选择Android Phone,SDK使用Android 6.0,如图1-4所示。
 
图1-3 新建项目
 
图1-4 选择应用运行平台
后面两步都使用默认设置,最后单击Finish进入我们的项目。进入后可以看到,左侧的项目文件区域显示的文件树结果和Eclipse并不相同,而且本地目录的文件层级也不相同。因为Android Studio使用了Gradle项目构建工具,而Eclipse使用Ant构建项目。
如果不习惯这种结构,可以通过Gradle设置与Eclipse相同的目录结构。
进入后发现不能编译,这是因为还未设置编译工具。需要先配置Gradle,由于Android Studio没有自带Gradle插件,所以会自动下载Gradle,但需要设置代理,并且设置代理下载仍然会比较慢,这里介绍离线配置Gradle的方法,步骤如下:
1)从官网下载Gradle:http://gradle.org/gradle-download/,这里我们选择1.3版本。
2)进入C:Users.gradlewrapperdistsgradle-2.2-all1vevkra640w3rb9hkuw50q5we,最后这个文件夹是随机生成的,所以直接进入,把下载好的gradle-1.3-all.zip放到这个文件夹内即可。
3)重新启动Android Studio,就可以正常编译了。
Gradle是一种依赖管理工具,基于Groovy语言,抛弃了基于XML的各种繁琐配置,取而代之的是一种基于Groovy的内部领域特定语言(DSL),掌握Gradle脚本的编译和打包是应用开发非常必要的。
1.2.3 从Eclipse项目迁移到Android Studio
Eclipse项目和Android Studio相比,在项目结构、构建系统以及IDE的风格上都有了较大的变化。从Eclipse ADT项目迁移到Android Studio有两种方法,一是直接把Eclipse项目导入Android Studio中,二是从Eclipse导出Gradle项目,然后在Android Studio中可以直接打开导出的项目。
Android Studio是基于intelliJ IDEA开发的一款IDE,与Eclipse有很多不同的地方,特别是工程的目录结构,区别非常大。在Eclipse Android中的Project在Android Studio中是一个Module,并且Android Studio是单项目管理,每个窗口只能打开一个Project,这也是Android Studio打开更快的原因之一。在Android Studio中,有多种视图结构类型:Packages、Project Files、Scratches、Problems、Production、Tests,可以根据自己需求来使用不同的视图类型。
Eclipse和Android Studio中项目结构的对应关系如表1-1所示。
表1-1 Eclipse与Android Studio项目结构对应的关系
Eclipse ADTAndroid Studio
WorkspaceProject
ProjectModule
Project-specif?ic JREModule JDK
Classpath variablePath variable
Project dependencyModule dependency
Library ModuleLibrary
AndroidManifest.xmlapp/src/main/AndroidManifest.xml
assets/app/src/main/assets
res/app/src/main/res/
src/app/src/main/java/
tests/src/app/src/androidTest/java/
 
从表1-1可以看出,结构发生了非常大的变化,如果直接按对应关系来迁移项目中的文件对应到Android Studio的目录结果,工作量不小并且容易出错。因此,为了简化迁移过程,Android的Studio提供了一个快速导入Eclipse项目的方法,可以将Eclipse和Ant构建脚本快速转换到Android Studio上。导入步骤如下:
1)在Android Studio菜单栏选择File→New→Import Project。如果是首次使用,在欢迎页可直接选择Import Project。
2)选择需要导入的Eclipse工程目录,AndroidManifest.xml必须是在根目录下。
3)在导入过程中会提示是否重新配置Eclipse中的所有第三方库和项目依赖关系,如果勾选,就会重新生成新的第三方管理库和依赖关系,依赖关系和第三方库也可以在build.gradle文件上修改。如图1-5所示,有三个选项可以选择,前两项目是jar包的引用规则,建议勾选,这样就不用管理这些jar包了。第三项是指是否需要把Module名创建为camelCase风格(首字母小写的命名规则)。
4)单击Finish按钮,完成后会生成一个import-summary.txt文件,它是导入过程中产生的日志,这个文件比较重要,如果项目比较大,导入过程不一定顺利,可以通过这个文件来发现导入过程中出现的问题。
这样就把Eclipse Android项目导入Android Studio了,注意前面讲过,导入完成后生成了一个描述导入过程的日志文件:import-summary.txt,文件中包含以下几个内容:
Ignored Files:描述在导入过程中忽略了哪些文件,这些文件是没有拷贝过来的,如果有需要,就要手动添加过来,一般会忽略Eclipse ADT相关的配置文件和一些自定义的文件/文件夹。
Replaced Jars with Dependencies和Replaced Libraries with Dependencies:列出那些替换的JAR包,在Android Studio中,如果在仓库中有这个库或者SDK,就会被替换。
Moved Files:文件移动路径列表。
Next Steps:接下来需要做些什么,如果没有问题,一般告诉你可以编译了。
Bugs:如果不能编译,就会列出当前项目存在的问题。
上面介绍的这种导入项目的方式也是Android官网推荐的,理由是简单高效,有问题也容易发现,最主要是不会改变原来的文件组织架构。
更多有关从Eclipse ADT迁移到Android Studio的内容可以从Android开发官网上查询:http://developer.android.com/intl/zh-cn/sdk/installing/migrate.html#prerequisites
这样导入的项目还是会保留Eclipse的构建方式,比如在Eclipse上使用Ant构建,迁移后还是会使用Ant构建,如果先从Eclipse导出成Gradle项目就使用Gradle构建,当然也可以手动改构建方式。
1.3 Android Studio实用技巧
1.3.1 代码管理
Android Studio支持Git、SVN等主流的源码管理工具,让开发者可以不用离开Android Studio就可以提交和管理代码。我们熟悉的开源社区Github上的项目就是使用Git来管理的,下面是使用Android Studio把本地代码托管到Github上的流程。
1)在本地安装Git,可以从官网下载安装包:https://git-scm.com/downloads
2)配置File→Setting→Version Control,分别配置Git目录(安装路径下Bin目录的GIt.exe文件)和GitHub账号(没有GitHub账号则需要先申请,开源项目都是免费使用的),如图1-6所示。配置完后可以单击测试按钮,配置没有问题就弹出测试成功提示框。
 
图1-6 配置代码管理工具Git
3)初始化Git项目:选择菜单栏→CVS→Enable Control Integration,在弹出的配置对话框中选择Git,完成后工具栏会新增如图1-7所示的快捷工具。
 
图1-7 VCS快捷工具
4)如果需要过滤掉不需要上传的文件或者目录,可以在File→Setting→VersionControl→Ignored Files中选择不需要同步的文件或文件夹,如图1-8所示,也可以通过修改项目目录下的.gitigonre文件来实现。建议使用前者,因为根据笔者实际的使用经验,修改.gitigonre文件有时会失效,而且管理也没有前者方便。
 
图1-8 过滤不需要同步的文件/文件夹
可以通过选择VCS→Git→Compare With Branch,指定Branch(分支)和本地代码做比较。提交前可以双击需要提交的文件来对比改动代码行。
5)同步代码到Github:选择VCS→Import into Version Control→Share Project on GitHub,如图1-9所示。
6)在图1-9中,单击Share按钮,弹出提交文件列表(可以看到前面过滤的文件不在列表内),同步完成后就可以在Github上看到我们同步的项目了。
7)后面需要提交代码,首先提交,然后选择VCS→Git→Push,即可同步代码到GitHub。
1.3.2 代码编辑技巧
如果您已经习惯了Eclipse的快捷键,可以通过File→Setting→Keymap来设置成Eclipse的快捷键,如图1-10所示。
 
图1-10 设置成Eclipse快捷键
Android Studio是一款非常智能的编辑器,在编写代码过程中,如果能熟练掌握一些小技巧,就可以提高写代码的速度,这里介绍一些常用的技巧。
内容补全:在写完一个方法名,或者一个判断语句(if、while、for)后,自动生成{}块并使光标停在{}中间,在写完方法名或需要用{}前,使用Ctrl + Shift + Enter组合键。
列选择:可以选择列块,按住Alt键选择代码块。
代码补全:使用<Enter>键从光标处插入补全的代码,对原来的代码不做任何操作。而使用<Tab>键时从光标处插入补全的代码,但是会删除后面的代码,直到遇到点号、圆括号、分号或空格为止。
查看方法调用路径:按Ctrl + Alt + H组合键。
布局文件编辑器:Android Studio提供了更加高级的布局文件编辑器,除了像Eclipse一样可以实时查看布局文件外,Android Studio的布局查看包括了很多种分辨率和手机模拟器,并且还可以自定义设备分辨率。
预览某个方法或者类的实现:在不离开当前文件或者当前类的情况下,快速预览某个方法或者类的实现,减少频繁切换文件/类,使用Ctrl + Shift + I组合键。
快速使用命令:对于没有设置快捷键或者忘记快捷键的菜单功能或者命令,可以通过输入其名字或者模糊匹配以快速调用。使用Ctrl + Shift + A组合键,比如输入‘commi’,会列出所有和commit相关的操作。
自动导包:进入settings→Editor→General→Auto Import设置页,选中Show import popup、Show import pupup、Optimize imports on the f?ly和Add unambiguous imports on the f?ly,就可以自动导包,并且会自动去掉无用的包。
Android Studio快捷键的更多使用技巧,可以通过Help-->Tip of the day,每日学习一个,在开发过程中逐渐掌握。
1.3.3 调试技巧
Android Studio另一个强大的地方,就是调试更加方便和高效,以下是调试过程中的常用场景。
调试程序:Android Studio可以随时进入调试模式,即使未以调试方式启动应用。我们可以通过菜单→Build→Attach to Android Process,也可以直接通过工具栏快捷工具Attach to Android Process进入调试模式。
条件断点:调试中非常有用的方式,可以自己直接赋值,减小调试时间,通过右键断点(也可以在Debug视图上的BreakPoint列表上)对一个断点加入条件,即填写Condition中的条件。只有当满足条件时,才会进入断点中。
分析传入/传出数据流:Menu→Analyze→Analyze Data Flow to Here这个操作将会根据当前选中的变量、参数或者字段,分析出其传递到此处的路径。如果你想知道某个参数是怎么传递到一段陌生的代码时,这是一个非常有用的操作。传出数据流(Analyze data f?low from here)则会分析当前选中的变量往下传递的路径,直到结束。
日志断点(Logging Breakpoints):一种不是暂停的断点,只是打印日志,当想打印一些日志信息,但是不想添加log代码后重新部署时,则可以在断点上单击鼠标右键,取消选中Suspend,然后勾选Log evaluated Expression,并在输入框中输入要打印的日志信息。
修改变量值:在调试过程中,修改变量值可以快速调试各个Case,提高异常处理的调试效率。在调试时进入断点后,如图1-11所示,如果需要修改level变量的值,右键单击level,在弹出的菜单中选择Set Value或者使用快捷键F2,就可以修改成需要的值,并且该值只对当次有效。
 
图1-11 调试时修改变量值
1.4 本章小结
Android Studio的安装并不复杂,首次使用可能会不适应并觉得效率甚至低于以前使用的其他IDE,但相信使用一段时间后,一定能体验到它的灵活和强大之处,同时Android Studio的技巧非常多,大家可以多从网上找到各种技巧。
古人云,“工欲善其事,必先利其器”,Android应用开发者的“器”则是指Android Studio,熟练运用开发工具,能极大程度提高开发效率。在掌握Android Studio这个开发神器后,再通过接下来的章节的学习,从UI性能、内存、稳定性等多个维度的优化,使Android应用程序更加高效、流畅地运行,从而打造出一款高质量的Android应用。
原文地址:https://www.cnblogs.com/totoo/p/android.html