我正在制作一个每隔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.当我再次回到应用程序时,我没有得到对话框
我遇到的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
答案 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
答案 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