如何做“应用无响应”(ANR)对话框?

时间:2014-05-07 12:20:05

标签: android

我正在制作一个每隔5秒就会更换壁纸的项目

我使用了这段代码,每5秒后壁纸就会发生变化,但问题就出现了,就像我在照片中提到的那样

DisplayMetrics displayMetrics = new DisplayMetrics();
        int height = displayMetrics.heightPixels;
        int width = displayMetrics.widthPixels << 1; // best wallpaper width is twice screen width

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        for(int i=0; i<=list.size();i++){
            if(i==list.size()){
                i=0;
            }


        BitmapFactory.decodeFile(list.get(i));


        options.inJustDecodeBounds = false;
        Bitmap decodedSampleBitmap = BitmapFactory.decodeFile(list.get(i));

        WallpaperManager wm = WallpaperManager.getInstance(this);
        try {
            Log.i("In Service", "before set wallpaper");
            wm.setBitmap(decodedSampleBitmap);
            Log.i("In Service", "after set wallpaper");
            Thread.sleep(5000);
            Log.i("In Service", "after thread");

        } catch (Exception e) {
            Log.e("Exception", "Cannot set image as wallpaper", e);
        }
        }

一段时间后,当图像发生变化时,会出现此对话框 当我点击等待按钮时,它开始工作

之后,当我再次打开应用程序以选择其他图像时,我会收到对话框

之后我读了http://developer.android.com/training/articles/perf-anr.html 并且确实在不同的线程中工作,但也没有任何用处。我可以知道我必须做什么,以便不得出现此对话框


更新1:

我使用Async Task并且它工作正常,我现在没有得到ANR对话框,但是在图像非常重的情况下它需要超过5秒,即1.5到2.5 mb的情况但是它的运行状况良好图像大小为300-400 mb

public class WallService extends Service {

    ArrayList<String> list;

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        Log.i("on create", "Service Created");

    }

    @Override
    @Deprecated
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub
        super.onStart(intent, startId);

        list = intent.getStringArrayListExtra("Imagess");
        new LongOperation().execute("");
    }

    private class LongOperation extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {

            DisplayMetrics displayMetrics = new DisplayMetrics();
            int height = displayMetrics.heightPixels;
            int width = displayMetrics.widthPixels << 1; // best wallpaper width
                                                            // is twice screen
                                                            // width

            // First decode with inJustDecodeBounds=true to check dimensions
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            for (int i = 0; i <= list.size(); i++) {
                if (i == list.size()) {
                    i = 0;
                }

                BitmapFactory.decodeFile(list.get(i));

                options.inJustDecodeBounds = false;
                Bitmap decodedSampleBitmap = BitmapFactory.decodeFile(list
                        .get(i));

                WallpaperManager wm = WallpaperManager
                        .getInstance(WallService.this);
                try {
                    Log.i("In Service", "before set wallpaper");
                    wm.setBitmap(decodedSampleBitmap);
                    Log.i("In Service", "after set wallpaper");
                    Thread.sleep(5000);
                    Log.i("In Service", "after thread");

                } catch (Exception e) {
                    Log.e("Exception", "Cannot set image as wallpaper", e);
                }
            }
            return "Executed";
        }

        @Override
        protected void onPostExecute(String result) {

        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(Void... values) {
        }
    }

}

但我没有得到第二个问题的解决方案,即当我再次打开应用程序并点击选择照片按钮时,它会给我这个对话框

我可以知道我必须为这两个问题做些什么,即 1.即使图像较重也能很好地工作 2.当我再次回到应用程序时,我没有得到对话框

enter image description here

我遇到的logcat是

05-07 19:03:34.414: E/dalvikvm(18247): can't open /data/misc/hprof_oom_dump.hprof: Permission denied
05-07 19:03:34.434: D/-heap(18247): Dump of hprof is not done
05-07 19:03:34.454: D/skia(18247): --- decoder->decode returned false
05-07 19:03:34.454: W/dalvikvm(18247): threadid=1: thread exiting with uncaught exception (group=0x418c5450)
05-07 19:03:34.454: E/AndroidRuntime(18247): FATAL EXCEPTION: main
05-07 19:03:34.454: E/AndroidRuntime(18247): java.lang.OutOfMemoryError
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:527)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:301)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:326)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at com.example.images.MainActivity.onActivityResult(MainActivity.java:110)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.app.Activity.dispatchActivityResult(Activity.java:5192)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.app.ActivityThread.deliverResults(ActivityThread.java:3143)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.app.ActivityThread.handleSendResult(ActivityThread.java:3190)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.app.ActivityThread.access$1100(ActivityThread.java:133)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1246)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.os.Handler.dispatchMessage(Handler.java:99)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.os.Looper.loop(Looper.java:137)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at android.app.ActivityThread.main(ActivityThread.java:4803)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at java.lang.reflect.Method.invokeNative(Native Method)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at java.lang.reflect.Method.invoke(Method.java:511)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
05-07 19:03:34.454: E/AndroidRuntime(18247):    at dalvik.system.NativeStart.main(Native Method)
05-07 19:03:34.575: I/In Service(18247): before set wallpaper
05-07 19:03:53.525: I/In Service(18247): after set wallpaper
05-07 19:03:58.530: I/In Service(18247): after thread

4 个答案:

答案 0 :(得分:2)

你应该重新审视一下你的设计。 ANR对话框是由主要UI线程上的重量级作业引起的。 试着看看你是否可以将处理推送到asynctask或者加载器。那应该可以解决你的问题。您正在使用的for循环可以有效地推送到asynctask。

答案 1 :(得分:1)

您获得应用程序无响应,因为您使用无限for循环阻止UI线程。您将获得阻止UI线程超过5秒的对话框。

请考虑使用Thread.sleep()Timer在指定时间启动回调,而不是循环和Handler延迟。

在后台线程而不是UI线程上进行位图加载和解码也是一个好主意,但这不是ANR的直接原因。

答案 2 :(得分:0)

没有现成的解决方案来避免ANR。通常,如果应用程序无法响应用户输入,系统将显示ANR。例如,如果应用程序阻止UI线程上的某些I / O操作(通常是网络访问),则系统无法处理传入的用户输入事件。

在您的应用程序执行可能冗长的操作的任何情况下,您不应该在UI线程上执行工作,而是创建工作线程并在那里完成大部分工作。这使得UI线程(驱动用户界面事件循环)保持运行,并阻止系统断定您的代码已冻结。

因此,您可以考虑在后台执行冗长的任务(使用AsyncTask)以避免ANR消息。

参考

http://developer.android.com/training/articles/perf-anr.html

https://stackoverflow.com/a/10515848/1665507

答案 3 :(得分:0)

你现在遇到的问题是你的应用程序内存不足,即OOM ..

为了避免ANR,你可以在没有UI线程的情况下进行长时间的操作,(线程和处理程序,异步任务等) 要避免OOM(内存不足异常),请按照以下步骤处理大型位阻http://developer.android.com/training/displaying-bitmaps/load-bitmap.html,同时您还可以找到一些jni强制执行来有效地存储和检索大型位图。

以下是您可能需要的JNI bitmap operations , for helping to avoid OOM when using large images