5

我在AppCompatActivity内有RecyclerView。在旋转设备后,会显示项目插入和更改并正确动画。使用打开的DialogFragment旋转设备后,RecyclerView不刷新

问题发生在你:对在RecyclerView项目

  1. 点击。
  2. A DialogFragment打开提示,如果你想删除该项目。
  3. 旋转设备。
  4. 确认对话框中的删除。
  5. 检查数组列表。该项目已被删除。
  6. RecyclerView仍显示该项目。

使用notifyDataSetChanged代替notifyItemRemoved试过,但没有工作,要么是因为仍在于RecyclerView所示的项目。

任何版本的Android都会发生这种情况。

简化的过程如何被处理的代码:

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; 
    } 
} 

我怎样才能获得RecyclerView正常工作?


编辑1:

我有其他RecyclerView S IN此工作正常。唯一的区别是在Fragment s之内,而不是AppCompatActivity。我怀疑这与RecyclerView的事件onDetachedFromWindowonAttachedToWindow有关。


编辑2:

如果对话框被关闭(步骤4),并再次打开它按预期工作。


编辑3:

如果RecyclerView被提取为Fragment问题消失,按预期工作。上述用例与AppCompatActivity而不是Fragment一起正确工作是不可能的。

+0

当你点击对话框时,它应该消失并删除列表中的项目。那么当您更改方向并删除数据时,对话如何保留? –

+0

@ReazMurshed用例如下:单击一个项目将其删除。它显示一个确认对话框('取消'和'删除')。您不要点击任何选项。您旋转设备。该对话框仍然打开。然后选择“删除”选项删除该项目。对话框关闭。该项目已从数据库中删除。 'RecyclerView'没有相应更新,它仍然显示已删除的项目。 – OneEyeQuestion

+0

这不是一个合适的解决方案,但无论如何,这个黑客可以做你想要的伎俩。 您可以在'onConfigurationChange'中轻松检测方向变化,并可以关闭屏幕上显示的对话框。 屏幕上显示的对话与活动/片段生命周期无关,因此它仍然保留在屏幕上。 –

回答

0

我正面临着RecyclerView的类似问题。 当我向左滑动以删除一个项目然后旋转屏幕时,该项目已从我的数据集中移除,但是屏幕没有像我们在不旋转的情况下执行相同操作时的正常操作那样刷新。似乎adaptar.notifyItemRemoved()根本不刷新屏幕。我使用Nemanja Kovacevic源代码作为起点,但我做了一些更改(如添加项目单击,编辑对话框,数据库支持等)。

所以我读了这个post,这给了我一个关于什么可能会出错的暗示。 看起来adapter.notify在旋转之前仍然指向先前的适配器引用。我们每次旋转一个新的适配器的时间是在活动创建:在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); 
    } 
} 

也许这是不理想(创建静态对象是不是一个好主意),但它解决了这个问题。

我希望它也可以帮助你。