I am working on a tasks app, for which I created a list view that shows list items consitsting of task names, their priority etc. The data given to the list view is from an sqlite database. I, however, am unable to add more than one item to the list. I have no idea why. I have created a method to do so, but it doesn’t seem to work. I don’t know if the error is due to the database or my method itself. Even debugging didn’t help. Please note that I am using a list adapter since I am using a custom listview.
Code for Activity where list is shown :
package com.example.taskmasterv3; import androidx.appcompat.app.AppCompatActivity; import android.content.Context; import android.database.Cursor; import android.os.Bundle; import android.view.LayoutInflater; import android.widget.ListView; import android.widget.TextView; import java.util.ArrayList; public class TaskSummary extends AppCompatActivity { ListView lvTaskList; TextView tvBreak, tvBreakAfterEvery, txt1, txt2, text1, hmm; TextView break_duration_mins; ArrayList<SubtaskPartTwo> subtaskList = new ArrayList<>(); String subtname; String pri; String time; DBHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_task_summary); lvTaskList = findViewById(R.id.lvTaskList); tvBreak = findViewById(R.id.tvBreak); tvBreakAfterEvery = findViewById(R.id.tvBreakAfterEvery); txt1 = findViewById(R.id.txt1); txt2 = findViewById(R.id.txt2); break_duration_mins = findViewById(R.id.break_duration_mins); text1 = findViewById(R.id.text1); hmm = findViewById(R.id.hmm); dbHelper = new DBHelper(this); subtname = getIntent().getStringExtra("subtaskname"); pri = getIntent().getStringExtra("pri"); time = getIntent().getStringExtra("time"); // Using adapter for listview : SubtaskDetailAdapter adapter = new SubtaskDetailAdapter(this, subtaskList); lvTaskList.setAdapter(adapter); SubtaskPartTwo subtaskPartTwo = new SubtaskPartTwo(subtname, pri, time); subtaskList.add(subtaskPartTwo); adapter.addANewSubTask(subtaskPartTwo); double working_hours = getIntent().getIntExtra("working_hours", 1); double working_minutes = getIntent().getIntExtra("working_minutes", 0); double without_break_hours = getIntent().getIntExtra("without_break_hours", 1); double without_break_minutes = getIntent().getIntExtra("without_break_minutes", 0); double break_duration = getIntent().getIntExtra("break_duration", 20); String a = working_hours + " h"; txt1.setText(a); String b = working_minutes + " m"; break_duration_mins.setText(b); String c = break_duration + " m"; txt2.setText(c); //Mathematics double g = working_hours * 100; double h = g + working_minutes; double i = h + break_duration; double j = i / 60; double p = (int) j; double q = j - p; double r = q * 60; without_break_hours = p; without_break_minutes = r; String d = without_break_hours + " h"; String e = without_break_minutes + " m"; text1.setText(d); hmm.setText(e); } }
Code for Adapter Class :
package com.example.taskmasterv3; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.util.ArrayList; public class SubtaskDetailAdapter extends ArrayAdapter<SubtaskPartTwo> { private final Context context; private ArrayList<SubtaskPartTwo> values; public boolean deleted; public SubtaskDetailAdapter(Context context, ArrayList<SubtaskPartTwo> list) { //since your are using custom view,pass zero and inflate the custom view by overriding getview super(context, 0 , list); this.context = context; this.values = list; } @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { //check if its null, if so inflate it, else simply reuse it if (convertView == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.task_summary_item, parent, false); } //use convertView to refer the childviews to populate it with data TextView tvSubtaskName = convertView.findViewById(R.id.tvlolitaskname); ImageView ivPri = convertView.findViewById(R.id.ivloliPri); ImageView ivTime = convertView.findViewById(R.id.ivloliTime); tvSubtaskName.setText(values.get(position).getSubtaskName()); if (values.get(position).getPri() == "h") { ivPri.setImageResource(R.drawable.priority_high); } if (values.get(position).getPri() == "m") { ivPri.setImageResource(R.drawable.priority_med); } if (values.get(position).getPri() == "l") { ivPri.setImageResource(R.drawable.priority_low); } if (values.get(position).getTime() == "more") { ivPri.setImageResource(R.drawable.time_symbol_more); } if (values.get(position).getPri() == "med") { ivPri.setImageResource(R.drawable.time_symbol_med); } if (values.get(position).getPri() == "less") { ivPri.setImageResource(R.drawable.time_symbol_less); } //return the view you inflated return convertView; } //to keep adding the new subtasks try the following public void addANewSubTask(SubtaskPartTwo newSubTask){ ArrayList<SubtaskPartTwo> newvalues = new ArrayList<>(this.values); newvalues.add(newSubTask); this.values = newvalues; notifyDataSetChanged(); } }
XML code for listview activity :
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/parent" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/background" tools:context=".TaskSummary"> <!-- hello --> <ScrollView android:id="@+id/scrollView2" android:layout_width="wrap_content" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:id="@+id/okay" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="16dp" android:orientation="vertical"> <ListView android:id="@+id/lvTaskList" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="16dp"> </ListView> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="horizontal"> <TextView android:id="@+id/tvBreak" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="8dp" android:fontFamily="@font/roboto" android:text="Total Working Time (Including Breaks)" android:textColor="#B8AEAE" android:textSize="20sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:orientation="horizontal"> <TextView android:id="@+id/txt1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="8dp" android:layout_weight="1" android:fontFamily="@font/roboto" android:gravity="right" android:text="00 h" android:textColor="#B8AEAE" android:textSize="20sp" /> <TextView android:id="@+id/break_duration_mins" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="8dp" android:layout_marginRight="8dp" android:layout_marginBottom="8dp" android:layout_weight="1" android:gravity="left" android:text="20 m" android:textColor="#B8AEAE" android:textSize="20sp" /> </LinearLayout> </LinearLayout> <!-- hello --> <!-- hello --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="16dp" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="horizontal"> <TextView android:id="@+id/tvWorktimeWithoutBreak" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="8dp" android:fontFamily="@font/roboto" android:text="Work Time Before Each Break" android:textColor="#B8AEAE" android:textSize="20sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:orientation="horizontal"> <TextView android:id="@+id/text1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="8dp" android:layout_weight="1" android:fontFamily="@font/roboto" android:gravity="right" android:text="00 h" android:textColor="#B8AEAE" android:textSize="20sp" /> <TextView android:id="@+id/hmm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="8dp" android:layout_marginRight="8dp" android:layout_marginBottom="8dp" android:layout_weight="1" android:gravity="left" android:text="20 m" android:textColor="#B8AEAE" android:textSize="20sp" /> </LinearLayout> </LinearLayout> </LinearLayout> <!-- hello --> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:id="@+id/tvBreakAfterEvery" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginTop="8dp" android:layout_marginRight="8dp" android:layout_marginBottom="8dp" android:fontFamily="@font/roboto" android:text="Break Duration" android:textColor="#B8AEAE" android:textSize="20sp" app:layout_constraintBottom_toTopOf="@+id/lvTaskList" app:layout_constraintEnd_toStartOf="@+id/lvTaskList" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/txt2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:fontFamily="@font/roboto" android:gravity="center_horizontal" android:text="30 m" android:textColor="#B8AEAE" android:textSize="20sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <Button android:id="@+id/btnStart" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|center_horizontal" android:layout_margin="16dp" android:text="Start" /> </LinearLayout> </LinearLayout> </LinearLayout> </ScrollView> </androidx.constraintlayout.widget.ConstraintLayout>
EDIT : Database Code
package com.example.taskmasterv3; public class TaskInfo extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_task_info); tvTaskName = findViewById(R.id.tvTaskName); btnProceed = findViewById(R.id.btnProceed); dbHelper = new DBHelper(this); tvTaskName.setVisibility(View.INVISIBLE); if (tvTaskName.getText().equals("")) { tvTaskName.setClickable(false); } else { tvTaskName.setClickable(true); } btnSaveTaskName.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { tvTaskName.setVisibility(View.VISIBLE); tvTaskName.setText(etTaskName.getText().toString().toUpperCase().trim()); etTaskName.setVisibility(View.GONE); btnSaveTaskName.setVisibility(View.GONE); btnNewSubtask.setEnabled(true); } }); tvTaskName.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String tasksname = tvTaskName.getText().toString().trim(); tvTaskName.setText(""); etTaskName.setVisibility(View.VISIBLE); etTaskName.setText(tasksname); btnSaveTaskName.setVisibility(View.VISIBLE); } }); btnNewSubtask.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent i2 = new Intent(TaskInfo.this, SubtaskActivity.class); startActivityForResult(i2, ENTER_SUBTASK); overridePendingTransition(R.anim.slide_in_up, R.anim.slide_out_up); } }); // THE DATABASE PART btnProceed.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Cursor res = dbHelper.getdata(); while(res != null && res.moveToNext()){ subtname = res.getString(0); pri = res.getString(1); time = res.getString(2); } if (etWorkingHours.getText().toString().isEmpty()) { etWorkingHours.setText("0"); } if (etWorkingMinutes.getText().toString().isEmpty()) { etWorkingMinutes.setText("0"); } if (etWorkinghrs.getText().toString().isEmpty()) { etWorkinghrs.setText("0"); } if (etWorkingMins.getText().toString().isEmpty()) { etWorkingMins.setText("0"); } int working_hours = Integer.parseInt(etWorkinghrs.getText().toString().trim()); int working_minutes = Integer.parseInt(etWorkingMins.getText().toString().trim()); int without_break_hours = Integer.parseInt(etWorkingHours.getText().toString().trim()); int without_break_minutes = Integer.parseInt(etWorkingMinutes.getText().toString().trim()); if (etWorkingHours.getText().toString().isEmpty() || etWorkingMinutes.getText().toString().isEmpty() || etWorkinghrs.getText().toString().isEmpty() || etWorkingMins.getText().toString().isEmpty()) { Toast.makeText(TaskInfo.this, "Field cannot be empty, please try again.", Toast.LENGTH_SHORT).show(); } else { if (working_hours != 0) { if (working_hours > without_break_hours) { int breaktime = Integer.parseInt(tvBreakTime.getText().toString()); Intent intent = new Intent(TaskInfo.this, TaskSummary.class); intent.putExtra("working_hours", working_hours); intent.putExtra("working_minutes", working_minutes); intent.putExtra("without_break_hours", without_break_hours); intent.putExtra("without_break_minutes", without_break_minutes); intent.putExtra("break_duration", breaktime); intent.putExtra("subtaskname", taskName); intent.putExtra("priigh", NpriHigh); intent.putExtra("primed", NpriMed); intent.putExtra("prilow", NpriLow); intent.putExtra("timemore", NtimeMore); intent.putExtra("timemed", NtimeMed); intent.putExtra("timeless", NtimeLess); startActivity(intent); } if (working_hours == without_break_hours){ if (working_minutes >= without_break_minutes){ int breaktime = Integer.parseInt(tvBreakTime.getText().toString()); Intent intent = new Intent(TaskInfo.this, TaskSummary.class); intent.putExtra("working_hours", working_hours); intent.putExtra("working_minutes", working_minutes); intent.putExtra("without_break_hours", without_break_hours); intent.putExtra("without_break_minutes", without_break_minutes); intent.putExtra("break_duration", breaktime); intent.putExtra("subtaskname", taskName); intent.putExtra("priigh", NpriHigh); intent.putExtra("primed", NpriMed); intent.putExtra("prilow", NpriLow); intent.putExtra("timemore", NtimeMore); intent.putExtra("timemed", NtimeMed); intent.putExtra("timeless", NtimeLess); intent.putExtra("subtaskname", subtname); intent.putExtra("pri", pri); intent.putExtra("time", time); startActivity(intent); } if (working_minutes < without_break_minutes){ Toast.makeText(TaskInfo.this, "Invalid Time Entered", Toast.LENGTH_SHORT).show(); } } if (working_hours < without_break_hours){ Toast.makeText(TaskInfo.this, "Invalid Time Entered", Toast.LENGTH_SHORT).show(); } } if (working_hours == 0){ if (without_break_hours == 0) { if (working_minutes >= without_break_minutes){ int breaktime = Integer.parseInt(tvBreakTime.getText().toString()); Intent intent = new Intent(TaskInfo.this, TaskSummary.class); intent.putExtra("working_hours", working_hours); intent.putExtra("working_minutes", working_minutes); intent.putExtra("without_break_hours", without_break_hours); intent.putExtra("without_break_minutes", without_break_minutes); intent.putExtra("break_duration", breaktime); intent.putExtra("subtaskname", taskName); intent.putExtra("prihigh", NpriHigh); intent.putExtra("primed", NpriMed); intent.putExtra("prilow", NpriLow); intent.putExtra("timemore", NtimeMore); intent.putExtra("timemed", NtimeMed); intent.putExtra("timeless", NtimeLess); startActivity(intent); } if (working_minutes < without_break_minutes){ Toast.makeText(TaskInfo.this, "Invalid Time Entered", Toast.LENGTH_SHORT).show(); } } if (without_break_hours != 0) { Toast.makeText(TaskInfo.this, "Invalid Time Entered", Toast.LENGTH_SHORT).show(); } } } } }); boolean delete = getIntent().getBooleanExtra("deleted", false); if (delete){ } } } } }
Advertisement
Answer
The problem is that you’re creating a new ArrayList
while the adapter is left using the old one. That’s why notifyDataSetChanged()
doesn’t work because the adapter’s backing list has not changed.
To fix this, update the values
list directly
public void addANewSubTask(SubtaskPartTwo newSubTask) { this.values.add(newSubTask); notifyDataSetChanged(); }
or, add()
through the adapter itself.
public void addANewSubTask(SubtaskPartTwo newSubTask) { add(newSubTask); notifyDataSetChanged(); }
Even if I add one item, it shows 2 (both the same)
It seems you’re adding the new element twice:
SubtaskPartTwo subtaskPartTwo = new SubtaskPartTwo(subtname, pri, time); subtaskList.add(subtaskPartTwo); adapter.addANewSubTask(subtaskPartTwo);
Just add via adapter only as it notifies as well. Check other places too for such duplicates.