【发布时间】:2017-07-01 06:55:38
【问题描述】:
我在AppCompatActivity 中有一个RecyclerView。旋转设备后,项目插入和更改会正确显示和动画。
问题发生在您:
- 点击
RecyclerView中的项目。 -
DialogFragment会打开提示您是否要删除该项目。 - 旋转设备。
- 在对话框中确认删除。
- 检查阵列列表。该项目已被删除。
-
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:
我还有其他RecyclerViews 可以正常工作。唯一的区别是那些在Fragments 里面而不是AppCompatActivity。我怀疑这与RecyclerView 的onDetachedFromWindow 和onAttachedToWindow 事件有关。
编辑 2:
如果对话框已关闭(第 4 步)并再次打开,它将按预期工作。
编辑 3:
如果RecyclerView 被提取为Fragment,问题就会消失并按预期工作。上述用例与AppCompatActivity 而不是Fragment 一起正常工作是不可能的。
【问题讨论】:
-
当您单击对话框时,它应该会消失并删除列表中的项目。那么,当您更改方向并删除数据时,对话框怎么会保留?
-
@ReazMurshed 用例如下:单击一个项目将其删除。它显示带有选项(“取消”和“删除”)的确认对话框。您无需单击任何选项。你旋转设备。对话框仍然打开。然后您选择“删除”选项来删除该项目。对话框关闭。该项目已从数据库中删除。
RecyclerView没有相应更新,它仍然显示已删除的项目。 -
这不是一个合适的解决方案,但无论如何,这个黑客可以做你想要的伎俩。您可以在
onConfigurationChange中轻松检测到方向变化,并且可以关闭屏幕上显示的对话。屏幕上显示的对话框与活动/片段生命周期无关,这就是它保留在屏幕上的原因。 -
@ReazMurshed 但我希望对话框保留。我不希望用户不得不再次重新打开对话框。此外,我还有其他
RecyclerViews遵循相同的用例并且工作正常。这只是让我感到困惑。我会用一些我认为可能导致问题的假设来更新我的问题。 -
@OneEyeQuestion 这是您的实际代码吗?
MyItemDeletionHandler不应按书面形式编译。它是一个静态内部类,因此它不应访问MyAppCompatActivity的实例成员。
标签: android android-recyclerview notifydatasetchanged orientation-changes