2013-04-01 6 views
0

У меня есть 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; 
} 
  1. Использовал я правильно функцию AsyncTask?
  2. Есть ли более простой способ написать это?

Заранее спасибо.

РЕДАКТИРОВАТЬ:

/** 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; 
} 
+2

Вы даже не используете свою «BitmapWorkerTask»!Там нет волшебства, которое делает произвольные части вашего кода в фоновом режиме, только когда вы пишете какой-то «AsyncTask» в свой код. Вы тоже должны это использовать. – Ridcully

+0

Если я добавлю decodeImageFromPath() в doInBackground(), как я могу передать переменную imagepath в decodeImageFromPath() ?, путь изображения должен быть определен внутри decodeImageFromPath(), но вместо его определения мне нужно использовать содержимое пути изображения, определенного внутри ChangeWallpaper() – KickAss

+0

См. изменение в моем ответе, пожалуйста. – Ridcully

ответ

1

Ваш основной код (обработка растрового изображения) следует вызывать из в методе doInBackground. Иначе это то же самое, что и синхронный звонок здесь.

 
    @Override 
    protected Bitmap doInBackground(String... params) { 
     Bitmap bmp = decodeImageFromPath(params[0]); 
     return bmp; 
    } 

    protected void onPostExecute(Bitmap bmp) { 
     wm.setBitmap(bmp) 
    } 
 
new BitmapWorkerTask().execute(imagePath); 

http://developer.android.com/reference/android/os/AsyncTask.html

Вы можете сослаться на пример по этой ссылке.

+0

Привет, Kumar, поэтому мне нужно изменить doInBackground's return to decodeImageFromPath (путь к изображению); Но как мне получить переменную Imagepath из ChangeWallpaper()? – KickAss

+0

Спасибо! Я тоже использовал вашу идею :) – KickAss

+0

Привет, Я реализовал ваш метод и все же запустил его, чтобы увидеть, работает ли он. Но изменение моего кода вызвало еще одну совершенно несвязанную ошибку. Внутри моего Spinner onItemSelected() parseInt() разработал эту ошибку: «Этот метод parseInt (String) не определен для типа String« – KickAss

0

Вы даже не используете свой BitmapWorkerTask! Там нет волшебства, которое делает произвольные части вашего кода в фоновом режиме, только когда вы пишете AsyncTask в свой код. Вы тоже должны это использовать.

Перемещение долговечные части ваших кодов в doInBackground() способе AsyncTask и вызывать его следующим образом: new BitmapWorkerTask().execute();

EDIT

Чтобы передать изображение-путь, изменить определение вашего BitmapWorkerTask например, ... extends AsyncTask<String, Void, Bitmap> ... (обратите внимание на String вместо Integer) и передайте путь изображения как параметр к методу execute().

new BitmapWorkerTask().execute(imagePath);

Имейте в виду, что теперь это работает асинхронно, так что возвращает выполнить() вызов немедленно, но загрузка изображения займет некоторое время, до сих пор.

Также прочитайте статью Painless Threading.

+0

Спасибо, я исправил его, используя вашу идею. – KickAss