第八章
1.IntentFlag启动模式
- Intent.FLAG_ACTIVITY_NEW_TASK 启动每个activity都在一个新栈里
- Intent.FLAG_ACTIVITY_SINGLE_TOP 和singleTop类似
- Intent.FLAG_ACTIVITY_CLEAR_TOP 和singleTask类似
- Intent.FLAG_ACTIVITY_NO_HISTORY 当该activity启动其他activity,自己本身就会消失
2.清空任务栈
- clearTaskOnLaunch:每次返回该activity时,该activity上的所有activity被清除
- finishOnTaskLaunch:与前者相似,只是作用在自己身上
- alwaysRetainTaskState:不接受任何清除指令,一直保当前Task状态
第九章
安卓系统信息获取
获取系统的配置信息
- android.os.Build
- SystemProperty系统特性
android.os.Build
- Build.BOARD://主板
- Build.BRAND://Android系统定制商
- Build.SUPPORTED_ABIS[0]://cpu指令集
- Build.DEVICE://设备参数
- Build.DISPLAY://显示屏参数
- Build.FINGERPRINT://唯一编号
- Build.SERIAL://硬件序列号
- Build.ID://修订版本列表
- Build.MANUFACTURER://硬件制造商
- Build.MODEL://版本
- Build.HARDWARE://硬件名
- Build.PRODUCT://手机产品名
- Build.TAGS://描述Build的标签
- Build.TYPE://Builder类型
- Build.VERSION.CODENAME://当前开发代号
- Build.VERSION.INCREMENTAL://源码控制版本号
- Build.VERSION.RELEASE://版本字符串
- Build.VERSION.SDK_INT://版本号
- Build.HOST://host值
- Build.USER://user名
- Build.TIME ://编译时间
SystemProperty系统特性
- System.getProperty(“os.version”)OSb版本
- System.getProperty(“os.name”)OS明显
- System.getProperty(“os.arch”)OS架构
- System.getProperty(“user.home”):Home属性
- System.getProperty(“user.name”):Name属性
- System.getProperty(“user.dir”)Dir属性
- System.getProperty(“user.timezone”)时区
- System.getProperty(“path.separator”)路径分隔符
- System.getProperty(“line.separator”)行分隔符
- System.getProperty(“file.separator”)文件分隔符
- System.getProperty(“java.vendor.url”)Java vendar url属性
- System.getProperty(“java.class.path”)Java class路径
- System.getProperty(“java.class.version”) Java class版本
- System.getProperty(“java.vendor”) JAVA Vendar属性
- System.getProperty(“java.version”) java版本
- System.getProperty(“java_home”) java home属性
PakageManager
常用的一些系统封装信息
- ActivityInfo:封装mainifest文件中activity和receiver中的所有信息
- ServiceInfo:封装service中所有信息
- ApplicationInfo:封装application之间的信息
- PackageInfo:用于封装mainifest文件中相关节点信息
- ResolveInfo:封装包含intent信息的上一层信息,用来获取包含intent条件的信息,如带分享和播放功能的应用
PakageManager经常使用的方法
- getPackageManager:通过调用这个方法返回一个PakageManager对象
- getApplicationInfo:以ApplicationInfo形式返回指定包名的ApplicationInfo
- getApplicationIcon:返回指定包名的Icon;
- getInstallApplications:以ApplicationInfo的形式返回已经安装的应用
- getInstalledPackages:以PackageInfo形式返回安装的应用
- queryIntentActivities:返回指定intent的ResolveInfo对象,Activity集合
- queryIntentServices:返回指定intent的ResolveInfo对象,Service集合
- resolveActivity:返回指定intent的Activity
- resolveService:返回指定intent的Service
判断app类型,通过ApplicationInfo中的FLAG_SYSTEM来进行判断
app.flags & ApplicationInfo.FLAG_SYSTEM
- flags & ApplicationInfo.FLAG_SYSTEM !=0为系统应用
- flags & ApplicationInfo.FLAG_SYSTEM <= 0 第三方应用
- flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE !=0 为安装在SDCard上的应用
ActivityManager
ActivityManager也封装了一些bean对象
ActivityManager.MemoryInfo
其中有几个重要字段:availMem系统可用内存
totalMem总内存
threshold低内存的阈值
lowMemory是否处于低内存Dubug.MemoryInfo:上面的用于获取全局的内存使用信息,这里是用于统计进程下的内存信息。
- RunningAppProcessInfo:运行进程的信息
- RunningServiceInfo:运行服务的信息
Android的安全机制
- 代码安全机制,代码混淆proguard\
- 应用接入权限控制,AndroidMainifest文件申明权限,权限检查机制
- 应用前面机制,数字证书
- Linux内核安全机制,Uid,访问权限控制
- Android 模拟机沙箱机制。沙箱隔离
第十章
布局优化
1.Android UI渲染机制
安卓提供了检测渲染的工具,打开“开发者选项”选择GPU呈现模式分析,选中其中的在屏幕上显示为条形图,这时候屏幕上会出现一些条形图
每一条柱状线都包含三部分,蓝色代表测量绘制Display list 的时间,红色代表OpenGL渲染Display List的时间,黄色代表CPU等待cpu处理的时间,上面的一条绿色代表VSYNC时间16ms,需要尽量将所有条形图都控制在绿线一下。
2.避免overDraw
overDraw过渡绘制会浪费很多cpu,GPU的资源,依然在开发者选项中有一个“调试GPU过渡绘制”的功能,然后让其显示,然后尽量增大蓝色区域,减少红色区域
3.优化布局层级
少使用LineraLayout,多使用RelativeLayout,因为LineraLayout是布满全屏的,会增加布局数的高度,影响渲染效率
4.避免嵌套过多无用的布局
- 使用include标签重用Layout
- 使用ViewSub实现view的延迟加载
viewsub.setVisibility(View.VISIBLE)或者
viewsub.inflate()让viewsub显示
两者不同的是inflate() 可以返回引用的布局,从而通过fb找到相应的控件
5.Hierarchy Viewer
在sdk的tool文件夹下
内存优化
bitmap优化
- 使用适当分辨率和大小的图片
- 及时回收内存
- 使用图片缓存
代码优化
- 对常量使用static修饰符
- 使用静态方法,静态方法会比普通方法提高15%的访问速度
- 减少不必要的成员变量
- 减少不必要的对象,使用基础类型会比使用对象更加节约资源
- 尽量不要使用枚举,少用迭代器
- 对Cursor,Receiver,Sensor,File等对象,要注意其创建,回收和注册于解注册
- 避免使用ioc框架
- 使用RenderScript,OpenGL进行非常复杂的绘图操作
- 使用Surface来替代View进行大量复杂,频繁的绘图操作
- 尽量使用视图缓存,而不是每次都执行inflate()方法解析视图
Lint 工具
Android lint工具是Android studio中集成的一个代码提示工具,它主要负责对你的代码进行优化提示,包括xml和Java文件,很强大。
编写完代码及时进行lint测试,会让我们的代码变得非常规范而且避免代码冗余。让我们及时发现代码中隐藏的问题。
举个例子:我们在代码中建立全局变量,而这个变量实际并不需要全局便利,lint在检测之后会提示我们改成局部变量,这对内存优化是一个很强大的促进手段。
如何使用:
可以看到有Inspect Code,翻译就是检测代码
效果如下:
然后警告和错误都会在列表中提示出来
Memory Monitor工具
点击Android studio 工具底部的Android Monitor ,在logcat的边上有一个Monitors就是用来分析内存的工具了
使用TraceView优化app性能
- 首先打开Andorid Device Monitor工具,选择要调试的进程,点击工具栏中的“start method profiling” 按钮,点击后会弹出对话框,要你选择监听模式
- 一个是整体监听(Trace base profiling)耗时长不建议,一个是抽样监听(sample base profiling)。
- 执行一段时间后再点击“start method profiling” 按钮,停止监听
- 时间轴区域显示不同线程在不同的时间段里面的执行情况,在时间轴里每一行都代表一个独立的线程
- Profile区域显示了你选择的色块所打女的方法在该色块所处时间段里面的性能分析,主要显示如下
Incl CPU Time:某方法占用cpu的时间(父+子)
Excl CPU Time:某方法本身不包括子方法占用CPU的时间(父)
Incl Real Time:某方法真正执行的时间(父+子)
Excl Real Time:某方法本身不包括子方法真正执行的时间(父)
Calls+RecurCalls:调用次数+递归回调的次数
还有比较重要的:
cpu time/call:平均每次调用占用cpu时间。
real time/call :平均每次调用所执行的时间。
打开每个方法,会显示Paents和children(即父方法和子方法),以及分别所占用时间。
每个时间都有两列,一个是实际时间,另一个是百分比。分析的时候通常从某方法占用CPU时间和调用次数 开始分析,对占用时间长的方法进行重点分析,如果占用时间长,而且调用次数少就更应该怀疑了
使用MAT工具分析App内存状态
1.首先打开Andorid Device Monitor工具,选择要监听的线程,然后点击“Update Heap”按钮
2.然后在Heap标签中点击“Cause GC” 按钮就会显示当前的内存状态。有一个小不停点击技巧,当我们不停单击”Cause GC”时,如果“data object” 一栏中的“Total Size”有明显变化,代表可能有内存泄漏。
3.上面说的是手动检查“heap”状态,下面点击“Dump HPROF Flie”按钮,等几秒钟之后,系统会生成一个.hprof的文件,我们要分析这个文件(书中有个转化的过程)
4.用AndroidStudio打开刚刚保存的hprof文件,将文件直接拖进AndroidStudio中即可,选后选择Package Tree View,内存使用情况就是以包名分类
5. 在界面中找到你的应用程序的包名,打开即可看到内存的使用情况,自己写的类一目了然!如果有内存泄露,很容易看到。
第十二章
Android过渡动画
public class MainActivity extends Activity {
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transition);
}
// 设置不同动画效果
public void explode(View view) {
intent = new Intent(this, Transitions.class);
intent.putExtra("flag", 0);
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this)
.toBundle());
}
// 设置不同动画效果
public void slide(View view) {
intent = new Intent(this, Transitions.class);
intent.putExtra("flag", 1);
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this)
.toBundle());
}
// 设置不同动画效果
public void fade(View view) {
intent = new Intent(this, Transitions.class);
intent.putExtra("flag", 2);
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this)
.toBundle());
}
// 设置不同动画效果
public void share(View view) {
View fab = findViewById(R.id.fab_button);
intent = new Intent(this, Transitions.class);
intent.putExtra("flag", 3);
// 创建单个共享元素
// startActivity(intent,
// ActivityOptions.makeSceneTransitionAnimation(
// this, view, "share").toBundle());
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(
this,
// 创建多个共享元素
Pair.create(view, "share"),
Pair.create(fab, "fab")).toBundle());
}
}
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
int flag = getIntent().getExtras().getInt("flag");
// 设置不同的动画效果
switch (flag) {
case 0:
getWindow().setEnterTransition(new Explode());
break;
case 1:
getWindow().setEnterTransition(new Slide());
break;
case 2:
getWindow().setEnterTransition(new Fade());
getWindow().setExitTransition(new Fade());
break;
case 3:
break;
}
setContentView(R.layout.activity_transition_to);
折叠式的Notification
public void collapsedNotify(View view) {
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse("http://www.sina.com"));
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, intent, 0);
Notification.Builder builder = new Notification.Builder(this);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
builder.setLargeIcon(BitmapFactory.decodeResource(
getResources(), R.drawable.ic_launcher));
// 通过RemoteViews来创建自定义的Notification视图
RemoteViews contentView =
new RemoteViews(getPackageName(),
R.layout.notification);
contentView.setTextViewText(R.id.textView,
"show me when collapsed");
Notification notification = builder.build();
notification.contentView = contentView;
// 通过RemoteViews来创建自定义的Notification视图
RemoteViews expandedView =
new RemoteViews(getPackageName(),
R.layout.notification_expanded);
notification.bigContentView = expandedView;
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
nm.notify(NOTIFICATION_ID_COLLAPSE, notification);
}
悬挂式Notification
Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setPriority(Notification.PRIORITY_DEFAULT)
.setCategory(Notification.CATEGORY_MESSAGE)
.setContentTitle("Headsup Notification")
.setContentText("I am a Headsup notification.");
Intent push = new Intent();
push.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
push.setClass(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, push, PendingIntent.FLAG_CANCEL_CURRENT);
builder.setContentText("Heads-Up Notification on Android 5.0")
.setFullScreenIntent(pendingIntent, true);
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
nm.notify(NOTIFICATION_ID_HEADSUP, builder.build());
设置Notification 显示的等级
VISIBILITY_PUBLIC :表名任何情况下都能显示
VISIBILITY_PRIVATE:表示只有当没有锁屏是才显示
VISIBILITY_SECRET:表明在pin,password等安全锁和没有锁屏的情况下才能够显示
public void visibilityNotify(View view) {
RadioGroup radioGroup = (RadioGroup) findViewById(
visibility_radio_group);
Notification.Builder builder = new Notification.Builder(this)
.setContentTitle("Notification for Visibility Test");
switch (radioGroup.getCheckedRadioButtonId()) {
case R.id.radio_button_public:
builder.setVisibility(Notification.VISIBILITY_PUBLIC);
builder.setContentText("Public");
builder.setSmallIcon(R.drawable.ic_public);
break;
case R.id.radio_button_private:
builder.setVisibility(Notification.VISIBILITY_PRIVATE);
builder.setContentText("Private");
builder.setSmallIcon(R.drawable.ic_private);
break;
case R.id.radio_button_secret:
builder.setVisibility(Notification.VISIBILITY_SECRET);
builder.setContentText("Secret");
builder.setSmallIcon(R.drawable.ic_secret);
break;
}
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
nm.notify(NOTIFICATION_ID_VISIBILITY, builder.build());
}