0

Also das Wichtigste zuerst, hier ist der Fehler, ich bin immer:PagerAdapter Adapter Inhalt geändert mit Benachrichtigung

java.lang.IllegalStateException: Die PagerAdapter Anwendung verändert den Inhalt des Adapters ohne Aufruf PagerAdapter # notifyDataSetChanged! Erwartete Adapter Artikel Zahl: 18, gefunden: 28

Ich bin ein RecyclerView in meiner Haupttätigkeit verwenden und dass ein List<Objects> als Datenbestand hat, das ist alles in Ordnung.

Von dieser Tätigkeit ich die zweite Aktivität aufrufen, wenn ein RecyclerView Element, das angeklickt wird, ist im Grunde eine Galerie ein ViewPager mit diesem Code implementiert:

public void startSlideActivity(final int position) { 
    DataTransferer.get().storeItems(feed); 

    Intent i = new Intent(context, SlideActivity.class); 
    ... 
    i.putExtra("POSITION", position); 
    context.startActivity(i); 
} 

Meine Daten sind zu groß, um durch eine Absicht zu übertragen (unter Verwendung von Parcel oder auf andere Weise), so bin ich ein Singleton mit meiner Liste zu halten und zu übertragen, hier ist der Code:

public class DataTransferer { 

    private static volatile DataTransferer singleton; 

    private List<Thing> items; 

    public static DataTransferer get(){ 
    if (singleton == null) { 
     synchronized (DataTransferer.class) { 
     singleton = new DataTransferer(); 
     } 
    } 
    return singleton; 
    } 

    private DataTransferer(){ 
    } 

    public void storeItems(List<Thing> items){ 
    this.items = items; 
    } 

    public List<Thing> getStoredItems(){ 
    return items; 
    } 
} 

In der zweiten Aktivität ich den Adapter setzen und rufen Sie die Liste wie folgt:

feed = DataTransferer.get().getStoredItems(); 
final int position = this.getIntent().getIntExtra("POSITION", 0); 
adapter = new FeedPagerAdapter(SlideActivity.this, feed); 
viewPager.setAdapter(adapter); 
adapter.notifyDataSetChanged(); 
viewPager.setCurrentItem(position); 
viewPager.setOffscreenPageLimit(4); 

Und schließlich ist hier in meinem PagerAdapter Code:

public class FeedPagerAdapter extends PagerAdapter { 
    @BindView(R.id.item_image_view) ImageView image; 

    private final SlideActivity host; 
    private List<Thing> items; 

    public FeedPagerAdapter(SlideActivity host, List<Thing> items){ 
    this.host = host; 
    this.items = items; 
    notifyDataSetChanged(); 
    } 

    @Override 
    public Object instantiateItem(ViewGroup parent, int position) { 
    View view = LayoutInflater.from(host).inflate(R.layout.item, parent, false); 
    ButterKnife.bind(this, view); 
    ... 
    parent.addView(view); 
    return view; 
    } 

    @Override 
    public int getCount() { 
    return items.size(); 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
    container.removeView((View)object); 
    } 

    @Override 
    public boolean isViewFromObject(View view, Object object) { 
    return view == object; 
    } 
} 

Ich habe versucht, auch die Datenmenge in onResume und und getItemCount im Adapter benachrichtigen, die gleiche Problem.

Zurück zur Hauptaktivität werden diese Daten über das Netzwerk geladen und Elemente zur Liste hinzugefügt, wenn der Ladevorgang abgeschlossen ist. Wenn ich meine Anwendung starte und auf das Element klicke, sobald sie anfangen, den RecyclerView zu füllen, öffnet sich die zweite Aktivität und ich bekomme den Absturz. Wenn ich die App starte und eine Sekunde lang auf ein RecyclerView-Element klicke, funktioniert es wie gewünscht.

Wenn jemand irgendwelche Vorschläge hat, wie ich warten kann, um sicher zu stellen, dass die Liste stabil ist, wenn ich die zweite Aktivität starte, oder eine bessere Möglichkeit, eine gitterbasierte RecyclerView-Galerie zu implementieren, um ein Viewpager-Layout mit dem gleichen Datensatz zu öffnen bin dankbar.

Antwort

0

Es ist, weil Sie diese Linie verwenden viewPager.setOffscreenPageLimit(4);, Es ist meine Viewpager wird nicht den Bildschirm in allen 4 Seiten neu erstellen. Es gibt jedoch eine Funktion, mit der Sie feststellen können, ob Ihr Bildschirm vollständig sichtbar ist. Rufen Sie an: setUserVisibleHint(). Sie müssen nur wie unten verwenden: // Für das Fragment Fall

@Override 
    public void setUserVisibleHint(boolean isVisibleToUser) { 
     if (isVisibleToUser) { 
     //TODO notify your recyclerview data over here 
     } 
    } 

EDIT:

Für den Aktivitätsfall: Wenn API-Ebene 14 oder über Targeting kann man

verwenden

android.app.Application.ActivityLifecycleCallbacks

public class MyApplication extends Application implements ActivityLifecycleCallbacks { 
    private static boolean isInterestingActivityVisible; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 

     // Register to be notified of activity state changes 
     registerActivityLifecycleCallbacks(this); 
     .... 
    } 

    public boolean isInterestingActivityVisible() { 
     return isInterestingActivityVisible; 
    } 

    @Override 
    public void onActivityResumed(Activity activity) { 
     if (activity instanceof MyInterestingActivity) { 
      isInterestingActivityVisible = true; 
     } 
    } 

    @Override 
    public void onActivityStopped(Activity activity) { 
     if (activity instanceof MyInterestingActivity) { 
      isInterestingActivityVisible = false; 
     } 
    } 

    // Other state change callback stubs 
    .... 
} 

Registrieren Sie Ihre Anwendungsklasse in AndroidManifest.xml:

<application 
     android:name="your.app.package.MyApplication" 
     android:icon="@drawable/icon" 
     android:label="@string/app_name" > 

hinzufügen onPause und onResume zu jeder Aktivität im Projekt:

@Override 
protected void onResume() { 
    super.onResume(); 
    MyApplication.activityResumed(); 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    MyApplication.activityPaused(); 
} 

In Ihrer finish() Methode, mögen Sie isActivityVisible() verwenden zu überprüfen, ob die Aktivität sichtbar oder nicht. Dort können Sie auch prüfen, ob der Benutzer eine Option ausgewählt hat oder nicht. Fahren Sie fort, wenn beide Bedingungen erfüllt sind.

+0

Und diese Methode gehört zu welcher Klasse? Keine der Klassen, die ich erwähnt habe, überschreibt diese Methode. (Bearbeiten: Google sagt, es ist mit einem Fragment verbunden, ich verwende kein Fragment irgendwo) – rycirese

+0

@rycirese Was ist der Typ der Klasse in Ihrem Viewpager Bildschirm? Normalerweise verwende ich diese Methode für mein 'Fragment'. Und Ihr Sound klingt, als ob Sie 'Activity' verwenden würden. – TranHieu

+0

Richtig, All diese Aktivität ist, ist ein Viewpager. – rycirese

Verwandte Themen