Reputation: 380
My app has a registration screen for blood donors and the blood type field is a spinner. I save all the donor information in an SQLite database. Now I need to retrieve it and show it for a list showing all the registered blood donors with their blood types.
How can I do that?
I've attached all my code below. The main problems appear in RegisterActivity.java and DonorList.java.
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
public class RegisterActivity extends AppCompatActivity {
EditText edtname, edtnumber;
Spinner spblood;
Button btnregister, btnlist;
public static SQLiteHelper sqLiteHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
init();
Spinner spinner = findViewById(R.id.blood_selector);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.blood_type, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
sqLiteHelper = new SQLiteHelper(this, "Donors.sqlite", null, 1);
sqLiteHelper.queryData("CREATE TABLE IF NOT EXISTS DONORS (Id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, number VARCHAR, blood VARCHAR)");
btnregister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
sqLiteHelper.insertData(
edtname.getText().toString().trim(),
edtnumber.getText().toString().trim(),
spblood
);
}
catch (Exception e) {
e.printStackTrace();
}
}
});
btnlist.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(RegisterActivity.this, DonorList.class);
startActivity(intent);
}
});
}
private void init() {
edtname = findViewById(R.id.name_input);
edtnumber = findViewById(R.id.numberinput);
spblood = findViewById(R.id.blood_selector);
btnregister = findViewById(R.id.register_button);
btnlist = findViewById(R.id.list_button);
}
}
import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;
import android.widget.Spinner;
import java.util.ArrayList;
public class DonorList extends AppCompatActivity {
ListView listView;
ArrayList<Donor> list;
DonorListAdapter adapter = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.contacts_list);
list = new ArrayList<>();
adapter = new DonorListAdapter(this, R.layout.activity_main, list);
listView.setAdapter(adapter);
Cursor cursor = RegisterActivity.sqLiteHelper.getData("SELECT * FROM DONORS");
list.clear();
while (cursor.moveToNext()) {
String name = cursor.getString(1);
String number = cursor.getString(2);
String blood = cursor.getString(3);
list.add(new Donor(name, number, blood));
}
adapter.notifyDataSetChanged();
}
}
import android.widget.Spinner;
public class Donor {
private String name;
private String number;
private Spinner blood;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Spinner getBlood() {
return blood;
}
public void setBlood(Spinner blood) {
this.blood = blood;
}
public Donor(String name, String number, Spinner blood) {
this.name = name;
this.number = number;
this.blood = blood;
}
}
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import android.widget.Spinner;
public class SQLiteHelper extends SQLiteOpenHelper {
public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
public void queryData(String sql) {
SQLiteDatabase database = getWritableDatabase();
database.execSQL(sql);
}
public void insertData(String name, String number, Spinner blood) {
SQLiteDatabase database = getWritableDatabase();
String sql = "INSERT INTO DONORS (name, number, blood) values (?, ?, ?)";
SQLiteStatement statement = database.compileStatement(sql);
statement.clearBindings();
statement.bindString(1, name);
statement.bindString(2, number);
statement.bindString(3, blood.getSelectedItem().toString());
statement.executeInsert();
}
public Cursor getData(String sql) {
SQLiteDatabase database = getReadableDatabase();
return database.rawQuery(sql, null);
}
}
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
public class DonorListAdapter extends BaseAdapter {
private Context context;
private int layout;
private ArrayList<Donor> donorList;
public DonorListAdapter(Context context, int layout, ArrayList<Donor> donorList) {
this.context = context;
this.layout = layout;
this.donorList = donorList;
}
@Override
public int getCount() {
return donorList.size();
}
@Override
public Object getItem(int position) {
return donorList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
private class ViewHolder {
TextView txtname, txtnumber, txtblood;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder = new ViewHolder();
if (row == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (inflater != null) {
row = inflater.inflate(layout, null);
}
if (row != null) {
holder.txtname = row.findViewById(R.id.name_input);
}
if (row != null) {
holder.txtnumber = row.findViewById(R.id.numberinput);
}
if (row != null) {
holder.txtblood = (TextView) row.findViewById(R.id.blood_selector);
}
if (row != null) {
row.setTag(holder);
}
}
else {
holder = (ViewHolder) row.getTag();
}
Donor donor = donorList.get(position);
holder.txtname.setText(donor.getName());
holder.txtnumber.setText(donor.getNumber());
holder.txtblood.setText(donor.getBlood().toString());
return row;
}
}
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.lumen.dayem.blooddonor.MainActivity">
<ListView
android:id="@+id/contacts_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:choiceMode="singleChoice">
</ListView>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/name_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/person_name"
android:ems="10"
android:inputType="textCapWords"
android:layout_marginBottom="5sp" />
<EditText
android:id="@+id/numberinput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/hint"
android:ems="10"
android:inputType="phone"
android:layout_marginBottom="5sp" />
<TextView
android:id="@+id/blood"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/blood_type"
android:layout_marginBottom="10sp"/>
<Spinner
android:id="@+id/blood_selector"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/blood_type"
android:prompt="@string/blood_select"
android:layout_marginBottom="5sp"/>
<Button
android:id="@+id/register_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/register" />
<Button
android:id="@+id/list_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/show_donors" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/contact_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/contact_name"
android:textSize="22sp"/>
<TextView
android:id="@+id/contact_number"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="?android:textAppearanceSmall"
android:text="@string/contact_number"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="29sp"
android:layout_marginStart="29sp"
android:layout_marginTop="31sp" />
<TextView
android:id="@+id/contact_blood"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="?android:textAppearanceMedium"
android:text="@string/blood_type"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="300sp"
android:layout_marginStart="300sp"
android:layout_marginTop="30sp"/>
</RelativeLayout>
Upvotes: 0
Views: 70
Reputation: 13009
Your class Donor
seems to have a field blood of type Spinner
. I changed the type to String
because a data class should not contain any View
s:
public class Donor
{
private String name;
private String number;
private String blood;
// Getters and Setters here...
public Donor(String name, String number, String blood) {
this.name = name;
this.number = number;
this.blood = blood;
}
}
The SQLiteHelper
should have a static getInstance()
method so you can avoid having it as a static field in RegisterActivity
. Also, I think that the database setup should be encapsulated. The Activity
does not need to know anything about the database implementation. So I moved the DDL to the SQLiteHelper
's onCreate()
and dropped queryData()
. For the same reason, I changed getData(String sql)
to getDonors()
. Lastly, insertData()
should take data as parameters not View
s. So one should not pass the Spinner
but the selected item's value.
My version of SQLiteHelper.java:
public class SQLiteHelper extends SQLiteOpenHelper{
private static SQLiteHelper sqliteHelper;
private static String dbName = "Donors.sqlite";
private static int version = 1;
private static final String CREATE_TABLE_DONORS = "CREATE TABLE IF NOT EXISTS DONORS (Id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, number VARCHAR, blood VARCHAR)";
/**
* We use the application Context under the hood because this helps to avoid Exceptions
* @param ctx
*/
private SQLiteHelper(Context ctx){
super(ctx.getApplicationContext(), dbName, null, version);
}
/**
* SQLiteHelper as a Singleton
* @param ctx any Context
* @return x
*/
public static SQLiteHelper getInstance(Context ctx)
{
if(sqliteHelper == null){
sqliteHelper = new SQLiteHelper(ctx);
}
return sqliteHelper;
}
@Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(CREATE_TABLE_DONORS);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
// necessary if you have a new database version
}
public void insertData(String name, String number, String blood) {
SQLiteDatabase database = getWritableDatabase();
String sql = "INSERT INTO DONORS (name, number, blood) values (?, ?, ?)";
SQLiteStatement statement = database.compileStatement(sql);
statement.clearBindings();
statement.bindString(1, name);
statement.bindString(2, number);
statement.bindString(3, blood);
statement.executeInsert();
}
public Cursor getDonors() {
String sql = "SELECT * FROM DONORS";
SQLiteDatabase database = getReadableDatabase();
return database.rawQuery(sql, null);
}
}
The updated RegisterActivity.java (note that I got rid of the local variable spinner and only used spblood):
public class RegisterActivity extends AppCompatActivity
{
private EditText edtname, edtnumber;
private Spinner spblood;
private Button btnregister, btnlist;
private SQLiteHelper sqLiteHelper;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
init();
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.blood_type, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spblood.setAdapter(adapter);
sqLiteHelper = SQLiteHelper.getInstance(this);
btnregister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
sqLiteHelper.insertData(
edtname.getText().toString().trim(),
edtnumber.getText().toString().trim(),
spblood.getSelectedItem().toString()
);
}
catch (Exception e) {
e.printStackTrace();
}
}
});
btnlist.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(RegisterActivity.this, DonorList.class);
startActivity(intent);
}
});
}
private void init() {
edtname = findViewById(R.id.name_input);
edtnumber = findViewById(R.id.numberinput);
spblood = findViewById(R.id.blood_selector);
btnregister = findViewById(R.id.register_button);
btnlist = findViewById(R.id.list_button);
}
}
The changes to DonorList
and the Adapter are due to the changes I made to SQLiteHelper
and Donor
. In addition to that, you need to pass the resource id of the list row to the Adapter's Constructor not the resource id of the Activity's layout. Similarly, the R.id.... values for the TextView
s in the list row have to match those in contact_item.xml
DonorList.java
public class DonorList extends AppCompatActivity
{
private ListView listView;
private ArrayList<Donor> list;
private DonorListAdapter adapter = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.contacts_list);
list = new ArrayList<>();
adapter = new DonorListAdapter(this, R.layout.contact_item, list);
listView.setAdapter(adapter);
Cursor cursor = SQLiteHelper.getInstance(this).getDonors();
list.clear();
while (cursor.moveToNext()) {
String name = cursor.getString(1);
String number = cursor.getString(2);
String blood = cursor.getString(3);
list.add(new Donor(name, number, blood));
}
adapter.notifyDataSetChanged();
}
}
And finally, the Adapter:
public class DonorListAdapter extends BaseAdapter
{
private Context context;
private int layout;
private ArrayList<Donor> donorList;
public DonorListAdapter(Context context, int layout, ArrayList<Donor> donorList) {
this.context = context;
this.layout = layout;
this.donorList = donorList;
}
@Override
public int getCount() {
return donorList.size();
}
@Override
public Object getItem(int position) {
return donorList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
private class ViewHolder {
TextView txtname, txtnumber, txtblood;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
ViewHolder holder = new ViewHolder();
row = LayoutInflater.from(context).inflate(layout, null);
holder.txtname = (TextView)row.findViewById(R.id.contact_name);
holder.txtnumber = (TextView)row.findViewById(R.id.contact_number);
holder.txtblood = (TextView) row.findViewById(R.id.contact_blood);
row.setTag(holder);
}
ViewHolder viewHolder = (ViewHolder) row.getTag();
Donor donor = donorList.get(position);
viewHolder.txtname.setText(donor.getName());
viewHolder.txtnumber.setText(donor.getNumber());
viewHolder.txtblood.setText(donor.getBlood());
return row;
}
}
Enjoy!
Upvotes: 1