Android, jakiś globalny callback na akcje

0

Hej,

jestem raczkującym programistą Androida i potrzebuje odpowiedzi na pytanie takie, otóż, mam AsyncTaska który pobiera mi xml ze strony, chciałbym aby na onPostExecute wykonał się jakiś globalny callback który poinformuje dwa fragmenty o tym aby wykonały one metodę refresh.
Co robią fragmenty, jeden przechowuje główną listę itemów a drugi też przechowuje listę jednak nie taką samą a w pewien sposób przefiltrowaną, dlatego chcę taki callback żeby jak najmniejszym kosztem wymusić zaktualizowanie głównej listy oraz równocześnie przefiltrowanej. W zasadzie aktualizację listy głównej mam zaimplementowaną ale nie podoba mi się ona ponieważ zdaje mi się że jest zrobiona na około (robię tylko notifyDataSetChange, i to wyłącznie dla głównej listy bo ta zfiltrowana ma inną instancje listy).
Mam nadzieję że jasno opisałem problem. Proszę o wyrozumiałość i pomoc.

2

to czego szukasz to EventBus. Jakiś czas temu miałem dokładnie ten sam problem i pomógł mi @Koziołek
albo otto http://square.github.io/otto/
albo green event bus
https://github.com/greenrobot/EventBus

do wyboru do koloru co kto woli :-)

Jezeli nie chcesz z tego korzystać pozostaje Ci napisanie interfejsu w asyncTasku który będzie wywoływał na postexecute funkcję w fragmencie :-)

mam nadzieję że pomogłem

pzdr

0

Dzięki za odpowiedź :) ale z tego co teraz testuje to nie spełnia to mojego założenia, hmm, jak by to inaczej zobrazować o co mi dokładnie chodzi, może pseudokod:

// MainActivity
public class MainActivity extends FragmentActivity {

  public interface MyListener {
    void callbackFunction(String output);
  }

  private class DownloadWebpageTask extends AsyncTask<String, Void, ArrayList<Place>> {
      private MyListener listener;

      @Override
      protected ArrayList<Place> doInBackground(String... urls) {
          // pobieraj
          return 1;
      }

      @Override
      protected void onPostExecute(ArrayList<Place> place){
          
          listener.callbackFunction("Taaak");
      }
  }
}

// fragment1

public class MyFragment extends Fragment implements MainActivity.MyListener {
  
  // i żeby tutaj sie ta funkcja wykonywała
  @Override
  public void callbackFunction(String output) {
      Toast.makeText(getActivity(), output, Toast.LENGTH_SHORT).show();
  }
}

od razu zaznaczam że nie wiem czy to jest wykonalne, to jest po prostu działanie jakie bym sobie wyobrażał. Da radę?

0

Bardziej konkretnie opisz problem. Co chcesz zrobić. Używanie AsyncTaska jest niezalecane nawet przez jego autora. Do obsługi żądań http są specjalne biblioteki takie jak retrofit czy volley.
Asynctask jest "nieczuły" na zmiany konfiguracji, tzn. wyobraź sobie taki scenariusz:

  • wywołujesz funkcję w aktywności (w asynctasku)
  • wychodzisz z aktywności zanim funkcja skończy pracę
  • masz teraz dwa problemy, asynctask trzyma referencję do aktywności, możesz również spodziewać się crasha w metodzie onPostExecute.

Jeżeli nie pracujesz z żadnym api, a chcesz po prostu pobrać pliki z internetu to służy do tego klasa DownloadManager (działa on np. jak instalujesz jakąś aplikację w playstore).

2
// MainActivity
public class MainActivity extends FragmentActivity {

  public interface MyListener {
    void callbackFunction(String output);
  }

  private class DownloadWebpageTask extends AsyncTask<String, Void, ArrayList<Place>> {
      private MyListener listener;

      @Override
      protected ArrayList<Place> doInBackground(String... urls) {
          // pobieraj
          return 1;
      }

      @Override
      protected void onPostExecute(ArrayList<Place> place){
          
          Bus.post(new PlaceEvent(place));
      }
  }
}

// fragment1

public class MyFragment extends Fragment implements MainActivity.MyListener {
  
  // i żeby tutaj sie ta funkcja wykonywała
  @Subscribe
  public void onPlaceEventAnswer(PlaceEvent event){
   ArrayList<Place> place=event.getPlace();



 }
}

Nie wiem dlaczego EventBus uważasz za zły przykład w tym momencie. Właśnie idealnie się do tego nadaje. powyżej przykład kodu.
Wtedy możesz nawet AsyncTaska wywalić do oddzielnej klasy żeby nie zaśmiecać Activity

ale zastanów się nad tym co napisał @zalogowanyNiezalogowany

pzdr

1

W Androidzie są od tego BroadcastReceiver oraz Context.sendBroadcast.

2

http://square.github.io/otto/

Dodajesz tą bibliotekę do projektu. Tworzysz klasę:


/**
* Maintains a singleton instance for obtaining the bus. Ideally this would be replaced with a more efficient means
* such as through injection directly into interested classes.
*/
public final class BusProvider {
private static final Bus BUS = new Bus();
   public static Bus getInstance() {
      return BUS;
   }
   private BusProvider() {
      // No instances.
  }
}

Tworzysz drugą klasę:

public class RefreshEvent  {
  // Twoje dane
}

W każdym fragmencie, który chcesz odświeżyć dajesz:

@Override public void onResume() {
   super.onResume();
   BusProvider.getInstance().register(this);
}
@Override public void onPause() {
   super.onPause();
   BusProvider.getInstance().unregister(this);
}


@Subscribe public void refreshFragment(RefreshEvent event) {
   //ta metoda zostanie odpalona w momencie jak zrobisz to co poniżej opisałem
}

W aktywności jak dostaniesz odpowiedź z plikiem xml (np. w metodzie onPostExecute()) to robisz coś takiego:

   BusProvider().getInstance().post(new RefreshEvent(/*tutaj np. przekazujesz dane z pliku xml*/))l
0

Zrobiłem tak jak poleciłeś tym otto, ale metoda z adnotacja subscribe działa tylko w MainActivity (w tym co robie BusProvider post) a we fragmencie już nie działa. Masz jakiś pomysł?

0

ło jezu a przeczytał Ty dokumentacje? trzeba zarejestrować odbiorcę.
cytuję post powyżej Twojego

W każdym fragmencie, który chcesz odświeżyć dajesz:
@Override public void onResume() {
super.onResume();
BusProvider.getInstance().register(this);
}
@Override public void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}

@Subscribe public void refreshFragment(RefreshEvent event) {
//ta metoda zostanie odpalona w momencie jak zrobisz to co poniżej opisałem
}

0

Ło jezu przeczytał. I jak możesz przeczytać w moim poscie "Zrobiłem tak jak poleciłeś" więc zarejestrowałem odbiorce. Problem polega na tym że fragment ładuje się mi po download tasku a więc po wysłaniu post eventbusa. Ale juz sobie poradzilem i EventBus działa zgodnie z moimi wyobrażeniami. Dzieki

1

nie w komentarzach pytania :P
mam pomysł. Zarejestrowałeś klasę FavouritesStationsFragment ale żadnego Subscriba nie napisałeś w środku . tak strzelam. Chociaż coś mi się kołacze po głowie że taki błąd to green event bus zwracał :P

a jeżeli nie to pokaż stacktrace i to się dzieje w czasie kompilacji czy w czasie wykonywania ?

0 użytkowników online, w tym zalogowanych: 0, gości: 0