怎么提高android contentresolver的查询效率优化流程 提高效率

相关文章推荐
通常我们写程序,都是在项目计划的压力下完成的,此时完成的代码可以完成具体业务逻辑,但是性能不一定是最优化的。一般来说,优秀的程序员在写完代码之后都会不断的对代码进行重构。重构的好处有很多,其中一点,就...
通常我们写程序,都是在项目计划的压力下完成的,此时完成的代码可以完成具体业务逻辑,但是性能不一定是最优化的。一般来说,优秀的程序员在写完代码之后都会不断的对代码进行重构。重构的好处有很多,其中一点,就...
出处:http://blog.csdn.net/arui319/article/details/8537588
通常我们写程序,都是在项目计划的压力下完成的,此时完成的代码可以完...
通常我们写程序,都是在项目计划的压力下完成的,此时完成的代码可以完成具体业务逻辑,但是性能不一定是最优化的。一般来说,优秀的程序员在写完代码之后都会不断的对代码进行重构。重构的好处有很多,其中一点,就...
通常我们写程序,都是在项目计划的压力下完成的,此时完成的代码可以完成具体业务逻辑,但是性能不一定是最优化的。一般来说,优秀的程序员在写完代码之后都会不断的对代码进行重构。重构的好处有很多,其中一点,就...
通常我们写程序,都是在项目计划的压力下完成的,此时完成的代码可以完成具体业务逻辑,但是性能不一定是最优化的。一般来说,优秀的程序员在写完代码之后都会不断的对代码进行重构。重构的好处有很多,其中一点,就...
原文链接:/article/android-resource-android-mem.html
这篇文章主要介绍在实际Android应用程序的开发...
无论大型或小型应用,灵活的缓存可以说不仅大大减轻了服务器的压力,而且因为更快速的用户体验而方便了用户。
Android的apk可以说是作为小型应用,其中99%的应用并不是需要实时更新的,而且诟病...
他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)本文为Android性能优化的第三篇——Java(Android)代码优化。主要介绍Java代码中性能优化方式及网络优化,包括缓存、异步、延迟、数据存储、算法、JNI、逻辑等优化方式。
点击广告支持我
我维护的 Android 经验分享的公众号
最新 Android 高薪内推
点击下面广告支持我
站内推荐文章
阿里、滴滴内推,年 40w 以上
那些著名开源库的原理分析
(156,882)(124,527)(109,090)(102,447)(101,323)(94,875)(80,008)(77,370)(76,036)(71,084)
阿里、滴滴内推,年 40w 以上
C 轮融资近 30 亿元理财推荐20:51 提问
Android:ContentResolver的query中用count(*)
Uri uri=Uri.parse("content://sms/conversations");
Cursor c=resolver.query(uri, new String[]{"COUNT(*) "}, null, null, null);
查不出来这条语句该咋写,能这样统计不。
按赞数排序
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐解析Android开发优化之:从代码角度进行优化的技巧
字体:[ ] 类型:转载 时间:
下面我们就从几个方面来了解Android开发过程中的代码优化,需要的朋友参考下
通常我们写程序,都是在项目计划的压力下完成的,此时完成的代码可以完成具体业务逻辑,但是性能不一定是最优化的。一般来说,优秀的程序员在写完代码之后都会不断的对代码进行重构。重构的好处有很多,其中一点,就是对代码进行优化,提高软件的性能。下面我们就从几个方面来了解Android开发过程中的代码优化。
1)静态变量引起内存泄露
在代码优化的过程中,我们需要对代码中的静态变量特别留意。静态变量是类相关的变量,它的生命周期是从这个类被声明,到这个类彻底被垃圾回收器回收才会被销毁。所以,一般情况下,静态变量从所在的类被使用开始就要一直占用着内存空间,直到程序退出。如果不注意,静态变量引用了占用大量内存的资源,造成垃圾回收器无法对内存进行回收,就可能造成内存的浪费。
先来看一段代码,这段代码定义了一个Activity。 代码如下:private static Resources mR&
protected void onCreate(Bundle state) {
super.onCreate(state);
if (mResources == null) {
&&& mResources = this.getResources();
}这段代码中有一个静态的Resources对象。代码片段mResources = this.getResources()对Resources对象进行了初始化。这时Resources对象拥有了当前Activity对象的引用,Activity又引用了整个页面中所有的对象。
如果当前的Activity被重新创建(比如横竖屏切换,默认情况下整个Activity会被重新创建),由于Resources引用了第一次创建的Activity,就会导致第一次创建的Activity不能被垃圾回收器回收,从而导致第一次创建的Activity中的所有对象都不能被回收。这个时候,一部分内存就浪费掉了。
经验分享:
在实际项目中,我们经常会把一些对象的引用加入到集合中,如果这个集合是静态的话,就需要特别注意了。当不需要某对象时,务必及时把它的引用从集合中清理掉。或者可以为集合提供一种更新策略,及时更新整个集合,这样可以保证集合的大小不超过某值,避免内存空间的浪费。&
2)使用Application的Context
在Android中,Application Context的生命周期和应用的生命周期一样长,而不是取决于某个Activity的生命周期。如果想保持一个长期生命的对象,并且这个对象需要一个Context,就可以使用Application对象。可以通过调用Context.getApplicationContext()方法或者Activity.getApplication()方法来获得Application对象。
依然拿上面的代码作为例子。可以将代码修改成下面的样子。 代码如下:private static Resources mR&
protected void onCreate(Bundle state) {
super.onCreate(state);
if (mResources == null) {
&&& // mResources = this.getResources();
&&& mResources = this.getApplication().getResources();
}在这里将this.getResources()修改为this.getApplication().getResources()。修改以后,Resources对象拥有的是Application对象的引用。如果Activity被重新创建,第一次创建的Activity就可以被回收了。
3)及时关闭资源
Cursor是Android查询数据后得到的一个管理数据集合的类。正常情况下,如果我们没有关闭它,系统会在回收它时进行关闭,但是这样的效率特别低。如果查询得到的数据量较小时还好,如果Cursor的数据量非常大,特别是如果里面有Blob信息时,就可能出现内存问题。所以一定要及时关闭Cursor。
下面给出一个通用的使用Cursor的代码片段。 代码如下:Cursor cursor =
&&& cursor = mContext.getContentResolver().query(uri,null,null,null,null);
&&& if (cursor != null) {
&&&&&&& cursor.moveToFirst();
&&&&&&& // 处理数据
} catch (Exception e){
&&& e.printStatckTrace();
} finally {
&&& if (cursor != null){
&&&&&&& cursor.close();
}即对异常进行捕获,并且在finally中将cursor关闭。
同样的,在使用文件的时候,也要及时关闭。
4)使用Bitmap及时调用recycle()
前面的章节讲过,在不使用Bitmap对象时,需要调用recycle()释放内存,然后将它设置为null。虽然调用recycle()并不能保证立即释放占用的内存,但是可以加速Bitmap的内存的释放。
在代码优化的过程中,如果发现某个Activity用到了Bitmap对象,却没有显式的调用recycle()释放内存,则需要分析代码逻辑,增加相关代码,在不再使用Bitmap以后调用recycle()释放内存。
5)对Adapter进行优化
下面以构造ListView的BaseAdapter为例说明如何对Adapter进行优化。
在BaseAdapter类中提供了如下方法: 代码如下:public View getView(int position, View convertView, ViewGroup parent)当ListView列表里的每一项显示时,都会调用Adapter的getView方法返回一个View,
来向ListView提供所需要的View对象。
下面是一个完整的getView()方法的代码示例。 代码如下:public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
  &&& convertView = mInflater.inflate(R.layout.list_item, null);
  &&& holder = new ViewHolder();
  &&& holder.text = (TextView) convertView.findViewById(R.id.text);
  &&& convertView.setTag(holder);
  } else {
  &&& holder = (ViewHolder) convertView.getTag();
  holder.text.setText("line" + position);
  return convertV
private class ViewHolder {
}当向上滚动ListView时,getView()方法会被反复调用。getView()的第二个参数convertView是被缓存起来的List条目中的View对象。当ListView滑动的时候,getView可能会直接返回旧的convertView。这里使用了convertView和ViewHolder,可以充分利用缓存,避免反复创建View对象和TextView对象。
如果ListView的条目只有几个,这种技巧并不能带来多少性能的提升。但是如果条目有几百甚至几千个,使用这种技巧只会创建几个convertView和ViewHolder(取决于当前界面能够显示的条目数),性能的差别就非常非常大了。&&&
6)代码“微优化”
当今时代已经进入了“微时代”。这里的“微优化”指的是代码层面的细节优化,即不改动代码整体结构,不改变程序原有的逻辑。尽管Android使用的是Dalvik虚拟机,但是传统的Java方面的代码优化技巧在Android开发中也都是适用的。
下面简要列举一部分。因为一般Java开发者都能够理解,就不再做具体的代码说明。
创建新的对象都需要额外的内存空间,要尽量减少创建新的对象。
将类、变量、方法等等的可见性修改为最小。
针对字符串的拼接,使用StringBuffer替代String。
不要在循环当中声明临时变量,不要在循环中捕获异常。
如果对于线程安全没有要求,尽量使用线程不安全的集合对象。
使用集合对象,如果事先知道其大小,则可以在构造方法中设置初始大小。
文件读取操作需要使用缓存类,及时关闭文件。
慎用异常,使用异常会导致性能降低。
如果程序会频繁创建线程,则可以考虑使用线程池。
经验分享:
代码的微优化有很多很多东西可以讲,小到一个变量的声明,大到一段算法。尤其在代码Review的过程中,可能会反复审查代码是否可以优化。不过我认为,代码的微优化是非常耗费时间的,没有必要从头到尾将所有代码都优化一遍。开发者应该根据具体的业务逻辑去专门针对某部分代码做优化。比如应用中可能有一些方法会被反复调用,那么这部分代码就值得专门做优化。其它的代码,需要开发者在写代码过程中去注意。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具Android性能优化(七)之你真的理解ANR吗?
在上一篇文章中,我们提到了卡顿的成因、检测卡顿的途径以及避免卡顿的方法。卡顿在扩大就会产生大名鼎鼎的ANR(Application Not Responding),然后告诉用户你的App无响应,继续等待或者强制关闭,很大的概率用户可能会顺手卸载如此卡的App。
ANR造成的影响特别严重,而在实际开发过程中我们一般都会使用异步来规避ANR,但同时也正因为此我们可能会对ANR熟视无睹:因为常见,所以多见不怪!不信我来提个问题:
在中采用单独开进程执行Dex预加载优化的操作时,主进程在后台sleep(),为什么不会出现ANR呢?
KeyDispatchTimeout –按键或触摸事件在特定时间内无响应;
BroadcastTimeout –BroadcastReceiver在特定时间内无法处理完成;
ServiceTimeout –Service在特定的时间内无法处理完成;
应用自身引起,例如:
主线程阻塞、IOWait等;
其他进程间接引起,例如:
当前应用进程进行进程间通信请求其他进程,其他进程的操作长时间没有反馈;
其他进程的CPU占用率高,使得当前应用进程无法抢占到CPU时间片;
当发生ANR的时候Logcat中会出现提示;
04-06 15:58:46.215 23480-23483/com.example.testanr I/art: Thread[2,tid=23483,WaitingInMainSignalCatcherLoop,Thread*=0x7fa2307000,peer=0x12cb40a0,"Signal Catcher"]: reacting to signal 3
04-06 15:58:46.364 23480-23483/com.example.testanr I/art: Wrote stack traces to '/data/anr/traces.txt'ANR的Log信息保存在:/data/anr/traces.txt,每一次新的ANR发生,会把之前的ANR信息覆盖掉。
04-01 13:12:11.572 I/InputDispatcher( 220): Application is not responding:Window{2b263310com.android.email/com.android.email.activity.SplitScreenActivitypaused=false}.
5009.8ms since event, 5009.5ms since waitstarted
04-0113:12:11.572 I/WindowManager( 220): Input event
dispatching timedout sending
tocom.android.email/com.android.email.activity.SplitScreenActivity
04-01 13:12:14.123 I/Process( 220): Sending signal. PID: 21404 SIG:3---发生ANR的时间和生成trace.txt的时间
04-01 13:12:14.123 I/dalvikvm(21404):threadid=4: reacting to signal 3 ……
04-0113:12:15.872 E/ActivityManager( 220): ANR in com.android.email(com.android.email/.activity.SplitScreenActivity)
04-0113:12:15.872 E/ActivityManager( 220): Reason:keyDispatchingTimedOut
-----ANR的类型
04-0113:12:15.872 E/ActivityManager( 220): Load: 8.68 / 8.37 / 8.53 --CPU的负载情况
04-0113:12:15.872 E/ActivityManager( 220): CPUusage from 4361ms to 699ms ago ----CPU在ANR发生前的使用情况;备注:这个ago,是发生前一段时间的使用情况,不是当前时间点的使用情况;
04-0113:12:15.872 E/ActivityManager( 220): 5.5%21404/com.android.email: 1.3% user + 4.1% kernel / faults:
04-0113:12:15.872 E/ActivityManager( 220): 4.3%220/system_server: 2.7% user + 1.5% kernel / faults: 11
minor 2 major
04-0113:12:15.872 E/ActivityManager( 220): 0.9%52/spi_qsd.0: 0% user + 0.9% kernel
04-0113:12:15.872 E/ActivityManager( 220): 0.5%65/irq/170-cyttsp-: 0% user + 0.5% kernel
04-0113:12:15.872 E/ActivityManager( 220): 0.5%296/com.android.systemui: 0.5% user + 0% kernel
04-0113:12:15.872 E/ActivityManager( 220): 100%TOTAL: 4.8% user + 7.6% kernel + 87% iowait----注意这行:注意87%的iowait
04-0113:12:15.872 E/ActivityManager( 220): CPUusage from 3697ms to 4223ms later:-- ANR后CPU的使用量
04-0113:12:15.872 E/ActivityManager( 220): 25%21404/com.android.email: 25% user + 0% kernel / faults: 191 minor
04-0113:12:15.872 E/ActivityManager( 220): 16% 21603/__eas(par.hakan: 16% user + 0% kernel
04-0113:12:15.872 E/ActivityManager( 220): 7.2% 21406/GC: 7.2% user + 0% kernel
04-0113:12:15.872 E/ActivityManager( 220): 1.8% 21409/Compiler: 1.8% user + 0% kernel
04-0113:12:15.872 E/ActivityManager( 220): 5.5%220/system_server: 0% user + 5.5% kernel / faults: 1 minor
04-0113:12:15.872 E/ActivityManager( 220): 5.5% 263/InputDispatcher: 0% user + 5.5% kernel
04-0113:12:15.872 E/ActivityManager( 220): 32%TOTAL: 28% user + 3.7% kernel从Logcat中可以得到以下信息:
导致ANR的包名(com.android.emai),类名(com.android.email.activity.SplitScreenActivity),进程PID(21404)
导致ANR的原因:keyDispatchingTimedOut
系统中活跃进程的CPU占用率,关键的一句:100%TOTAL: 4.8% user + 7.6% kernel + 87% iowait;表示CPU占用满负荷了,其中绝大数是被iowait即I/O操作占用了。我们就可以大致得出是io操作导致的ANR。
限于篇幅有限,不在分析别的ANR类型。同时需要注意:并不是所有的ANR类型都有章可循,很多偶发的ANR受限于当时发生的环境或者系统Bug;因此对ANR,更应该强调预防而不是分析。
InputDispatching Timeout :输入事件分发超时5s未响应完毕;
BroadcastQueue Timeout :前台广播在10s内、后台广播在20秒内未执行完成;
Service Timeout :前台服务在20s内、后台服务在200秒内未执行完成;
ContentProvider Timeout :内容提供者,在publish过超时10s;
系统的ANR机制是如何运行的,ANR是如何被出发的呢?我们先来说说Service,主要用于在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。但很多同志认为Service就可以执行耗时任务,这是一种误解,Service本身也运行于主线程,执行耗时任务同样会发生ANR。此处只分析Service Timeout的出发场景。
Service的启动过程由ContextWrapper开始,我们直接步入重点环节ActiveServices.java中realStartServiceLocked方法
private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app, boolean execInFg) throws RemoteException {
bumpServiceExecutingLocked(r, execInFg, "create");
app.thread.scheduleCreateService(r, r.serviceInfo,
patibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
}其中bumpServiceExecutingLocked()方法又会调用到scheduleServiceTimeoutLocked()方法延时发送SERVICE_TIMEOUT_MSG消息。
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
if (proc.executingServices.size() == 0 || proc.thread == null) {
long now = SystemClock.uptimeMillis();
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
mAm.mHandler.sendMessageAtTime(msg,
proc.execServicesFg ? (now+SERVICE_TIMEOUT) : (now+ SERVICE_BACKGROUND_TIMEOUT));
}接下来调用到了ActivityThread.java的scheduleCreateService()方法,实际上使用Handler发送了一条msg,最终调用到ActivityThread.java的handleCreateService()方法
private void handleCreateService(CreateServiceData data) {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl..name).newInstance();
} catch (Exception e) {
service.onCreate();
mServices.put(data.token, service);
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (Exception e) {
ActivityManagerNative.getDefault().serviceDoneExecuting会执行到ActivityManagerService.java中的serviceDoneExecuting()方法,进而执行到ActiveService.java中的serviceDoneExecutingLocked()方法。此处意义:remove掉刚刚延时发送的Message。
private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,boolean finishing) {
if (r.app.executingServices.size() == 0) {
if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
"No more executingServices of " + r.shortName);
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
} else if (r.executeFg) {
for (int i=r.app.executingServices.size()-1; i&=0; i--) {
if (r.app.executingServices.valueAt(i).executeFg) {
r.app.execServicesFg = true;
而如果Message没有被mAm.mHandler(也就是ActivityManagerService中的MainHandler)及时remove掉,被执行的话就会出发ANR的发生;执行到ActivityManagerService中MainHandler的SERVICE_TIMEOUT_MSG然后调用到ActiveServices的serviceTimeout()方法,最终执行到ActivityManagerService的appNotResponding()方法。
final void appNotResponding(ProcessRecord app, ActivityRecord activity,
ActivityRecord parent, boolean aboveSystem, final String annotation) {
ArrayList&Integer& firstPids = new ArrayList&Integer&(5);
SparseArray&Boolean& lastPids = new SparseArray&Boolean&(20);
synchronized (this) {
firstPids.add(app.pid);
int parentPid = app.
if (parent != null && parent.app != null && parent.app.pid & 0) parentPid = parent.app.
if (parentPid != app.pid) firstPids.add(parentPid);
if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
for (int i = mLruProcesses.size() - 1; i &= 0; i--) {
ProcessRecord r = mLruProcesses.get(i);
if (r != null && r.thread != null) {
int pid = r.
if (pid & 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
if (r.persistent) {
firstPids.add(pid);
lastPids.put(pid, Boolean.TRUE);
StringBuilder info = new StringBuilder();
info.setLength(0);
info.append("ANR in ").append(app.processName);
if (activity != null && activity.shortComponentName != null) {
info.append(" (").append(activity.shortComponentName).append(")");
info.append("\n");
info.append("PID: ").append(app.pid).append("\n");
if (annotation != null) {
info.append("Reason: ").append(annotation).append("\n");
if (parent != null && parent != activity) {
info.append("Parent: ").append(parent.shortComponentName).append("\n");
final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
File tracesFile = dumpStackTraces(true, firstPids, processCpuTracker, lastPids,
NATIVE_STACKS_OF_INTEREST);
String cpuInfo = null;
if (MONITOR_CPU_USAGE) {
updateCpuStatsNow();
synchronized (mProcessCpuTracker) {
cpuInfo = mProcessCpuTracker.printCurrentState(anrTime);
info.append(processCpuTracker.printCurrentLoad());
info.append(cpuInfo);
info.append(processCpuTracker.printCurrentState(anrTime));
Slog.e(TAG, info.toString());
if (tracesFile == null) {
Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
cpuInfo, tracesFile, null);
boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
synchronized (this) {
mBatteryStatsService.noteProcessAnr(app.processName, app.uid);
if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
app.kill("bg anr", true);
makeAppNotRespondingLocked(app,
activity != null ? activity.shortComponentName : null,
annotation != null ? "ANR " + annotation : "ANR",
info.toString());
Message msg = Message.obtain();
HashMap&String, Object& map = new HashMap&String, Object&();
msg.what = SHOW_NOT_RESPONDING_MSG;
msg.arg1 = aboveSystem ? 1 : 0;
map.put("app", app);
if (activity != null) {
map.put("activity", activity);
mUiHandler.sendMessage(msg);
}流程总结:1. Service创建之前会延迟发送一个消息,而这个消息就是ANR的起源;2. Service创建完毕,在规定的时间之内执行完毕onCreate()方法就移除这个消息,就不会产生ANR了;3. 在规定的时间之内没有完成onCreate()的调用,消息被执行,ANR发生。
Service Timeout流程图
1、Service创建过程中对onCreate()埋下了ANR的起源,其中不能执行超过规定时间的操作,那是不是可以移到onStartCommand()方法中?
真是机智的同学,点个赞!然而事实并不是这样的,onStartCommond()方法的调用是在ActiveServices.java的sendServiceArgsLocked(),这个过程和onCreate()很类似,都会延时发送Message,然后在规定时间内执行完毕的话移除;没有完成的话发生ANR!
2、回到上面的问题:在中采用单独开进程执行Dex预加载优化的操作时,主进程在后台sleep(),为什么不会出现ANR呢?
答案是不是很清晰了:回忆下ANR的触发场景,此时主进程处于后台,无法响应按键、触摸等事件,同时此时也并没有Service等发生ANR的条件,因此主进程只是在后台等待,不会发生ANR。这种思路在MultiDex以及插件化方案中都有实践。
欢迎关注微信公众号:定期分享Java、Android干货!
55分享到微信扫一扫掘金翻译计划是一个翻译优质互联网技术文章的社区,文章翻译自国外优秀英文文章。内容覆盖区块链、人工智能、Android、iOS、React、前端、后端、产品、设计等领域。欢迎加入掘金翻译计划。相关文章55}

我要回帖

更多关于 android 广播效率 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信