getitemcount() 值在片段重新启动之前不会更新
Posted
技术标签:
【中文标题】getitemcount() 值在片段重新启动之前不会更新【英文标题】:getitemcount() value not updating until the fragment is restarted 【发布时间】:2020-07-12 11:36:18 【问题描述】:我的自定义适配器,当我添加一个任务时,getitemcount() 值不会增加,除非它重新启动应用程序或在片段之间切换。并且 itemtouchelper 也不会更新 UI,除非我也为此执行相同的步骤。我正在使用 activityresult 方法来更新适配器。
public class CustomAdapterReminders extends RecyclerView.Adapter<CustomAdapterReminders.MyRecyclerView2> implements ItemMoveCallback.ItemTouchHelperContractReminder
private List<String[]> customListView;
private String[] mRecentlyDeletedItem;
private int mRecentlyDeletedItemPosition;
private View snackbarView;
private static final String dueDatedTime = "Due on: ";
private Context context;
public int positionAfterNewTAsk;
public void setPositionAfterNewTAsk(int positionAfterNewTAsk)
this.positionAfterNewTAsk = positionAfterNewTAsk;
public CustomAdapterReminders(List<String[]> customListView)
this.customListView = customListView;
Log.d("Item count" , String.valueOf(getItemCount()));
public CustomAdapterReminders()
@NonNull
@Override
public MyRecyclerView2 onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(R.layout.recycler_item_reminders,parent,false);
MyRecyclerView2 viewHolder = new MyRecyclerView2(itemView);
snackbarView = parent.getRootView();
return viewHolder;
@Override
public void onBindViewHolder(@NonNull MyRecyclerView2 holder, int position)
String[] temp = customListView.get(position);
holder.taskText.setText(temp[1]);
holder.taskDate.setText(dueDatedTime + temp[2]);
public void changeData()
notifyDataSetChanged();
@Override
public int getItemCount()
return customListView.size();
@Override
public void onRowMoved(int fromPosition, int toPosition)
try
if (fromPosition < toPosition)
for (int i = fromPosition; i < toPosition; i++)
Collections.swap(customListView, i, i + 1);
else
for (int i = fromPosition; i > toPosition; i--)
Collections.swap(customListView, i, i - 1);
notifyItemMoved(fromPosition, toPosition);
catch (Exception ex)
Log.d("TAG", "Error in moving items");
@Override
public void onRowSelected(MyRecyclerView2 myViewHolder)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
myViewHolder.rowView.setBackgroundResource(R.drawable.border);
@Override
public void onItemDismiss(int position)
Log.d("Position", String.valueOf(position) +"Count"+ String.valueOf(getItemCount()) + "Pos" + positionAfterNewTAsk);
String[] deleteIndex = customListView.get(position);
mRecentlyDeletedItemPosition = position;
mRecentlyDeletedItem = customListView.get(position);
customListView.remove(position);
TaskDBHelper taskDBHelper = new TaskDBHelper(context);
final Handler handler = new Handler();
showUndoSnackbar();
handler.postDelayed(() -> taskDBHelper.DeleteFromReminders(deleteIndex[0]), 3000);
notifyItemRemoved(position);
notifyItemRangeChanged(position,getItemCount());
positionAfterNewTAsk = 0;
@Override
public void onRowClear(MyRecyclerView2 myViewHolder)
myViewHolder.rowView.setBackgroundResource(R.drawable.seleted_border);
private void undoDelete()
customListView.add(mRecentlyDeletedItemPosition,
mRecentlyDeletedItem);
notifyItemInserted(mRecentlyDeletedItemPosition);
notifyItemRangeChanged(mRecentlyDeletedItemPosition,getItemCount());
private void showUndoSnackbar()
Snackbar.make(snackbarView, "Task deleted", Snackbar.LENGTH_LONG)
.setAction("Undo", v -> undoDelete()).show();
public class MyRecyclerView2 extends RecyclerView.ViewHolder
TextView taskText, taskDate;
View rowView;
private MyRecyclerView2(@NonNull View itemView)
super(itemView);
rowView = itemView;
taskText = itemView.findViewById(R.id.reminderstextView);
taskDate = itemView.findViewById(R.id.remindersDateView);
> **
-
在 recyclerview 上设置适配器的 Home Fragment
**
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
remindersViewModel = ViewModelProviders.of(this).get(RemindersViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
OneSignal.startInit(this.getContext())
.inFocusDisplaying(OneSignal.OSInFocusDisplayOption.Notification)
.unsubscribeWhenNotificationsAreDisabled(true)
.init();
OneSignal.startInit(this.getContext())
.setNotificationReceivedHandler(new ExampleNotificationReceivedHandler())
.inFocusDisplaying(OneSignal.OSInFocusDisplayOption.Notification)
.unsubscribeWhenNotificationsAreDisabled(true)
.init();
setAdapter();
FloatingActionButton fab = root.findViewById(R.id.floatingActionButton);
fab.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
Intent addTask = new Intent(getActivity(), AddTask.class);
startActivityForResult(addTask,ADD_TASK);
);
return root;
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data)
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1)
refreshUI();
@Override
public void onResume()
super.onResume();
setAdapter();
private void refreshUI()
setAdapter();
adapter.changeData();
private void setAdapter()
try
taskDBHelper = new TaskDBHelper(this.getContext());
try
taskList = taskDBHelper.browseReminders();
adapter = new CustomAdapterReminders(taskList);
catch (Exception e)
Log.d(TAG, "Exception in browsing");
staggaggeredGridLayoutManager = new StaggeredGridLayoutManager(2, 1);
recyclerViewItems = getActivity().findViewById(R.id.rv);
recyclerViewItems.setLayoutManager(staggaggeredGridLayoutManager);
recyclerViewItems.setAdapter(adapter);
adapter.changeData();
ItemMoveCallback itemMoveCallback = new ItemMoveCallback();
ItemTouchHelper.Callback callback = new ItemMoveCallback(adapter);
touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(recyclerViewItems);
catch (NullPointerException ex)
Log.d(TAG, "Exception in setAdapter");
@Override
public void requestDrag(RecyclerView.ViewHolder viewHolder)
touchHelper.startDrag(viewHolder);
【问题讨论】:
您似乎在另一个名为 addTask 的活动中将任务添加到 recyclerview 中,您尚未在代码中发布该活动。我还没有看到您将任务转换为字符串并将其添加到 customListView 的部分,这是一个字符串数组列表,也许您在添加任务后没有这样做 在那个活动中,我将任务字符串直接存储到数据库中(AddTask 在这里自行完成),并且 onActivityResult 再次调用 setAdapter ,它正在浏览数据库并填充 List我想我可能知道问题出在哪里,但由于我还没有看到 addTask 类,所以目前只能猜测。 数据库操作通常是异步的,即不在主线程上完成,所以基本上当 onActivityResult 被调用时,不能保证 addTask 中的进程在您读取数据时已完成将数据插入数据库。
一个简单的解决方法是重新排列代码的工作方式。您现在正在做的是用户决定添加一个任务,然后您将一些数据添加到数据库中(在 Addtask 中)然后您读取数据库中的内容并使用它使用 setAdapter 方法完全重置适配器。
当用户决定添加任务时,将相应的String[]
对象直接馈入customListView
并调用通知数据集更改。同时你执行一个命令将相同的数据插入到数据库中。
因为您是从主线程修改适配器,所以所有事情都会按顺序发生,您不会冒在插入操作发生之前读取数据库的风险。
另一种选择是您使用 Room 框架使用 LiveData 和 onChanged 侦听器来处理您的数据库。这意味着阅读文献需要付出很多努力,但是房间框架确实可以为您提供很多简化代码的功能
【讨论】:
非常感谢您的帮助,它终于使用 OnResume 并使用 setter 更新适配器列表,然后调用 notifyDataSetChange()。以上是关于getitemcount() 值在片段重新启动之前不会更新的主要内容,如果未能解决你的问题,请参考以下文章
Enmap (better-sqlite map) 在应用程序重新启动之前不会更新
当我们在android中使用backstack返回上一个片段时,上一个片段正在重新启动
sh Unbounce脚本片段,用于在零停机时间内重新启动HAProxy