2015-08-05 16 views
9

Pracuję nad aplikacją na Androida, która pobiera obraz z Internetu i wyświetla w interfejsie użytkownika. Używam RecyclerView do wyświetlania obrazu. Planuję pobrać obraz przy użyciu osobnego wątku. i aktualizuj RecyclerView za pomocą handler'a. Nie wiem, pogoda ta koncepcja jest poprawna czy nie, (wiem AsyncTask, ale za cel uczenie Próbuję zaimplementować Handler.) Więc kodowana takie same jak poniżejUżyj programu obsługi do publikowania w wątku interfejsu użytkownika

private void loadNewsThumbnailImage(ArrayList<DataItem> dataList) { 
    for (DataItem item : DataList) { //DataItem is the model class 
     loadThumbnailFromInternet(item); 
     } 
} 



private void loadThumbnailFromInternet(final DataItem dataItem) { 

     Thread imageDowloaderThread = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       Bitmap bitmap = null; 
       try { 
        bitmap = getDataItemBitmap(dataItem.getmImageUrl()); 
        dataItem.setmThumbnail(bitmap); 
        new Handler().post(new Runnable() { // Tried new Handler(Looper.myLopper()) also 
         @Override 
         public void run() { 
          mAdapter.notifyDataSetChanged(); 
         } 
        }); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
     imageDowloaderThread.start(); 

    } 

Mam realizowane to kod, ale dostaję błąd, a aplikacja zostaje zakończona, nie wiem, dlaczego tak się dzieje. proszę, pomóż mi rozwiązać ten problem. i wyjaśnij, jaki jest problem z bieżącym kodem.

(proszę nie sugerować użycie AsyncTask (Próbowałem to i to działa dobrze))

UPDATE

Błąd pobierania: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

+0

prosimy odświeżyć Qn – droidev

Odpowiedz

15

Aplikacja jest uzyskiwanie zakończona, ponieważ wywołujesz metodę notifyDataSetChanged() z wątku innego niż interfejs użytkownika.

Wymienić:

new Handler().post(new Runnable() { // Tried new Handler(Looper.myLopper()) also 
         @Override 
         public void run() { 
          mAdapter.notifyDataSetChanged(); 
         } 
        }); 

z tym:

new Handler(Looper.getMainLooper()).post(new Runnable() { // Tried new Handler(Looper.myLopper()) also 
        @Override 
        public void run() { 
         mAdapter.notifyDataSetChanged(); 
        } 
       }); 
+1

że brzmi dobrze, ale jaka jest różnica między Looper.getMainLooper() i Looper.myLooper()? – droidev

+2

Looper.getMainLooper() pobiera główny looper aplikacji, natomiast Looper.myLooper() zwraca Looper powiązany z bieżącym wątkiem. refere: http://developer.android.com/reference/android/os/Looper.html –

1

Gwint zdefiniowano nie posiada Looper, a nie kolejka komunikatów, więc nie można wysłać wiadomość w tym wątku. AsyncTask ma swój własny Looper, który można znaleźć w jego kodzie źródłowym. To jest teleskopowa zdefiniowana w AsyncTask:

private static class InternalHandler extends Handler { 
    public InternalHandler() { 
     super(Looper.getMainLooper()); 
    } 

    @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) 
    @Override 
    public void handleMessage(Message msg) { 
     AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj; 
     switch (msg.what) { 
      case MESSAGE_POST_RESULT: 
       // There is only one result 
       result.mTask.finish(result.mData[0]); 
       break; 
      case MESSAGE_POST_PROGRESS: 
       result.mTask.onProgressUpdate(result.mData); 
       break; 
     } 
    } 
} 
Powiązane problemy