26

Więc mam mój MainDisplayActivity, który implementuje zarówno Activity i LoaderManager.LoaderCallbacks<Cursor>. Tutaj mam A ListView, który wypełniam informacjami Agendy, które otrzymuję z mojej bazy danych za pomocą ContentProvider. Mam też GridView, który jest kalendarzem. Mam to ustawione po kliknięciu komórki, że agenda jest aktualizowana z klikniętym dniem. Mój problem polega na tym, że przy ponownym użyciu programu ładującego, który utworzyłem w onCreate() wewnątrz setOnItemClickListener(), nie odświeżam informacji za pomocą nowego kursora, który tworzę. Mogę po prostu utworzyć nowy program ładujący z innym identyfikatorem i działa on raz, ale po kliknięciu innego dnia przestaje odświeżać. Problem polega na kursie. Jak mogę odświeżyć kursor z programu ładującego, więc nie muszę tworzyć nowego programu ładującego? Z góry dziękuję!Jak odświeżyć kursor z CursorLoader?

wezwanie Początkowa stworzyć Loader onCreate() w moim MainDisplayActivity klasy:

makeProviderBundle(new String[] {"_id, event_name, start_date, start_time, end_date, end_time, location"}, 
      "date(?) >= start_date and date(?) <= end_date", new String[]{getChosenDate(), getChosenDate()}, null); 
    getLoaderManager().initLoader(0, myBundle, MainDisplayActivity.this); 

    list.setAdapter(agendaAdapter); 

Są nadpisane metody z LoaderCallbacks<Cursor>

@Override 
public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    Uri baseUri = SmartCalProvider.CONTENT_URI; 
    return new CursorLoader(this, baseUri, args.getStringArray("projection"), 
      args.getString("selection"), args.getStringArray("selectionArgs"), args.getBoolean("sortOrder") ? args.getString("sortOrder") : null); 
} 



@Override 
public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) { 
    agendaAdapter.swapCursor(arg1); 
} 



@Override 
public void onLoaderReset(Loader<Cursor> arg0) { 
    //Not really sure how this works. Maybe I need to fix this here? 
    agendaAdapter.swapCursor(null); 

} 

public void makeProviderBundle(String[] projection, String selection, String[] selectionArgs, String sortOrder){ 
    /*this is a convenience method to pass it arguments 
    * to pass into myBundle which in turn is passed 
    * into the Cursor loader to query the smartcal.db*/ 
    myBundle = new Bundle(); 
    myBundle.putStringArray("projection", projection); 
    myBundle.putString("selection", selection); 
    myBundle.putStringArray("selectionArgs", selectionArgs); 
    if(sortOrder != null) myBundle.putString("sortOrder", sortOrder); 
} 

Każdy dodatkowy kod potrzebny proszę nie wahaj się zapytać . Dziękuje jeszcze raz za każdą pomoc!

+0

To było moje doświadczenie, że kiedy używasz 'ContentResolver' do aktualizacji treści w' ContentProvider', że 'cursor' zostanie powiadomiony, a lista zostanie automatycznie zaktualizowana. Czy możesz również opublikować swój kod onClick? – stuckless

+0

Wiem dobrze. Zakładałem to również, ponieważ wszyscy mówili, jakie to wygodne. Ale tego nie robi. Problem polega na tym, że rozumiem, że to nie działa. Kiedy 'Loader' jest po raz pierwszy utworzony, wywołuje' onCreateLoader() '. Podczas wywoływania 'getLoaderManager(). InitLoader()', jeśli pierwszy argument, ID jest taki sam jak wcześniej utworzony 'Loader',' onCreateLoader() 'prawdopodobnie nie zostanie wywołany. Oczywiście jest to czysta spekulacja z mojej strony, ponieważ wciąż się uczę, ale pomyślałem, że musi istnieć metoda załadowania nowego Cursora, jeśli tak było. Alex był na tyle miły, aby go zapewnić! – Andy

Odpowiedz

40

Wystarczy tylko trochę przesunąć kod i zadzwonić pod numer restartLoader. Oznacza to, że

  1. Gdy użytkownik kliknie element listy, to jakoś zmienić prywatną instancji zmiennej, która jest zwracana w getChosenDate() (jestem będąc tutaj celowo niejasne, ponieważ nie określić, co dokładnie getChosenDate() zwrotów).

  2. Po wprowadzeniu zmiany należy zadzwonić pod numer getLoaderManager().restartLoader() na numer Loader. Twoje stare dane zostaną odrzucone, a restartLoader uruchomi ponownie onCreateLoader. Tym razem getChosenDate() zwróci inną wartość (w zależności od klikniętego elementu listy) i powinno to zrobić. Implementacja onCreateLoader powinien wyglądać mniej więcej tak:

    @Override 
    public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
        Uri baseUri = SmartCalProvider.CONTENT_URI; 
    
        makeProviderBundle(
         new String[] { "_id, event_name, start_date, start_time, end_date, end_time, location" }, 
         "date(?) >= start_date and date(?) <= end_date", 
         new String[]{ getChosenDate(), getChosenDate() }, 
         null); 
    
        return new CursorLoader(
          this, 
          baseUri, 
          args.getStringArray("projection"), 
          args.getString("selection"), 
          args.getStringArray("selectionArgs"),  
          args.getBoolean("sortOrder") ? args.getString("sortOrder") : null); 
    } 
    

Daj mi znać, jeśli to ma sens. :)

+0

Holy shiznit lol. To geniusz haha. Widzę, co mówisz. Tak więc metoda, którą mógłbym nazwać, to 'restartLoader()'. Dlaczego nie widzę tej metody w CursorLoader ?! Aha i przepraszam, 'getChosenDate()' zwraca datę String w formacie używanym przez bazy danych, więc mogę po prostu zrobić całe filtrowanie za pomocą SQLite zamiast kodu Java. – Andy

+0

Koleś !!! Kocham Cię! To działało pięknie. I patrząc na mój kod zdałem sobie sprawę z 'myBundle.putString (" date ", getChosenDate());', to było niepotrzebne. Więc go zdjąłem. Po prostu użyję go podczas wywoływania 'makeProviderBundle()'. Wielkie dzięki ... ZNOWU! – Andy

+11

Haha ... jesteś łatwy do pobudzenia, prawda? Cieszę się, że mogłem pomóc :). –