Значение getitemcount () не обновляется, пока фрагмент не будет перезапущен - PullRequest
0 голосов
/ 31 марта 2020

Мой пользовательский адаптер, когда я добавляю задачу, значение getitemcount () не увеличивается до тех пор, пока оно не перезапустит приложение или не переключится между фрагментами. и ни один предмет не обновляет пользовательский интерфейс, если я не сделаю те же шаги для этого тоже. Я использую метод Resultresult для обновления адаптера.

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


> **
  1. Домашний фрагмент, в котором для адаптера задано представление переработчика

**

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

1 Ответ

1 голос
/ 31 марта 2020

Я думаю, что могу знать, где проблема, но на данный момент это предположение, так как я не видел класс addTask. Операции с БД обычно асинхронны, то есть не выполняются в основном потоке, поэтому в основном при вызове onActivityResult не гарантируется, что процесс внутри addTask завершит вставку данных в БД в тот момент, когда вы ее читаете.

a простое исправление - просто изменить способ работы вашего кода. то, что вы делаете сейчас, - это то, что пользователь решает добавить задачу, затем вы добавляете некоторые данные в БД (в Addtask), затем читаете, что в БД, и используете это для полного сброса адаптера с помощью метода setAdapter.

вместо этого, когда пользователь решает добавить фид задач соответствующего объекта String[] непосредственно в customListView и вызвать notify набор данных. в то же время вы выполняете команду для вставки этих же данных в БД.

, поскольку вы изменяете адаптер из основного потока, только все будет происходить последовательно, и вы не рискуете прочитать БД до того, как Произошла операция вставки.

другая альтернатива заключается в том, что вы используете каркас Room для обработки вашей базы данных с использованием LiveData и прослушивателя onChanged. Это подразумевает много усилий по чтению литературы, но структура комнаты действительно предложит вам многое, чтобы упростить ваш код

...