标签:风格 logcat ++ group app 问题 rds eth 修改
http://blog.csdn.net/bd_zengxinxin/article/details/52525781
自己编写App的时候,有时会感觉界面卡顿,尤其是自定义View的时候,大多数是因为布局的层次过多,存在不必要的绘制, 或者onDraw等方法中过于耗时。那么究竟需要多快,才能给用户一个流畅的体验呢?那么就需要简单了解下Android的渲染机制:
Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,那么整个过程如果保证在16ms以内就能达到一个流畅的画面。 那么如果操作超过了16ms就会发生下面的情况:
如果系统发生的VSYNC信号,而此时无法进行渲染,还在做别的操作,那么就会导致丢帧的现象, (大家在察觉到APP卡顿的时候,可以看看logcat控制台,会有drop frames类似的警告)。这样的话,绘制就会在下一个16ms的时候才进行绘制, 即使只丢一帧,用户也会发现卡顿的。
那为什么是16ms,16ms意味着着1000/60hz,相当于60fps,那么只要解释为什么是60fps。
这是因为人眼与大脑之间的协作无法感知超过60fps的画面更新。12fps大概类似手动快速翻动书籍的帧率, 这明显是可以感知到不够顺滑的。24fps使得人眼感知的是连续线性的运动,这其实是归功于运动模糊的 效果。 24fps是电影胶圈通常使用的帧率,因为这个帧率已经足够支撑大部分电影画面需要表达的内容,同时能够最大的减少费用支出。 但是低于30fps是 无法顺畅表现绚丽的画面内容的,此时就需要用到60fps来达到想要的效果,当然超过60fps是没有必要的。
有了对Android渲染机制基本的认识以后,那么我们的卡顿的原因就在于没有办法在16ms内完成该完成的操作, 而主要因素是在于没有必要的layouts、invalidations、Overdraw。渲染的过程是由CPU与GPU协作完成, 下面一张图很好的展示出了CPU和GPU的工作,以及潜在的问题,检测的工具和解决方案。
我们需要知道: 1.通过Hierarchy Viewer去检测渲染效率,去除不必要的嵌套 2.通过Show GPU Overdraw去检测Overdraw,最终可以通过移除不必要的背景以及使用canvas.clipRect解决大多数问题。
Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次的UI结构里面, 如果不可见的UI也在做绘制的操作,这就会导致某些像素区域被绘制了多次。这就浪费大量的CPU以及GPU资源。
当设计上追求更华丽的视觉效果的时候,我们就容易陷入采用越来越多的层叠组件来实现这种视觉效果的怪圈。这很容易导致大量的性能问题, 为了获得最佳的性能,我们必须尽量减少Overdraw的情况发生。
我们可以通过手机设置里面的开发者选项,打开Show GPU Overdraw的选项,可以观察UI上的Overdraw情况。
蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况,我们的目标就是尽量减少红色Overdraw,看到更多的蓝色区域。
Overdraw有时候是因为你的UI布局存在大量重叠的部分,还有的时候是因为非必须的重叠背景。例如某个Activity有一个背景, 然后里面 的Layout又有自己的背景,同时子View又分别有自己的背景。仅仅是通过移除非必须的背景图片,这就能够减少大量的红色Overdraw区域, 增加 蓝色区域的占比。这一措施能够显著提升程序性能。
下面看一个简单的展示ListView的例子: activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:background="@android:color/white"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/narrow_space"
android:textSize="@dimen/large_text_size"
android:layout_marginBottom="@dimen/wide_space"
android:text="@string/header_text"/>
<ListView
android:id="@+id/id_listview_chats"
android:layout_width="match_parent"
android:background="@android:color/white"
android:layout_height="wrap_content"
android:divider="@android:color/transparent"
android:dividerHeight="@dimen/divider_height"/>
</LinearLayout>
item的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingBottom="@dimen/chat_padding_bottom">
<ImageView
android:id="@+id/id_chat_icon"
android:layout_width="@dimen/avatar_dimen"
android:layout_height="@dimen/avatar_dimen"
android:src="@drawable/joanna"
android:layout_margin="@dimen/avatar_layout_margin" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:orientation="vertical">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:textColor="#78A"
android:orientation="horizontal">
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:padding="@dimen/narrow_space"
android:text="@string/hello_world"
android:gravity="bottom"
android:id="@+id/id_chat_name" />
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:textStyle="italic"
android:text="@string/hello_world"
android:padding="@dimen/narrow_space"
android:id="@+id/id_chat_date" />
</RelativeLayout>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/narrow_space"
android:background="@android:color/white"
android:text="@string/hello_world"
android:id="@+id/id_chat_msg" />
</LinearLayout>
</LinearLayout>
Activity的代码
public class OverDrawActivity01 extends AppCompatActivity
{
private ListView mListView;
private LayoutInflater mInflater ;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_overdraw_01);
mInflater = LayoutInflater.from(this);
mListView = (ListView) findViewById(R.id.id_listview_chats);
mListView.setAdapter(new ArrayAdapter<Droid>(this, -1, Droid.generateDatas())
{
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null ;
if(convertView == null)
{
convertView = mInflater.inflate(R.layout.chat_item,parent,false);
holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.id_chat_icon);
holder.name = (TextView) convertView.findViewById(R.id.id_chat_name);
holder.date = (TextView) convertView.findViewById(R.id.id_chat_date);
holder.msg = (TextView) convertView.findViewById(R.id.id_chat_msg);
convertView.setTag(holder);
}else
{
holder = (ViewHolder) convertView.getTag();
}
Droid droid = getItem(position);
holder.icon.setBackgroundColor(0x44ff0000);
holder.icon.setImageResource(droid.imageId);
holder.date.setText(droid.date);