5

gedreht wurde. Ich habe einen RecyclerView innerhalb eines AppCompatActivity. Artikeleinfügungen und -änderungen werden nach dem Drehen des Geräts korrekt angezeigt und animiert.RecyclerView wird nicht aktualisiert, nachdem das Gerät mit einem geöffneten DialogFragment

Das Problem tritt auf, wenn Sie:

  1. Tippen Sie auf ein Element in der RecyclerView.
  2. Eine DialogFragment öffnet die Abfrage, wenn Sie das Element löschen möchten.
  3. Drehen Sie das Gerät.
  4. Bestätigen Sie das Löschen im Dialog.
  5. Überprüfen Sie die Array-Liste. Der Artikel wurde gelöscht.
  6. Die RecyclerView zeigt immer noch das Element.

Versuchte notifyDataSetChanged statt notifyItemRemoved verwenden, aber hat nicht funktioniert entweder, weil das Element noch in der RecyclerView gezeigt werden wird.

Dies geschieht mit jeder Version von Android.

Vereinfachte Code, wie der Prozess gehandhabt wird:

public class MyAppCompatActivity extends AppCompatActivity { 
     int positionOfDeletedItem; 
     MyObjectRecyclerViewAdapter adapter; 
     ArrayList<MyObject> someTestData; 
     MyItemDeletionHandler deletionHandlerRemover; 

     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.my_activity_layout); 

      RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); 
      positionOfDeletedItem = 1; 
      deletionHandlerRemover = new MyItemDeletionHandler(this); 

      someTestData = new ArrayList<MyObject>(3); 
      someTestData.add(new MyObject("A")); 
      someTestData.add(new MyObject("B")); 
      someTestData.add(new MyObject("C")); 

      recyclerView.setHasFixedSize(true); 
      recyclerView.setLayoutManager(new LinearLayoutManager(this)); 

      adapter = new MyObjectRecyclerViewAdapter(new MyAdapterOnClickEvent.OnItemClick() { 
       @Override 
       public void onClick(int posicion, int idViaje, View view) { 
        String tag = "Some tag value"; 
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
        Fragment prev = getSupportFragmentManager().findFragmentByTag(tag); 
        if(prev != null) 
         ft.remove(prev); 
        ft.addToBackStack(null); 
        DialogFragment newFragment = MyDeletionConfirmationDialog.newInstance(deletionHandlerRemover); 
        newFragment.show(ft, tag); 
       } 
      }, someTestData); 
      recyclerView.setAdapter(adapter); 
     } 

     private final static class MyItemDeletionHandler extends Handler { 
      private final WeakReference<MyAppCompatActivity> theActivity; 

      private MyItemDeletionHandler(MyAppCompatActivity act) { 
       theActivity = new WeakReference<MyAppCompatActivity>(act); 
      } 
      @Override 
      public void handleMessage(Message msg) { 
       MyAppCompatActivity activity = theActivity.get(); 
       if(activity != null) { 
        if(msg.what == 1) { 
         activity.deleteTheItem(); 
        } 
       } 
      } 
     } 

     public void deleteTheItem() { 
      someTestData.remove(positionOfDeletedItem); 
      adapter.notifyItemRemoved(positionOfDeletedItem); 
     } 
} 





public class MyDeletionConfirmationDialog extends DialogFragment { 
    private Message handlerMessage; 

    public static MyDeletionConfirmationDialog newInstance(Handler callbackHandler) { 
     MyDeletionConfirmationDialog myDialog = new MyDeletionConfirmationDialog(); 

     Bundle args = new Bundle(); 
     args.putParcelable("handlerMessage", callbackHandler.obtainMessage(1, true)); 
     myDialog.setArguments(args); 

     return myDialog; 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     handlerMessage = getArguments().getParcelable("handlerMessage"); 
    } 

    @Override 
    @NonNull 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); 

     alertDialogBuilder.setMessage("Some message"); 
     alertDialogBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int id) { 
       final Message toSend = Message.obtain(handlerMessage); 
       toSend.sendToTarget(); 
      } 
     }); 
     alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialog, int which) { 
       dialog.dismiss(); 
      } 
     }); 
     Dialog dialog = alertDialogBuilder.create(); 
     dialog.setCanceledOnTouchOutside(true); 
     return dialog; 
    } 
} 

Wie kann ich die RecyclerView richtig zu arbeiten?


Edit 1:

Ich habe andere RecyclerView s, in denen diese korrekt funktioniert. Der einzige Unterschied ist, dass diese innerhalb Fragment s statt AppCompatActivity sind. Ich vermute, dass dies etwas mit den Ereignissen onDetachedFromWindow und onAttachedToWindow der RecyclerView zu tun hat.


Edit 2:

Wenn der Dialog geschlossen wird (Schritt 4) und wieder geöffnet es funktioniert wie erwartet.


bearbeiten 3:

Wenn die RecyclerView als Fragment extrahiert wird das Problem verschwindet und wie vorgesehen funktioniert. Es ist unmöglich, den oben beschriebenen Anwendungsfall in Verbindung mit AppCompatActivity anstelle einer Fragment korrekt zu behandeln.

+0

Wenn Sie auf den Dialog klicken, sollte er verschwinden und das Element in der Liste löschen. Wie kommt es, dass der Dialog bleibt, wenn Sie die Ausrichtung ändern und die Daten löschen? –

+0

@ReazMurshed Der Anwendungsfall ist folgender: Sie klicken auf ein Element, um es zu löschen. Es zeigt einen Bestätigungsdialog mit den Optionen ('Abbrechen' und 'Löschen'). Sie klicken auf keine der Optionen. Sie drehen das Gerät. Der Dialog ist noch offen. Sie wählen dann die Option "Löschen", um den Artikel zu löschen. Der Dialog wird geschlossen. Der Artikel wurde aus der Datenbank gelöscht. Das 'RecyclerView' wird nicht entsprechend aktualisiert, es zeigt immer noch das gelöschte Element an. – OneEyeQuestion

+0

Dies ist keine richtige Lösung, aber auf jeden Fall kann dieser Hack den Trick machen, den Sie wollen. Sie können die Orientierungsänderung leicht in 'onConfigurationChange' erkennen und den auf dem Bildschirm angezeigten Dialog schließen. Der auf dem Bildschirm angezeigte Dialog bezieht sich nicht auf den Aktivitäts-/Fragmentlebenszyklus und deshalb bleibt er auf dem Bildschirm. –

Antwort

0

Ich hatte ein ähnliches Problem mit RecyclerView. Wenn ich nach links wischte, um ein Element zu löschen und dann den Bildschirm zu drehen, wurde das Objekt aus meinem Dataset entfernt, aber der Bildschirm war nicht so erfrischend, wie es normalerweise der Fall ist, wenn wir die gleiche Aktion ausführen. Es scheint, dass die adaptar.notifyItemRemoved() den Bildschirm überhaupt nicht aktualisiert hat.

Ich verwende den Quellcode Nemanja Kovacevic als Ausgangspunkt, aber ich habe einige Änderungen daran (wie Hinzufügen von Element klicken, bearbeiten mit einem Dialogfeld, Datenbankunterstützung, etc).

Also las ich diese post, die mir einen Hinweis gab, was könnte schief gehen. Es scheint, dass die adapter.notify immer noch auf die vorherige Adapterreferenz vor der Rotation zeigt. Jedes Mal, wenn wir einen neuen Adapter drehen, an der Aktivität erstellt: OnCreate

public class MainActivity extends AppCompatActivity 
    implements NavigationView.OnNavigationItemSelectedListener, 
    AddAlertDialog.OnAlertSavedListener, 
    AlertListAdapter.OnItemDeletedListener { 

    static ListAdapter mListAdapter; 
    RecyclerView mRecyclerView; 
    ... 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    ... 
    mRecyclerView = (RecyclerView) findViewById(R.id.mainListView); 
    mDB = new DatabaseTable(this); 

    // Reading all alerts 
    ArrayList<Alert> alerts = mDB.getAllAlerts(); 

    if (mListAdapter == null) 
     mListAdapter = new ListAdapter(this, alerts); 
    } 
} 

Vielleicht ist es nicht ideal ist (zur Schaffung von statischen Objekten ist keine gute Idee), aber es hat das Problem gelöst.

Ich hoffe, dass es Ihnen auch helfen kann.