I'm trying to build a simple To Do List app using a RecyclerView with a custom Adapter. I've build a model data class to get and set my todos. My problem is that each time I click the button to add my item, nothing happens. I did call notifyDataSetChanged() method but it still doesn't work.
This is a practice app that I'm building to learn RecyclerViews and custom adapters so I'd appreciate it if someone could explain why it doesn't work and perhaps explain to me how I can fix it.
This is my code where I'm retrieving the user input from the EditText field and placing it in my data:
public class MainActivity extends AppCompatActivity {
private ToDoData toDoData;
private List<ToDoData> toDoList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ToDoAdapter toDoAdapter = new ToDoAdapter(toDoList, this);
toDoData = new ToDoData(this);
final EditText toDoInput = (EditText)findViewById(R.id.add_todo);
Button toDoAdd = (Button)findViewById(R.id.add_item);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
RecyclerView toDoDisplay = (RecyclerView) findViewById(R.id.toDoDisplayRecyclerView);
toDoDisplay.setAdapter(toDoAdapter);
toDoDisplay.setHasFixedSize(true);
toDoDisplay.setLayoutManager(layoutManager);
toDoAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
toDoData.setToDo(toDoInput.getText().toString());
toDoAdapter.notifyDataSetChanged();
}
});
}
}
This is my model class with getters and setters. The list-item has only 1 field so its rather small:
public class ToDoData {
private String toDoString;
public ToDoData(String todoString){
this.toDoString = todoString;
}
public ToDoData(Context context){}
public String getToDo() {
return toDoString;
}
public void setToDo(String toDoString) {
this.toDoString = toDoString;
}
}
And this is my custom adapter. I followed through a tutorial while building this but I do however think that my problem stems from the adapter:
public class ToDoAdapter extends RecyclerView.Adapter<ToDoAdapter.ViewHolder> {
private List<ToDoData> toDoList;
private Context context;
public ToDoAdapter(List<ToDoData> todoList, Context context) {
this.toDoList = todoList;
this.context = context;
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView todoView;
public ViewHolder(View itemView) {
super(itemView);
todoView = (TextView) itemView.findViewById(R.id.to_do_display);
}
}
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.to_do_list_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
ToDoData todo = toDoList.get(position);
holder.todoView.setText(todo.getToDo());
}
#Override
public int getItemCount() {
return (toDoList == null) ? 0 : toDoList.size();
}
}
Add one setter method in your adapter class for setting the collection and then invoke notifyDataSetChanged.
Declare the ToDoAdapter as class member and then invoke the setter function on Button click as follows,
adapter.setTodoList(/* pass collection */);
adapter.notifyDataSetchanged();
Related
Is it all possible to access an adapter's data via another adapter?
I want to start an activity and pass data from an adapter to a fragment which is used in TabLayout as one of three fragments, I have two adapters and a button which is clicked to start an activity, its Java code is in my first adapter and I need to pass second adapter's data via second adapter itself
here is my codes:
my first adapter:
public class RecyclerViewDataAdapter extends RecyclerView.Adapter<RecyclerViewDataAdapter.ItemRowHolder>{
private ArrayList<SectionDataModel> dataList;
private Context mContext;
private RecyclerView.RecycledViewPool recycledViewPool;
private SnapHelper snapHelper;
public RecyclerViewDataAdapter(ArrayList<SectionDataModel> dataList, Context mContext) {
this.dataList = dataList;
this.mContext = mContext;
recycledViewPool = new RecyclerView.RecycledViewPool();
}
#Override
public ItemRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, null);
ItemRowHolder rowHolder = new ItemRowHolder(v);
snapHelper = new GravitySnapHelper(Gravity.START);
return rowHolder;
}
#Override
public void onBindViewHolder(ItemRowHolder holder, int position) {
ArrayList singleSectionItems = dataList.get(position).getAllItemInSection();
final String sectionName = dataList.get(position).getHeaderTitle();
holder.itemTitle.setText(sectionName);
SectionDataAdapter adapter = new SectionDataAdapter(singleSectionItems, mContext);
holder.recyclerView.setHasFixedSize(true);
holder.recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
holder.recyclerView.setAdapter(adapter);
holder.recyclerView.setRecycledViewPool(recycledViewPool);
snapHelper.attachToRecyclerView(holder.recyclerView);
holder.btnMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//here i can start the activity but..(second adapter)
Toast.makeText(view.getContext(), sectionName, Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return (null != dataList ? dataList.size() : 0);
}
public class ItemRowHolder extends RecyclerView.ViewHolder {
protected ImageView mitemImage;
protected TextView mitemtext;
protected TextView itemTitle;
protected RecyclerView recyclerView;
protected Button btnMore;
public ItemRowHolder(View itemView) {
super(itemView);
this.mitemImage = itemView.findViewById(R.id.itemImage);
this.mitemtext = itemView.findViewById(R.id.tvTitle);
this.itemTitle = itemView.findViewById(R.id.itemTitle);
this.recyclerView = itemView.findViewById(R.id.recycler_view_list);
this.btnMore = itemView.findViewById(R.id.btnMore);
}
}
} '
and my second adapter:
import java.net.PortUnreachableException;
import java.util.ArrayList;
public class SectionDataAdapter extends RecyclerView.Adapter<SectionDataAdapter.SssingleItemRowHolder>{
private ArrayList<SingleItemModel> itemModels;
private Context mContext;
public SectionDataAdapter(ArrayList<SingleItemModel> itemModels, Context mContext) {
this.itemModels = itemModels;
this.mContext = mContext;
}
#Override
public SingleItemRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_single_card, null);
SingleItemRowHolder singleItemRowHolder = new SingleItemRowHolder(v);
return singleItemRowHolder;
}
#Override
public void onBindViewHolder(SingleItemRowHolder holder, int position) {
SingleItemModel itemModel = itemModels.get(position);
holder.tvTitle.setText(itemModel.getName());
holder.mitemImage.setImageResource(itemModel.getImage());
}
#Override
public int getItemCount() {
return (null != itemModels ? itemModels.size() : 0);
}
public class SingleItemRowHolder extends RecyclerView.ViewHolder {
protected TextView tvTitle;
protected ImageView mitemImage;
public SingleItemRowHolder(View itemView) {
super(itemView);
final Intent intent = new Intent(mContext,MainActivity.class);
this.mitemImage = itemView.findViewById(R.id.itemImage);
this.tvTitle = itemView.findViewById(R.id.tvTitle);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//... need to start the activity from here
Toast.makeText(view.getContext(), tvTitle.getText(), Toast.LENGTH_SHORT).show();
}
});
}
}
Like #MilaDroid said you simply need a getter that returns the another Adapter's ArrayList<SingleItemModel> but the problem you will face is that you need to have the same instance of the Adapter from the Activity in order to get the populated ArrayList<SingleItemModel>.
A good workaround is to used Bill Pugh's Singleton in the Adapter
public class Adapter {
private ArrayList<SingleItemModel> list;
private Adapter() {}
public static Adapter getInstance() {
return InstInit.INSTANCE;
}
// Don't forget to set the list (or NPE)
// because we can't argue with a Singleton
public void setList(ArrayList<SingleItemModel> list) {
this.list = list;
}
// You can now get the ArrayList
public ArrayList<SingleItemModel> getList() {
return list;
}
private static class InstInit {
private static final Adapter INSTANCE = new Adapter();
}
// Overrided RecyclerView.Adapter Methods
.................
}
Retrieving the ArrayList assuming that the following Adapters are Singleton
AdapterOne a1 = AdapterOne.getInstance();
AdapterTwo a2 = AdapterTwo.getInstance();
ArrayList<SingleItemModel> a1RetrievedList = a1.getList();
// You don't need to create a new instance
// creating a new instance doesn't make sense
// because you need to repopulate the list
// for the new instance.
ArrayList<SingleItemModel> a2RetrievedList = a2.getList();
// You can also retrieve from AdapterTwo
I have this code in MainActivity
public class MainActivity extends AppCompatActivity implements MainViewInterface{
RecyclerView rvMovies;
private String TAG = "MainActivity";
MoviesAdapter adapter;
MainPresenter mainPresenter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupMVP();
mainPresenter.getMovies();
rvMovies = (RecyclerView)findViewById(R.id.rvMovies);
LinearLayoutManager manager = new LinearLayoutManager(this);
manager.setOrientation(LinearLayoutManager.VERTICAL);
rvMovies.setLayoutManager(manager);
//rvMovies.setHasFixedSize(true);
}
private void setupMVP() {
mainPresenter = new MainPresenter(this);
}
#Override
public void showToast(String s) {
Toast.makeText(MainActivity.this,s,Toast.LENGTH_LONG).show();
}
#Override
public void displayMovies(MovieResponse moviesResponse) {
if(moviesResponse!=null) {
Log.d(TAG,moviesResponse.getResults().get(1).getTitle());
adapter = new MoviesAdapter(moviesResponse.getResults(), MainActivity.this);
rvMovies.setAdapter(adapter);
adapter.notifyDataSetChanged();
}else{
Log.d(TAG,"Movies response null");
}
}
#Override
public void displayError(String s) {
showToast(s);
}
}
But I get this
E/RecyclerView: No adapter attached; skipping layout
I know other people asked the same question. I tried their solutions but didn't work. What am I missing?
This is my adapter code.
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MoviesHolder> {
List<Result> movieList;
Context context;
public MoviesAdapter(List<Result> movieList, Context context){
this.movieList = movieList;
this.context = context;
}
#Override
public MoviesHolder onCreateViewHolder( ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.row_movies,parent,false);
MoviesHolder mh = new MoviesHolder(v);
return mh;
}
#Override
public void onBindViewHolder( MoviesHolder holder, int position) {
holder.tvTitle.setText(movieList.get(position).getTitle());
holder.tvOverview.setText(movieList.get(position).getOverview());
holder.tvReleaseDate.setText(movieList.get(position).getReleaseDate());
Glide.with(context).load("https://image.tmdb.org/t/p/w500/"+movieList.get(position).getPosterPath()).into(holder.ivMovie);
}
#Override
public int getItemCount() {
return movieList.size();
}
public class MoviesHolder extends RecyclerView.ViewHolder {
TextView tvTitle,tvOverview,tvReleaseDate;
ImageView ivMovie;
public MoviesHolder(View itemView) {
super(itemView);
tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
tvOverview = (TextView) itemView.findViewById(R.id.tvOverView);
tvReleaseDate = (TextView) itemView.findViewById(R.id.tvReleaseDate);
ivMovie = (ImageView) itemView.findViewById(R.id.ivMovie);
}
}
Thanks,
Theo.
SOLVED
In my activivity_main.xml I had both height and with equal to 0dp!!! I honestly don't know how and who put those values in!! That's why the recycler view was not visible!!!
I think you should call rvMovies.setAdapter(new MoviesAdapter(new ArrayList<>())) on your RecyclerView during onCreate - there is nothing bad about setting an empty (from items perspective) adapter on RecyclerView, it will simply show an empty list. Then once you have your data ready (downloaded/loaded from any source you are loading from) you will simply call something like adapter.setItems(newItemsList) and adapter.notifyDataSetChanged().
Also one more note: you should not store Context in class member fields as leaks might occur (I am pretty sure your Android Studio must complain about that as well in a form of a Lint Warning check). You actually don't even need that Context instance passing to your adapter as you can simply retrieve a Context instance from parent View in onCreateViewHolder - rewrite it like this:
#Override
public MoviesHolder onCreateViewHolder( ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_movies,parent,false);
MoviesHolder mh = new MoviesHolder(v);
return mh;
}
These 2 lines:
setupMVP();
mainPresenter.getMovies();
must be written after:
rvMovies = (RecyclerView)findViewById(R.id.rvMovies);
you need to set adapter after you set the views.
rvMovies = (RecyclerView)findViewById(R.id.rvMovies);
LinearLayoutManager manager = new LinearLayoutManager(this);
manager.setOrientation(LinearLayoutManager.VERTICAL);
rvMovies.setLayoutManager(manager);
//rvMovies.setHasFixedSize(true);
//call after setting the view
mainPresenter.getMovies();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupMVP();
rvMovies = (RecyclerView)findViewById(R.id.rvMovies);
LinearLayoutManager manager = new LinearLayoutManager(this);
manager.setOrientation(LinearLayoutManager.VERTICAL);
rvMovies.setLayoutManager(manager);
rvMovies.setVisibility(View.VISIBLE);
mainPresenter.getMovies(); <== put this line in last
}
I have an Android To-do list app with SQLite database accessed using Room. Then I wanted to make a list of available lists in navigation drawer. So I used Paging Library. Now the RecyclerView is empty and I don't know why. BTW: none of my lists work. I am a beginner, so I stick to the official tutorial. I've already found out, that they are wrong and that ViewModel needs an empty constructor. Now the situation looks like this: the method, that sets up the adapter is called successfully (8), ViewModel is created (7) Adapter is created (1), the setList() method is called (9), but no Holder is being created (4), no onCreateViewHolder or onBindViewHolder are called (2,3), no DiffCalback methods are called (5,6) and just an empty Recycler view is displayed. The PagedList<SQLList> contains right information, but no information is being passed to the adapter. Has anybody any idea why?
//Sorry for my English.
Adapter class:
//this is my Adapter. SQLList is my object (Equivalent to the User object in
the tutorial)
public class ListsAdapter extends PagedListAdapter<SQLList,ListsAdapter.Holder> {
private Context context;
public ListsAdapter(Context context) {
//1
super(DIFF_CALLBACK);
this.context = context;
}
#Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
//2
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.list_item,null);
return new Holder(view);
}
#Override
public void onBindViewHolder(Holder holder, int position) {
//3
SQLList item = getItem(position);
if (item == null){
holder.clear();
}else {
holder.bindTo(item);
}
}
public static class Holder extends RecyclerView.ViewHolder {
public TextView textView;
public int id;
public TextView idView;
public Holder(View itemView) {
//4
super(itemView);
textView = itemView.findViewById(R.id.textView);
idView = itemView.findViewById(R.id.idTextView);
}
public void bindTo(SQLList list) {
textView.setText(list.getName());
id = list.getId();
idView.setText(Integer.toString(list.getId()));
}
public void clear() {
textView.setText("");
id = 0;
idView.setText("0");
}
}
private static final DiffCallback<SQLList> DIFF_CALLBACK = new DiffCallback<SQLList>() {
#Override
public boolean areItemsTheSame(#NonNull SQLList oldItem, #NonNull SQLList newItem) {
//5
return oldItem.getId() == newItem.getId();
}
#Override
public boolean areContentsTheSame(#NonNull SQLList oldItem, #NonNull SQLList newItem) {
//6
return oldItem.getName().equals(newItem.getName());
}
};
}
View Model:
public static class ListViewModel extends ViewModel {
public final LiveData<PagedList<SQLList>> listsList;
public ListViewModel(){
//7
listsList = new LivePagedListBuilder<>(DMO.getDao().loadListFactory(),20).build();
}
}
Part of Fragment the RecyclerView is placed in:
...
//8
ListViewModel listViewModel = ViewModelProviders.of(this).get(ListViewModel.class);
adapter = new ListsAdapter(context);
listViewModel.listsList.observe(this, new Observer<PagedList<SQLList>>() {
#Override
public void onChanged(#Nullable PagedList<SQLList> sqlLists) {
//9
adapter.setList(sqlLists);
}
});
recyclerView.setAdapter(adapter);
...
Problem found: I forgot to set layout manager!
I had the same problem but I accidentally added-
RecyclerView.setHasFixedSize(true);
After removing this, It worked.
Same issue I had and I just removed RecyclerView.setHasFixedSize(true) then it started working fine.
I had to set the adapter. recyclerView.setAdapter(adapter);
In my MainActivity I have something like this:
recyclerAdapter = new RecyclerAdapter(this, arrayList);
recyclerView.setAdapter(recyclerAdapter);
To update my RecyclerView, I do: (in MainActivity, too)
Item item = new Item();
item.setId(id);
item.setMessage(message);
arrayList.set(position, item);
recyclerAdapter.notifyItemChanged(position);
I want to have a button within every RecyclerView list item which can enable/disable the current entry. Therefore I need to get the current toggle state.
My problem is, how can I update the RecyclerView in MainActivity from within my ViewHolder?
RecyclerView.ViewHolder:
public class SetViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{//, View.OnLongClickListener{
public ImageView toggle;
public SetViewHolder(View itemView){
super(itemView);
toggle = (ImageView) itemView.findViewById(R.id.img_main_card_toggle);
toggle.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v.getId() == toggle.getId()) {
int clicked_position = getAdapterPosition();
//TODO update Item of RecyclerView of MainActivity
}
}
My Recycler.Adapter:
public class RulesAdapter extends RecyclerView.Adapter<SetViewHolder>{
private Activity activity;
List<Item> items = Collections.emptyList();
private OnTapListener onTapListener;
public RulesAdapter(Activity activity, List<Item> items){
this.activity = activity;
this.items = items;
}
#Override
public SetViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rules_list_item,parent,false);
return new SetViewHolder(view);
}
#Override
public void onBindViewHolder(SetViewHolder holder, final int position) {
holder.recevied_message.setText(items.get(position).getReceived_message());
holder.reply_message.setText(items.get(position).getReply_message());
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(onTapListener != null){
onTapListener.OnTapView(position);
}
}
});
}
#Override
public int getItemCount() {
return items.size();
}
public void setOnTapListener(OnTapListener onTapListener){
this.onTapListener = onTapListener;
}
}
Define an Interface.
public interface OnRecyclerItemToggleClickListener {
void onToggleClick(int adapterPosition);
}
Implement this in your adapter. And pass the adapter instance to the ViewHolder through a setter method in the onCreateViewHolder callback.
public class SetViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{//, View.OnLongClickListener{
public ImageView toggle;
private OnRecyclerItemToggleClickListener listener;
public SetViewHolder(View itemView){
super(itemView);
toggle = (ImageView)
itemView.findViewById(R.id.img_main_card_toggle);
toggle.setOnClickListener(this);
}
public void setRecyclerItemToggleClickListener( OnRecyclerItemToggleClickListener listener) {
this.listener = listener;
}
#Override
public void onClick(View v) {
if (v.getId() == toggle.getId()) {
int clicked_position = getAdapterPosition();
//TODO update Item of RecyclerView of MainActivity
listener.onToggleClick(clicked_position);
}
}
In your adapter:
#Override
public SetViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rules_list_item,parent,false);
SetViewHolder holder = new SetViewHolder(view);
holder.setOnRecyclerItemToggleClickListener(this);
return holder;
}
#Override public void onToggleClick(int adapterPosition) {
// you will get the callback here when the toggle button is clicked.
// you can update the ArrayList here.
// Or similarly, call an interface method to Activity.
}
And call this onToggleClick method from ViewHolder when the toggle is clicked. You will get a callback to adapter, where you can update the ArrayList. Otherwise you can have another similar Interface to give callback to Activity from the adapter.
You just have to add a static function and make items static too:
public static ArrayList<Items> getAreayList()
{
return items;
}
And get this function in MainActivity:
onStart()
I'm trying to learn how to use RecyclerViews and the best way to learn is by doing :) so I'm trying to transition from using a ListView in a simple to do list to a Recyclerview. I'm trying to get the String value from the EditText and add that value to my RecyclerView list when the button is clicked. The following are my implementations.
This is my custom adapter. I'm using a ViewHolder to use a basic, single TextView custom list-item.
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder>{
private List<todo> todoList;
public class ViewHolder extends RecyclerView.ViewHolder{
public TextView toDoTextView;
public ViewHolder(View itemView) {
super(itemView);
toDoTextView = (TextView)itemView.findViewById(R.id.to_do);
}
}
public ItemAdapter(List<todo> todoList){
this.todoList = todoList;
}
#Override
public ItemAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(ItemAdapter.ViewHolder holder, int position) {
todo toDo = todoList.get(position);
holder.toDoTextView.setText(toDo.getToDo());
}
#Override
public int getItemCount() {
return todoList.size();
}
}
And this is my MainActivity. This is where I'm going to be adding my EditText values to my RecyclerView List. The implementation is done in the setOnClickListener but it gives me an error.
public class MainActivity extends AppCompatActivity {
private List<todo> items = new ArrayList<>();
private ItemAdapter itemAdapter;
private RecyclerView listItemsRecyclerView;
EditText itemsInput;
Button addingItems;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
itemsInput = (EditText)findViewById(R.id.to_do_editText);
addingItems = (Button)findViewById(R.id.to_do_btn);
listItemsRecyclerView = (RecyclerView) findViewById(R.id.to_do_list);
final String todoItem = String.valueOf(itemsInput.getText());
itemAdapter = new ItemAdapter(items);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
listItemsRecyclerView.setLayoutManager(layoutManager);
listItemsRecyclerView.setItemAnimator(new DefaultItemAnimator());
listItemsRecyclerView.setAdapter(itemAdapter);
addingItems.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(todoItem != null){
items.add(todoItem);
itemsInput.setText("");
}else {
Toast.makeText(MainActivity.this, "Please enter something to do", Toast.LENGTH_SHORT).show();
}
itemAdapter.notifyDataSetChanged();
}
});
This is my todo class:
public class todo {
private String toDo;
public todo(){}
public todo(String somethingToDo){
somethingToDo = toDo;
}
public String getToDo() {
return toDo;
}
public void setToDo(String toDo) {
this.toDo = toDo;
}
}
Modify your code inside if condition inside button OnClickListener
if(todoItem != null){
todo mTodo = new todo(todoItem); //Create object of todo using the input done by user.
items.add(mTodo);
itemsInput.setText("");
}
Also your todo class constructor code is wrong
public todo(String somethingToDo){
//somethingToDo = toDo;
toDo = somethingToDo; //need to assign the value received as signature to the class variable.
}