ViewPager-Fragmente beziehen sich auf denselben RecyclerView und / oder Adapter

Ich habe ein Fragment, das ein RecyclerView enthält, um Ereignisse für einen bestimmten Tag anzuzeigen. Ich benutze einen ViewPager, um die Fragmente in mehrere Tage zu trennen. Ein Fragment für die Ereignisse des Samstag und ein Fragment für die Ereignisse des Sonntags.

Es scheint jedoch, dass beide Fragmente auf dieselbe RecyclerView und / oder Adapter verweisen, da es nur die letzte Registerkarte (in diesem Fall Sonntag) ist, deren Ereignisse angezeigt werden.

  • Wie kann ich eine Variable in eine neue Runnable-Deklaration übergeben?
  • Android View.onDraw () hat immer eine saubere Leinwand
  • Warum die onProgressUpdate () von AsyncTask <> Schnittstelle wird niemals aufgerufen?
  • Wie man die Android Img-Datei unter Linux?
  • Aufzählen von Ordnern und Dateien mit Google Drive SDK V2
  • Android Fragment Griff zurück Taste drücken
  • In meinem konkreten Fall hat der Samstag zwei Veranstaltungen, und Sonntag hat keine Veranstaltungen. Beide Fragmente haben leere RecyclerViews. Um meine Theorie zu bestätigen, dass es durch die letzte Registerkarte verursacht wurde, habe ich das Datum umgestellt. Dies führte dazu, dass beide RecyclerViews zwei Ereignisse hatten (die von Samstag).

    Hier ist der relevante Code für die einzelnen Fragmente:

    public class EventListFragment extends Fragment{ private EventAdapter mEventAdapter; private static final String DATE_ARG = "eventDate"; public static EventListFragment newInstance(LocalDate date){ EventListFragment eventListFragment = new EventListFragment(); Bundle args = new Bundle(); args.putSerializable(DATE_ARG, date); eventListFragment.setArguments(args); return eventListFragment; } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_event_list, container, false); // Setup recyclerview RecyclerView eventRecyclerView = (RecyclerView) view.findViewById(R.id.event_recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); eventRecyclerView.setLayoutManager(layoutManager); // Get date LocalDate eventDate = (LocalDate) getArguments().getSerializable(DATE_ARG); // Set adapter mEventAdapter = new EventAdapter(getActivity(), getEvents(eventDate)); eventRecyclerView.setAdapter(mEventAdapter); return view; } } 

    getEvents() ist nur eine private Funktion, um Ereignisse für ein bestimmtes Datum zurückzugeben. Ich habe den Debugger sowie Unit-Tests verwendet, um zu überprüfen, ob es richtig funktioniert. Der Debugger zeigt, dass es die richtige Liste für jedes Fragment zieht, aber wie ich erklärte, dass sie nicht richtig angezeigt werden.

    Hier ist der relevante Code für das Elternteil Fragment:

     public class EventFragment extends Fragment { @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_event, container, false); // Get and set up viewpager final ViewPager viewPager = (ViewPager) view.findViewById(R.id.event_view_pager); EventFragmentAdapter eventFragmentAdapter = new EventFragmentAdapter(getFragmentManager(), getEventDates()); viewPager.setAdapter(eventFragmentAdapter); // Get and set up tablayout final TabLayout tabLayout = (TabLayout) view.findViewById(R.id.event_tabs); tabLayout.setTabGravity(TabLayout.GRAVITY_FILL); tabLayout.post(new Runnable() { @Override public void run() { tabLayout.setupWithViewPager(viewPager); } }); return view; } } 

    Ähnlich wie die letzte, getEventDates() zieht nur die Daten, die Ereignisse stattfinden. Für Testzwecke im Moment bin ich hart codiert eine zurückgegebene Liste der Daten, da wir unsere Datenbank noch nicht eingerichtet haben. Ich zog diese Methode heraus, weil ich die App in der Lage sein werde, wieder im Jahr 2016 funktionieren zu können, was unterschiedliche Termine haben kann:

     private List<LocalDate> getEventDates(){ List<LocalDate> eventDates = new ArrayList<>(); eventDates.add(new LocalDate(2015, 10, 17)); eventDates.add(new LocalDate(2015, 10, 18)); return eventDates; } 

    Das letzte Bit des relevanten Codes ist für den FragmentStatePagerAdapter, den ich für meinen ViewPager verwende:

     public class EventFragmentAdapter extends FragmentStatePagerAdapter { private List<LocalDate> mEventDates; public EventFragmentAdapter(FragmentManager fragmentManager, List<LocalDate> eventDates){ super(fragmentManager); this.mEventDates = eventDates; } @Override public Fragment getItem(int i) { return EventListFragment.newInstance(mEventDates.get(i)); } @Override public int getCount() { return mEventDates.size(); } @Override public CharSequence getPageTitle(int position) { return mEventDates.get(position).dayOfWeek().getAsText(); } } 

    Irgendwelche Ideen, warum beide Listen immer gleich sind und auf der letzten Registerkarte im ViewPager basieren? Ich nehme an, dass sie irgendwie auf dieselbe RecyclerView oder denselben RecyclerViewAdapter verweisen, aber ich habe keine statischen Felder für die, also bin ich nicht sicher, wie es passiert.

  • Android - Dateianbieter - Berechtigungsverweigerung
  • Finden Sie ein Google Drive Sheet nach Name mit API 4 In Android
  • Android Studio gradle dauert zu lange, um zu bauen
  • Was macht setUseWideViewPort () und setLoadWithOverviewMode () genau?
  • CollapsingToolbarLayout mit einer benutzerdefinierten Ansicht
  • Was ist das String 'volumeName' Argument von MediaStore.Audio.Playlists.Members.getContentUri beziehen sich auf?
  • 3 Solutions collect form web for “ViewPager-Fragmente beziehen sich auf denselben RecyclerView und / oder Adapter”

    Eine lange Jagd und eine anti-climaktische Lösung (wie bei den meisten schwierigen Bugs). Auch ein bisschen unfair seit der Bug ist nicht in den Code gepostet oben, musste ich jagen Sie Ihre Git-Projekt, um es herauszufinden. Der Fehler ist in EventAdapter :

     public class EventAdapter extends RecyclerView.Adapter<EventAdapter.ViewHolder> { private static final List<Event> mEvents; private final Context mContext; public EventAdapter(Context context, List<Event> events){ this.mContext = context; mEvents = events; } ... } 

    mEvents ist statisch! … so ist es über alle Instanzen von mEvents . Dies erklärt den Bug perfekt, da die Updates zuletzt die Werte für alle EventAdapters .

    Es sieht so aus, als mEvents du mEvents statisch gemacht, damit du in deinem ViewHolders zugreifen ViewHolders . Stattdessen kannst du das einzelne Event nur innerhalb des ViewHolder und den gefährlichen statischen Modifikator ViewHolder . Auf der Flip-Side, Hooray für Open Source Projekte!

    Ich habe deinen Code gesehen und ich bin völlig mit Travor einverstanden – du benutzt ein statisches Mitglied, das jedes Mal ersetzt wird, wenn du einen neuen Adapter schaffst (und so bekommst es nur die letzten Seitendaten). Ich habe Ihr Projekt ein wenig geändert, um es richtig zu machen. Werfen Sie einen Blick darauf, hoffe, dass es nützlich sein kann.

    EventFragment: Ersetzen Sie getFragmentManager mit getChildFragmentManager, da Sie EventListFragment benötigen, um von EventFragment Fragment Manager und nicht von der Aktivität Fragment Manager zu behandeln

     public class EventFragment extends Fragment { @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_event, container, false); // Get and set up viewpager final ViewPager viewPager = (ViewPager) view.findViewById(R.id.event_view_pager); EventFragmentAdapter eventFragmentAdapter = new EventFragmentAdapter(getChildFragmentManager(), getEventDates()); viewPager.setAdapter(eventFragmentAdapter); // Get and set up tablayout final TabLayout tabLayout = (TabLayout) view.findViewById(R.id.event_tabs); tabLayout.setTabGravity(TabLayout.GRAVITY_FILL); tabLayout.post(new Runnable() { @Override public void run() { tabLayout.setupWithViewPager(viewPager); } }); return view; } /** * Retrieves the event dates for the hackathon so that the proper events can be displayed. * @return */ private List<LocalDate> getEventDates(){ List<LocalDate> eventDates = new ArrayList<>(); eventDates.add(new LocalDate(2015, 10, 17)); eventDates.add(new LocalDate(2015, 10, 18)); return eventDates; } } 

    EventListFragment – Ich habe die Abfrage geändert, da die sqlite-Abfrage nicht mit meinem Gebietsschema (italienisch) funktioniert

     public class EventListFragment extends Fragment{ private EventAdapter mEventAdapter; private static final String TAG = EventListFragment.class.getSimpleName(); private static final String DATE_ARG = "eventDate"; public static EventListFragment newInstance(LocalDate date){ EventListFragment eventListFragment = new EventListFragment(); Bundle args = new Bundle(); args.putSerializable(DATE_ARG, date); eventListFragment.setArguments(args); return eventListFragment; } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_event_list, container, false); // Setup recyclerview RecyclerView eventRecyclerView = (RecyclerView) view.findViewById(R.id.event_recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); eventRecyclerView.setLayoutManager(layoutManager); // Get date LocalDate eventDate = (LocalDate) getArguments().getSerializable(DATE_ARG); // Set adapter mEventAdapter = new EventAdapter(getEvents(eventDate)); eventRecyclerView.setAdapter(mEventAdapter); Log.v(TAG, eventRecyclerView.toString()); return view; } /** * Retrieves the events for the given date for the fragment. */ private List<Event> getEvents(LocalDate date){ List<Event> returnList = new ArrayList<>(); String dateString = Utility.getDBDateString(date); List<String> dateList = new ArrayList<>(); Cursor cursor = getActivity().getContentResolver().query( GHContract.EventEntry.CONTENT_URI, new String[]{ "*", "substr(" + GHContract.EventEntry.COLUMN_TIME + ",0,11)" }, "substr(" + GHContract.EventEntry.COLUMN_TIME + ",0,11) = ? ", new String[]{dateString}, GHContract.EventEntry.COLUMN_TIME ); while(cursor.moveToNext()){ returnList.add(new Event(cursor)); dateList.add(cursor.getString(cursor.getColumnIndex(GHContract.EventEntry.COLUMN_TIME))); } cursor.close(); return returnList; } } 

    EventAdapter – entfernt das statische Schlüsselwort und den Verweis auf den Aktivitätskontext (Sie müssen den Kontext irgendwo anders erhalten)

     public class EventAdapter extends RecyclerView.Adapter<EventAdapter.ViewHolder> { private List<Event> mEvents; public EventAdapter(List<Event> events){ mEvents = events; } /** * Inflates the view for Event items. */ @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_event, parent, false); return new ViewHolder(view); } /** * Binds the data for an event to its view. */ @Override public void onBindViewHolder(ViewHolder holder, int position) { Event event = mEvents.get(position); holder.timeView.setText(Utility.getTimeString(event.getTime())); holder.titleView.setText(event.getTitle()); holder.locationView.setText(event.getLocation()); // If reminder time is not null, show check mark. If it is, show plus. if(event.getReminderTime() != null){ holder.alarmView.setImageDrawable(holder.itemView.getResources().getDrawable(R.drawable.ic_alarm_on)); } else{ holder.alarmView.setImageDrawable(holder.itemView.getResources().getDrawable(R.drawable.ic_add_alarm)); } } /** * Returns the size of the adapter. */ @Override public int getItemCount() { return mEvents.size(); } /** * Retains a reference to the view so `findViewById` calls are only made once for the adapter. */ public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ public final TextView timeView; public final TextView titleView; public final TextView locationView; public final ImageView alarmView; public ViewHolder(View view){ super(view); timeView = (TextView) view.findViewById(R.id.event_time); titleView = (TextView) view.findViewById(R.id.event_title); locationView = (TextView) view.findViewById(R.id.event_location); alarmView = (ImageView) view.findViewById(R.id.event_add_reminder); alarmView.setOnClickListener(this); } /** * Handles the click a user makes on the alarm image view. */ @Override public void onClick(View v) { OnEventReminderClickListener activity = (OnEventReminderClickListener) v.getContext(); activity.onEventReminderClicked(mEvents.get(getPosition())); } } /** * Interface to call back to the activity when an alarm is clicked for an event item. */ public interface OnEventReminderClickListener{ void onEventReminderClicked(Event event); } } 

    Und schließlich die app / build.gradle, da musst du die gleiche Version für alle Support-Bibliotheken (Recycler, Karte und so weiter)

     apply plugin: 'com.android.application' android { compileSdkVersion 22 buildToolsVersion "22.0.1" defaultConfig { applicationId "com.adammcneilly.grizzhacks" minSdkVersion 15 targetSdkVersion 22 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.2.1' compile 'joda-time:joda-time:2.7' compile 'com.android.support:recyclerview-v7:22.2.1' compile 'com.android.support:cardview-v7:22.2.1' compile 'com.android.support:design:22.2.1' } 

    Könnten Sie das versuchen?

     public class EventFragmentAdapter extends FragmentStatePagerAdapter { private List<LocalDate> mEventDates; private List<EventListFragment> mFragments; public EventFragmentAdapter(FragmentManager fragmentManager, List<LocalDate> eventDates){ super(fragmentManager); this.mEventDates = eventDates; this.mFragments = new ArrayList<>; for (LocalDate date : this.mEventDates) { this.mFragments.add(EventListFragment.newInstance(date)); } } @Override public Fragment getItem(int i) { return mFragments.get(i); } @Override public int getCount() { return mEventDates.size(); } @Override public CharSequence getPageTitle(int position) { return mEventDates.get(position).dayOfWeek().getAsText(); } } 

    Dann kontrollierst du in jedes Element von mFragents, wenn sie den erwarteten Inhalt haben.

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