为何红米note3手机相册里滑动不顺手?求大神回复!

作者&投稿:将黛 (若有异议请与网页底部的电邮联系)
Android 界面滑动卡顿分析与解决方案(入门)
导致Android界面滑动卡顿主要有两个原因:
1.UI线程(main)有耗时操作
2.视图渲染时间过长,导致卡顿
目前只讲第1点,第二点相对比较复杂待以后慢慢研究。
众所周知,界面的流畅度主要依赖FPS这个值,这个值是通过(1s/渲染1帧所花费的时间)计算所得,FPS值越大视频越流畅,所以就需要渲染1帧的时间能尽量缩短。正常流畅度的FPS值在60左右,即渲染一帧的时间不应大于17ms。
先看一个例子:
见Video1,该应用通过一组URL加载网络上的图片并显示在ListView中。从视频中可以看到滑动ListView存在一定的卡顿的现象。
分析工具1:Android systrace
打开Android开发工具中的DDMS,选中应用所在的进程并点击倒数第二个图标出现如下界面:

填上相关信息后点击OK,此时Android systrace已经开始工作,你只需要正常操作手机复现卡顿现象即可。
Android systrace 停止以后就会根据你上图中的设置生成trace.xml文件(注:此文件在火狐浏览器中无法正常浏览,需使用chrome)。
打开trace.xml后观察surfaceflinger存在很多断断续续,分布不够均匀。

放大看

在某间隔出的时间是48ms,这远远的大于17ms,正是这个原因直接导致了界面的卡顿感。
接着再看:

此处也存在不规则分布,可以看到主要的耗时操作在:

obtainView和decodeBitmap上面,看到这两个方法似乎是找到了罪魁祸首。那我们就看看这两个方法是在哪里被调用的。
通过查找源代码知道obtainView这个方法被定义在AbsListView.java这个类中,主要作用就是获得一个和数据绑定过的视图,在这个方法中调用到了
mAdapter.getView(position, transientView, this);

这个方法大家再熟悉不过了,因为在自定义Adapter的时候都要去重写getView方法,那我们可以推测卡顿的原因很有可能出自getView。毕竟这个方法里有我们自己写的很大一坨代码。
接着再看getView中最主要的方法
mCacheWrapper.getBitmapFromCache(url, mHandler, position,2);

具体实现是:
public void getBitmapFromCache(final String urlString, Handler handler,
final int position, final int scale) {
final String key = hashKeyForString(urlString);
final Message msg = handler.obtainMessage();
Bitmap bitmapCache = mMemoryCache.get(key);
if (bitmapCache != null) {
msg.arg1 = position;
msg.obj = bitmapCache;
msg.sendToTarget();
Log.d(TAG, "memory include the key");
return;
}
//InputStream is = getInputStreamFromCache(key);
//if (is != null) {
// Bitmap bitmap = getBitmap(is, key, scale);
// if (bitmap != null) {
// mMemoryCache.put(key, bitmap);
// msg.arg1 = position;
// msg.obj = bitmap;
// msg.sendToTarget();
// Log.d(TAG, "disk include the key");
// }
// return;
//}
mExecutor.execute(new Runnable() {
@Override
public void run() {
if (mCurrentTask.contains(key)) {
Log.d(TAG, "the key of task is still execute");
return;
}
mCurrentTask.add(key);
boolean isOK = write2Cache(urlString);
if (isOK) {
InputStream is = getInputStreamFromCache(key);
Log.d(TAG, "the file is write to disk cache");
is = getInputStreamFromCache(key);
if (is != null) {
Bitmap bitmap = getBitmap(is, key, scale);
if (bitmap != null) {
mMemoryCache.put(key, bitmap);
msg.arg1 = position;
msg.obj = bitmap;
msg.sendToTarget();
}
}
}
mCurrentTask.remove(key);
}
});
}

看上面这段代码发现加注释代码存在一定的嫌疑,因为它在主线程中做了IO操作和bitmap的decode操作。
我们稍微修改一下上面这段代码:
public void getBitmapFromCache(final String urlString, Handler handler,
final int position, final int scale) {
final String key = hashKeyForString(urlString);
final Message msg = handler.obtainMessage();
Bitmap bitmapCache = mMemoryCache.get(key);
if (bitmapCache != null) {
msg.arg1 = position;
msg.obj = bitmapCache;
msg.sendToTarget();
Log.d(TAG, "memory include the key");
return;
}
mExecutor.execute(new Runnable() {
@Override
public void run() {
if (mCurrentTask.contains(key)) {
Log.d(TAG, "the key of task is still execute");
return;
}
//mCurrentTask.add(key);
//InputStream is = getInputStreamFromCache(key);
//if (is != null) {
// Bitmap bitmap = getBitmap(is, key, scale);
// if (bitmap != null) {
// mMemoryCache.put(key, bitmap);
// msg.arg1 = position;
// msg.obj = bitmap;
// msg.sendToTarget();
// Log.d(TAG, "disk include the key");
// }
// mCurrentTask.remove(key);
// return;
//}
boolean isOK = write2Cache(urlString);
if (isOK) {
Log.d(TAG, "the file is write to disk cache");
is = getInputStreamFromCache(key);
if (is != null) {
Bitmap bitmap = getBitmap(is, key, scale);
if (bitmap != null) {
mMemoryCache.put(key, bitmap);
msg.arg1 = position;
msg.obj = bitmap;
msg.sendToTarget();
}
}
}
mCurrentTask.remove(key);
}
});
}

将置灰出的代码移动到主线程以外,在看看滑动流畅读video2.mp4
可以看到卡顿现象已经没有了,那罪魁祸首就是在主线程中有IO操作和bitmap的decode操作引起的。
上述分析过程跳跃性比较大,这里再推荐一种简单直观的方法:
分析工具2:Method Profiling.
还是打开DDMS,选中你的应用,点击第六个图标,

这边默认OK

点击OK开始抓取,接着滑动手机复现卡顿现象。最后再次点击第六个钮即可。

这里只看上图中的main就可以了。

点击main方法后会展开它的父方法(即调用main的方法)和它的子方法(即在main中调用的方法)。这里一般点击后面百分数较大的那个子方法(百分数表示方法执行所占用的cpu时间)。接着要做的就是一步一步往下点,直到找到我们要找的耗时操作。
最后我们还是来到了这边

上图已经定位了decodeStream方法,再往下走也是进到framework没意义了。剩下的就是怎么将decodeStream放到主线程以外的线程的事情了。
总结:
主线程中不要放置耗时的操作,耗时操作可以扔Thread再通过Handler与主线程同步或使用AsyncTask来完成耗时操作。

清空缓存试试

为什么我的手机相册是这样啊~

图片加载速度慢,等待加载图片完成就好了,如果不行就重启一下手机

登录你自己的qq空间

为何红米note3手机相册里滑动不顺手?求大神回复!
答:见Video1,该应用通过一组URL加载网络上的图片并显示在ListView中。从视频中可以看到滑动ListView存在一定的卡顿的现象。分析工具1:Android systrace 打开Android开发工具中的DDMS,选中应用所在的进程并点击倒数第二个图标出现如下界面:填上相关信息后点击OK,此时Android systrace已经开始工作,你只需要正常操...

红米note3上滑功能在哪里设置
答:在“上划功能”选项中找到“上滑”选项,进行勾选 根据自己的需要选择相应的操作 例如,选择“打开通知栏”、“打开最近使用的应用”、“返回桌面”等等 完成设置后,进行保存即可 4. 其他滑动功能设置 除了上滑功能外,红米手机还支持其他滑动功能的设置。具体步骤如下:在“辅助功能”中找到“手势操作...

红米note3触屏怎么设置?
答:1、首先在我们的手机桌面找到设置栏目点击设置;2、进入到设置界面,我们滑动手指拉到最底部可以看到一个其他高级设置模块,点击其他高级设置;3、进入到其他高级设置界面,找到开发者选项;4、点击进入到开发者选项页面,我们可以看到有个输入模块,在输入模块下面有个显示触摸操作,目前是处于关闭的状态;5...

红米note3私密相册首页下拉,指的是哪首页
答:这是说你进入私密相册,你把私密相册打开,然后这个不就是那个住院吗他就是首页

红米note3系统最新版本的云相册和私密相册在哪里?
答:打开手机里的图库,长按住某张图片,出现更多选项,设为私密。滑动到云的界面下拉,会出现私密相册,设置图形密码。红米Note 3 红米Note 3是小米公司在2015年11月24日发布的红米note系列第三代手机,是小米第一部指纹解锁手机,采用金属机身加指纹识别,红米Note3双网通版本采用2Ghz的MT6795八核处理器,全...

小米红米note3怎么截屏
答:红米note3截屏有多种方法,下面就是红米note3的四种截屏方法:1.可以使用系统的截屏快捷键进行截屏:同时按住“电源键”键和“音量-”,这样就可以实现截屏操作了 2.使用系统通知栏截屏开关实现快速截屏:3.使用手势操作来实现快捷截屏:(1)在系统操作界面中打开“设置”开关,找到“更多设置”选项并...

红米note3手机如何设置时间水印?
答:红米Note 3手机的相机想要添加时间水印,其实操作起来非常简单。首先,你需要打开手机内置的相机应用(步骤01)。然后,找到并点击【模式选择】选项(步骤02)。接着,滑动到右上角,你会看到一个设置图标,点击进入(步骤03)。在这个设置菜单里,找到并点击【时间水印】选项,确保灰色图标变为选中状态(...

红米note3刚截图啊,怎么相册里没有啊?
答:你是三根手指下滑截图吗。截图完右上角会立马出现一个缩略图。你点击就可以看到自己的截图,同时可以编辑图片。还有就是点击相册,首先显示的是拍的照片,所以你看不到截图。你可以点上方的相册,切换到相册视角,相册里会有一个 最近 ,还有个 截屏,在这两个选项里都能看到你的截图,图片是按时间...

红米note3怎样保存照片直接保存到相册里
答:嗨!1.在待机页面下,点击【应用程序】。2.点击【照相机】。3.进入拍照模式后,点击【小齿轮】图标。4.再次点击【小齿轮】图标。5.点击【小齿轮】图标,用手指向上滑动屏幕菜单,选择【存储器】。6.根据您的需要选择照片的保存位置即可。

红米note3怎样设置桌面整圈滑动
答:这个是开发者模式里面的设置。进入手机的其他高级设置,选择开发者模式进入,然后开启屏幕触摸显示即可。