发布于 2016-03-01 22:05:27 | 164 次阅读 | 评论: 1 | 来源: 网友投递

这里有新鲜出炉的精品教程,程序狗速度看过来!

Android移动端操作系统

Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安致”。


这篇文章主要介绍了Android开发中避免应用无响应的方法,即避免弹出Application Not Responding(ANR)对话框,需要的朋友可以参考下

App里发生的最糟糕的事是弹出应用无响应”Application Not Responding” (ANR) 对话框.本课讲的是如何保持应用响应,避免ANR。

什么触发ANR

通常,系统会在应用无法对用户输入响应时显示ANR。比如,如果一个应用在I/O操作上阻塞了(频繁请求网络)UI线程,系统无法处理用户输入事件。或者,在UI线程中,app花了大量时间在构建复杂的类,或在游戏中计算下一个动作。保证这些操作高效是很重要的,但最高效的代码也需要花费时间。

在任何情况下,都不要在UI线程执行耗时任务,取而代之的是创建 一个工作线程,在这个线程里操作。这可以保持UI线程运行,阻止系统因为代码卡住而结束应用。
在Android里,Activity Manager和Window Manager系统服务监控着应用的响应能力。Android会在检测到以下情形中之一时,弹出ANR对话框:

1.未在5秒内对用户输入事件响应
2.BroadcastReceiver未在10秒内执行完

如何避免ANR

Android应用默认运行在单线程里,叫UI线程或主线程。这意味着,你的应用所有工作都在UI线程里,如果花费很长时间才能完成,会触发ANR,因为此时应用无法操控输入事件或广播。

因此,UI 线程里的任何方法都应该尽可能地做轻量的工作,特别是Activity在生命周期方法,像onCreate(),onResume().潜在的耗时操作,像网络,数据库,或昂贵的计算(像改变图片大小)应该在工作线程里完成(或者在数据库操作案例里,通过一个异步请求)。

最高效的方法是为耗时操作使用AsyncTask类创建工作线程。继承AsyncTask实现doInBackground()方法来执行工作。要发送进度给用户,调用 publishProgress(),会触发onProgressUpdate(),例子:



private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {

    // Do the long-running work in here

    protected Long doInBackground(URL... urls) {

        int count = urls.length;

        long totalSize = 0;

        for (int i = 0; i < count; i++) {

            totalSize += Downloader.downloadFile(urls[i]);

            publishProgress((int) ((i / (float) count) * 100));

            // Escape early if cancel() is called

            if (isCancelled()) break;

        }

        return totalSize;

    }

 

    // This is called each time you call publishProgress()

    protected void onProgressUpdate(Integer... progress) {

        setProgressPercent(progress[0]);

    }

 

    // This is called when doInBackground() is finished

    protected void onPostExecute(Long result) {

        showNotification("Downloaded " + result + " bytes");

    }

}

执行这个工作线程,只需要创建一个实例,调用 execute():

new DownloadFilesTask().execute(url1, url2, url3);

尽管比AsyncTask更复杂,你可能还是想创建自己的线程或者HandlerThread类,如果这么做,你应该调用Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND) 设置线程优先线为”background”.如果没有,线程仍然会拖慢应用,因为它跟UI线程优先级相同。

如果你实现Thread或HandlerThread,确保UI线程没有因为等待工作线程执行完而阻塞。不要调用Thread.wait()或Thread.sleep(),而是提供一个Handler,供任务执行完后回调。如此设计,UI线程会保持响应,避免出现ANR对话框。

特别强调BroadcastReceiver的执行时间,意味着你要:分散工作到后台线程里,像保存设置或者注册Notification。执行密集任务(intensive tasks),应该用IntentService。

提示:你可以用StrictMode帮你找到在UI线程上潜在的耗时操作



最新网友评论  共有(1)条评论 发布评论 返回顶部
pfczn 发布于2016-04-24 10:37:11
真的很好,谢谢楼主
支持(0)  反对(0)  回复

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务