У меня есть CountDownTimer, который вызывает метод ChangeWallpaper() каждые 15 секунд. Обои меняются так, как должно, но когда я пытаюсь открыть приложение, он делает экран App Drawer неактивным в течение нескольких секунд. Когда приложение наконец откроется, все, что я выбираю, занимает 5-10 секунд, чтобы ответить. Я прочитал об AsyncTask в Android Developer, который должен загружать растровые изображения вне потока пользовательского интерфейса и не допускать зависание приложения, но он, похоже, не работает.Приложение UI перестает отвечать на запросы при загрузке Bitmap
Следующий код находится внутри моего класса активности:
/** changeWallpaper() **/ - called by CountDownTimer every 15 seconds
protected void changeWallpaper() throws IOException {
Integer totalimages = finallist.size();
if (lastloopcount == totalimages) { // if end of the list of images is reached, it resets and goes back to top.
loopcount = 0;
lastloopcount = 0;
}
for (String imagepath : finallist) { // "finallist" is global variable with all the image's paths in an array list. The Loop count is to select the next image in the array list every 15 seconds.
loopcount++;
if (loopcount > lastloopcount) {
lastloopcount = loopcount;
loopcount = 0;
WallpaperManager wm = WallpaperManager.getInstance(this);
wm.setBitmap(decodeImageFromPath(imagepath));
break;
}
}
}
/** AsyncTask Wallpaper Load **/
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
public BitmapWorkerTask(ImageView imageView) {
new WeakReference<ImageView>(imageView);
}
@Override
protected Bitmap doInBackground(Integer... params) {
return null;
}
}
/** decodeImageFromPath() **/
public Bitmap decodeImageFromPath(String imagepath) {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels << 2;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagepath, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, width, height);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(imagepath, options);
}
/** WallpaperManager (Method) **/
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// ... Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int stretch_width = Math.round((float)width/(float)reqWidth);
int stretch_height = Math.round((float)height/(float)reqHeight);
if (stretch_width <= stretch_height) return stretch_height;
else return stretch_width;
}
- Использовал я правильно функцию AsyncTask?
- Есть ли более простой способ написать это?
Заранее спасибо.
РЕДАКТИРОВАТЬ:
/** Spinner **/
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String chosenTime = parent.getItemAtPosition(position).toString();
int chosenTimeNew = 0;
if (chosenTime.contains("sec")) {
chosenTime = chosenTime.replace(" sec","");
chosenTimeNew = Integer.parseInt(chosenTime) * 500;
} else if (chosenTime.contains("min")) {
chosenTime = chosenTime.replace(" min","");
chosenTimeNew = Integer.parseInt(chosenTime) * 30000;
} else if (chosenTime.contains("hour")) {
chosenTime = chosenTime.replace(" hour","");
chosenTimeNew = (Integer.parseInt(chosenTime) * 30000) * 60;
} else if (chosenTime.contains("day")) {
chosenTime = chosenTime.replace(" day","");
chosenTimeNew = ((Integer.parseInt(chosenTime) * 30000) * 60) * 24;
}
rSpeed = chosenTimeNew;
}
EDIT 2:
Вызывается CountDownTimer():
new BitmapWorkerTask(null).execute(imagepath);
Тогда:
/** AsyncTask Wallpaper Load **/
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
public BitmapWorkerTask(ImageView imageView) {
new WeakReference<ImageView>(imageView);
}
@Override
protected Bitmap doInBackground(String... params) {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels << 2;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(params[0], options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, width, height);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap bmp = BitmapFactory.decodeFile(params[0], options);
return bmp;
}
protected void onPostExecute(Bitmap bmp) {
Context context = getApplicationContext();
WallpaperManager wm = WallpaperManager.getInstance(context);
try {
wm.setBitmap(bmp);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** WallpaperManager (Method) **/
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// ... Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int stretch_width = Math.round((float)width/(float)reqWidth);
int stretch_height = Math.round((float)height/(float)reqHeight);
if (stretch_width <= stretch_height) return stretch_height;
else return stretch_width;
}
Вы даже не используете свою «BitmapWorkerTask»!Там нет волшебства, которое делает произвольные части вашего кода в фоновом режиме, только когда вы пишете какой-то «AsyncTask» в свой код. Вы тоже должны это использовать. – Ridcully
Если я добавлю decodeImageFromPath() в doInBackground(), как я могу передать переменную imagepath в decodeImageFromPath() ?, путь изображения должен быть определен внутри decodeImageFromPath(), но вместо его определения мне нужно использовать содержимое пути изображения, определенного внутри ChangeWallpaper() – KickAss
См. изменение в моем ответе, пожалуйста. – Ridcully