Android verwaltet Fragmente von der Aktivität elegant

Beschreibung von dem, was ich versuche zu erreichen: Ich habe eine App, die eine FragmentActivity mit einem LinearLayout als Container für die Fragmente verwendet. Ich klicke auf verschiedene Tasten auf der FragmentActivity UI und füge hinzu und füge Fragmente zum Container in der FragmentActivity hinzu. Zusätzlich zum Anklicken von Schaltflächen auf der FragmentActivity-Benutzeroberfläche hat jedes Fragment auch Schaltflächen, die angeklickt werden können, die das aktuelle Fragment entfernen und ein anderes Fragment an seinem Platz hinzufügen.

Die Android-Art, Dinge zu tun, wie ich es verstehe: Ich habe gelesen, wie man das macht und wie ich es verstehe, ist die "richtige" Art, Dinge zu tun, die FragmentActivity als eine Art Relaisstation zu benutzen und jedes Fragment zu haben Mache Rückrufe an die FragmentActivity, um Ereignisse zu kommunizieren und mit ihnen umzugehen.

Szenario: Sagen wir also, dass die FragmentActivity das Fragment A anzeigt und wenn der Benutzer auf eine Schaltfläche in FragmentA klickt, möchte ich aufhören, FragmentA anzuzeigen und mit FragmentB zu beginnen. Um dies zu tun, habe ich eine Schnittstelle in FragmentA namens AListener erstellt. In der onAttach () – Methode von FragmentA verwende ich die vorgeschlagene Methode, um zu prüfen, ob die FragmentActivity Alistener implementiert. Wenn die Schaltfläche in FragmentA geklickt wird, verwende ich eine der Rückrufmethoden von AListener, um das Klickereignis an die FragmentActivity zu übermitteln. In der FragmentActivity schaffe ich eine Instanz von FragmentB und füge sie dem Container in FragmentActivity hinzu. Dann, wenn ein Ereignis in FragmentB passiert, benutze ich das gleiche Schema, um das Event der FragmentActivity zu vermitteln und etwas Interessantes zu machen.

Also, was ist das Problem? Für meine Bewerbung habe ich dieses Schema gefunden, dass Fragments die FragmentActivity zurückrufen und dann die FragmentActivity ein neues Fragment erstellen oder an das vorhandene Fragment sehr umständlich weiterleiten. Ich habe viele Fragmente, die von der FragmentActivity angezeigt werden müssen und deshalb implementiere ich eine Schnittstelle für jede Art von Fragment, die angezeigt werden muss (jedes Fragment ist anders, so dass sie jeweils ihre eigene Schnittstelle haben). Dies verursacht Zusammenstöße, wenn ich zwei Schnittstellen habe, die die gleichen Methoden-Signaturen haben und ich bin gezwungen, eine der Methoden umzubenennen.

Zum Beispiel, wenn ich einen Hörer an ein Fragment mit der onAttach () – Methode des Fragments anhängen möchte, dann muss meine FragmentActivity die Schnittstelle implementieren. Ich habe mehrere Fälle gefunden, wo ich Rückruf-Methoden, die den gleichen Namen haben (oder ich bin gezwungen, nennen sie etwas ähnliches, aber anders wegen einer Namespace-Kollision). Eine Lösung hierfür wäre, eine anonyme Klassen als Rückruf zu verwenden, anstatt die FragmentActivity die Schnittstelle zu implementieren. Dies scheint gut genug zu funktionieren, aber geht gegen das, was die Android-Dokumentation über die Verwendung der onAttach () – Methode zum Setzen des Zuhörers sagt.

Gibt es irgendwelche eleganten Möglichkeiten, sich diesem Problem zu nähern? Es scheint mir der Kompromiss ist, dass du entweder die FragmentActivity zwangst, eine Schnittstelle für jedes Fragment zu implementieren, die du in ihr anzeigen möchtest und das lustige Problem hast, auf die Signaturkollisionen zu achten, oder du gehst gegen die Android-Dokumentation und benutze Anonymous Klassen, um die Rückrufe zu behandeln (nicht sicher von den Implikationen davon).

Ich bin ziemlich neu in Java und fühle mich wie ich könnte fehlen ein Konzept hier, dass mein Problem lösen würde. Kann jemand mich so einstellen, wie man dieses Problem elegant löst?

  • Ersetzen Sie Fragment in einem ViewPager
  • Wie benutzt man Dialog Fragment? (ShowDialog veraltet) Android
  • Android Navigation Schublade mit Aktivitäten umgesetzt
  • Wann man Android-Fragmente von Hand anhängen / lösen soll?
  • Wie lade ich YouTubePlayer mit YouTubePlayerFragment in einem anderen Fragment ein? (Android)
  • ViewPager mit verschachtelten Fragmenten?
  • Binde Service zu Aktivität oder Fragment?
  • Wie zeigt man Soft-Tastatur perfekt in Fragment in Android?
  • 2 Solutions collect form web for “Android verwaltet Fragmente von der Aktivität elegant”

    Ich verstehe Ihr Problem, seit ich es schon lange beschäftigte. Hier ist die Lösung, die ich gerade kam! Es kann einige Modifikationen auf der Grundlage Ihrer Notwendigkeit, aber ich es funktioniert gut.

    Zunächst einmal, um die Kommunikation der Veranstaltung einfacher in Ihrer App zu machen, verwenden Sie einen EventBus! Hier ist der bekannteste https://goo.gl/nAEW6 Event Bus ermöglicht es Ihnen, Event von überall zu irgendwo zu senden, ohne sich um die Implementierung von Schnittstellen, Broadcast-Empfängern, Threading usw. zu sorgen.

    Dann füge FragmentOrganizer deiner App hinzu. Es ist eine Basisklasse für alle Ihre Fragment-Organisatoren. Grundsätzlich brauchst du eine für jede Aktivität. Hier ist der Code

    public abstract class FragmentOrganizer { protected FragmentManager fragmentManager; public FragmentOrganizer(FragmentManager fragmentManager) { this.fragmentManager = fragmentManager; openFragment(getInitialFragment()); EventBus.getDefault().register(this); } protected abstract Fragment getInitialFragment(); protected abstract void onEvent(Object event); public abstract boolean handleBackNavigation(); public void freeUpResources(){ EventBus.getDefault().unregister(this); } protected Fragment getOpenFragment(){ String tag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() -1).getName(); return fragmentManager.findFragmentByTag(tag); } protected boolean isFragmentOpen(Fragment fragment){ return isFragmentOpen(fragment, true); } protected boolean isFragmentOpen(Fragment fragment, boolean useArgs){ String fragmentTag = createFragmentTag(fragment, useArgs); if (fragmentManager.getBackStackEntryCount() != 0) { String name = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName(); if(!useArgs) name = name.substring(0, name.indexOf("-")); return name.equals(fragmentTag); } return false; } private String createFragmentTag(Fragment fragment, boolean addArgs) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(fragment.getClass().getSimpleName()); if(addArgs) { stringBuilder.append("-"); if (fragment.getArguments() != null) stringBuilder.append(fragment.getArguments().toString()); } return stringBuilder.toString(); } public void openFragment(Fragment fragment) { if(isFragmentOpen(fragment)) return; String fragmentTag = createFragmentTag(fragment, true); FragmentTransaction transaction = fragmentManager.beginTransaction(); transaction.replace(R.id.activity_main_fragment_container, fragment, fragmentTag); transaction.addToBackStack(fragmentTag).commit(); } } 

    Jetzt müssen Sie Ihren Fragment-Organisator erstellen, der von FragmentOrganizer erbt und 3 benötigte Methoden implementiert. Hier die Probe

     public class MainFragmentOrganizer extends FragmentOrganizer { public MainFragmentOrganizer(FragmentManager fragmentManager) { super(fragmentManager); } @Override protected Fragment getInitialFragment() { return HomeFragment.newInstance(); } @Override public void onEvent(Object event){ if(event instanceof ClickedOnPhotoEvent){ String photoCode = ((ClickedOnPhotoEvent) event).photoCode; openFragment(PhotoFragment.newInstance(photoCode)); } } @Override public boolean handleBackNavigation(){ Fragment fragment = getOpenFragment(); if (fragment instanceof HomeFragment){ return false; } else { fragmentManager.popBackStack(); return true; } } } 

    Und in deiner Aktivität musst du nur deinen FragmentManager insangieren und es die Magie machen lassen!

     fragmentManager = getSupportFragmentManager(); fragmentOrganizer = new MainFragmentOrganizer(getSupportFragmentManager()); @Override public void onBackPressed() { //first let fragment organizer handle back. If it does not activity takes cares of it! if(!fragmentOrganizer.handleBackNavigation()){ finish(); } } @Override protected void onDestroy() { fragmentOrganizer.freeUpResources(); super.onDestroy(); } 

    Es scheint eine Menge Code, aber wie Sie sehen, die meisten der Code in FragmentOrganizer Basisklasse eingekapselt und es macht alle allgemeinen Werke, so dass Sie nur diese Datei von einem Projekt in ein anderes zu kopieren.

    Wie ich schon sagte, ich bin gerade erst mit dieser Lösung gekommen, also kann es nicht perfekt sein. Ich plane, dies in meinem nächsten Projekt zu verwenden, ich hoffe, dass du es tust. Und wenn du es tust, dann schätze ich, wenn du dich doch teilen kannst. Hab viel Spaß

    Ein Kollege von mir kam mit dem, was ich für eine elegante Lösung für dieses Problem halte.

    Denken Sie daran, was wir zu erreichen versuchen, ist ein Weg für Fragmente, um die übergeordnete Aktivität zurückzukehren, ohne dass die Aktivität die Schnittstelle implementiert. Auch müssen wir den Hörer automatisch wieder einstellen können, wenn die Aktivität zerstört und dann neu erstellt wird.

    Aktivitäten haben einen Lebenszyklus Rückruf aufgerufenAttachFragment (Fragment Fragment), die aufgerufen wird, wenn ein Fragment an die Aktivität angehängt wird. So, zum Beispiel, wenn ein neues Fragment innerhalb der Aktivität erstellt wird, wird dies aufgerufen. Es wird auch angerufen, wenn eine Aktivität, die zuvor zerstört wurde, neu erstellt wird. Was Sie tun können, ist eine Schnittstelle oder eine anonyme Klasse, um einen Zuhörer auf das neue Fragment in onAttachFragment wie folgt zu setzen:

     @Override public void onAttachFragment(Fragment fragment) { super.onAttachFragment(fragment); //Determine which fragment this is by checking its tag if(fragment.getTag().contains(TextFrag.FRAG_TAG)){ //set a listener on this fragment using an anonymous class or interface ((TextFrag)fragment).setListener(new TextFragButtonListener() { @Override public void onButtonClicked() { count++; counterTV.setText(String.valueOf(count)); } }); } } 

    Mit dieser Technik können wir die Aktivität vermeiden, die eine Schnittstelle für den Rückruf implementieren muss und somit vermeiden wir keine Namenskonflikte mit unseren Callback-Methoden. Auch wenn die Aktivität zerstört wird, sobald es neu erstellt wird, wird der Hörer automatisch zurückgesetzt, so dass unsere Rückrufe noch funktionieren.

    Es gibt wahrscheinlich viele andere Möglichkeiten, dies zu tun und ich würde gerne hier irgendjemand Kritik an dieser Technik und Vorschläge für alle anderen Techniken.

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.