Todo App - Android

The Todo application uses Suas to add, mark as done, delete and move an item in a to-do list. In our example, the list of todos is represented by a RecyclerView using an implementation of ItemTouchHelper to handle the swipe to delete and drag to move gestures. Also, it uses the TodoListAdapter to bind our State to the views. (Check the Todo application source code on GitHub)

Below is the MainActivity used in our todo application.

public class MainActivity extends AppCompatActivity implements Listener<TodoList>{

    private Store store;
    private TodoListAdapter todoListAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final RecyclerView todoList = findViewById(R.id.list);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        todoList.setLayoutManager(layoutManager);

        todoListAdapter = new TodoListAdapter(new ArrayList<>());
        todoList.setAdapter(todoListAdapter);

        //...

        store = Suas.createStore(new TodoReducer())
                .withMiddleware(monitorMiddleware, loggerMiddleware)
                .withDefaultFilter(Filters.EQUALS)
                .build();

        //...
    }

    @Override
    protected void onStart() {
        super.onStart();
        store.addListener(TodoList.class, this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        store.removeListener(this);
    }

    @Override
    public void update(@NonNull TodoList todoList) {
        todoListAdapter.update(todoList.getItems());
    }
}

The MainActivity first initializes the RecyclerView, TodoListAdapter and Store during onCreate(). Then, it adds itself as a Listener<TodoItem> during onStart() and removes itself during onStop().By doing this, the MainActivity receives all the updates in the update(@NonNull TodoList todoList) method.

All updates to the list happens in the update(@NonNull TodoList todoList) method, when todoListAdapter.update(todoList.getItems()) is called. Then the TodoListAdapter displays the new State:

void update(List<TodoItem> items) {
    this.items.clear();
    this.items.addAll(items);
    notifyDataSetChanged();
}

Different parts of the app dispatch Actions to the Store. Todo items are created by reading the input from the EditText when clicking Add Item.

@Override
public void onClick(View view) {
    String newTitle = newItemInput.getText().toString();
    Action addAction = ActionFactory.addAction(newTitle);
    store.dispatch(addAction);

    newItemInput.setText("");
}

Then, items are marked as done by dispatching toggle Actions to the Store in the ViewHolder.

ViewHolder(View view) {
    super(view);

    titleLabel = view.findViewById(R.id.label);
    checkBox = view.findViewById(R.id.checkbox);

    view.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            Action toggleAction = ActionFactory.toggleAction(getAdapterPosition());
            store.dispatch(toggleAction);
        }
    });
}

All Actions related to gestures are dispatched in the ItemTouchHelper:

ItemTouchHelper itemTouchHelper = new ItemTouchHelper(
        new ItemTouchHelper.SimpleCallback(
                ItemTouchHelper.UP | ItemTouchHelper.DOWN,
                ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {

            @Override
            public boolean isLongPressDragEnabled() {
                return true;
            }

            public boolean onMove(RecyclerView recyclerView,
                    ViewHolder viewHolder, ViewHolder target) {

                final int fromPos = viewHolder.getAdapterPosition();
                final int toPos = target.getAdapterPosition();

                Pair<Integer, Integer> fromToPositions = new Pair<>(fromPos, toPos);
                Action moveAction = ActionFactory.moveAction(fromToPositions);
                store.dispatch(moveAction);

                return true;
            }

            @Override
            public boolean isItemViewSwipeEnabled() {
                return true;
            }

            public void onSwiped(ViewHolder viewHolder, int direction) {
                Action deleteAction = ActionFactory
                        .deleteAction(viewHolder.getAdapterPosition());
                store.dispatch(deleteAction);
            }
        });

What's Next

Todo application source code on GitHub

Learn more about Suas listeners

Suas listeners
Using the StateSelector
Adding a listener with a filter

Other sample apps

List of sample applications
Counter App Example
Todo app with settings example
Search Cities Example