Reputation: 199
I have created an SQLiteDatabase that holds information from user input. The user inputs data about their own recipe for a meal they want to share with others over facebook. This user data is stored and then displayed inside a listview. This works fine for the most part but when the listview is scrolled to observe more entries, a nullpointer occurs. I store 3 types of text information into this database but I only want the listview to display the entryID of the rows and display the rest of the information when the item is clicked.
The error message:
This is the adapter class it refers to:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class RecipeAdapter extends ArrayAdapter {
List list = new ArrayList();
public RecipeAdapter(Context context, int resource) {
super(context, resource);
}
public void add(Recipe object) {
list.add(object);
super.add(object);
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
RecipeHolder recipeHolder;
if(row == null){
LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.display_entry_row,parent,false);
recipeHolder = new RecipeHolder();
recipeHolder.tx_id = (TextView)row.findViewById(R.id.t_id);
}
else{
recipeHolder = (RecipeHolder) row.getTag();
}
Recipe recipe = (Recipe)getItem(position);
recipeHolder.tx_id.setText(recipe.getId_entry().toString());
return row;
}
static class RecipeHolder{
TextView tx_id;
}
}
This is the line it is referring to:
recipeHolder.tx_id.setText(recipe.getId_entry().toString());
The Recipe Task with getter and setter:
public class Recipe {
private String id_entry;
public Recipe(String id_entry){
this.setId_entry(id_entry);
}
public String getId_entry() {
return id_entry;
}
public void setId_entry(String id_entry) {
this.id_entry = id_entry;
}
}
And if needed my background task for the database itself:
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.widget.ListView;
import android.widget.Toast;
public class BackgroundTask extends AsyncTask<String, Recipe, String> {
Context ctx;
RecipeAdapter mRecipeAdapter;
Activity activity;
ListView listView;
BackgroundTask(Context ctx){
this.ctx = ctx;
activity = (Activity)ctx;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
String method = params[0];
DatabaseOperations dbOperations = new DatabaseOperations(ctx);
//adds information into database
if (method.equals("add_information")){
String entry = params[1];
String ingred = params [2];
String direc = params [3];
SQLiteDatabase db = dbOperations.getWritableDatabase();
dbOperations.putInformation(db, entry, ingred, direc);
return "One Row Inserted";
}
//gets information from database and places inside listview
else if (method.equals("get_info")){
listView = (ListView) activity.findViewById(R.id.listVrecipe);
SQLiteDatabase db = dbOperations.getReadableDatabase();
Cursor cursor = dbOperations.getInformation(db);
mRecipeAdapter = new RecipeAdapter(ctx,R.layout.display_entry_row);
String entry;
//loops through all row information
while (cursor.moveToNext()){
//grabs entry id
entry = cursor.getString(cursor.getColumnIndex(TableData.TableInfo.EntryID));
Recipe recipe = new Recipe(entry);
publishProgress(recipe);
}
return "get_info";
}
return null;
}
@Override
protected void onProgressUpdate(Recipe... values) {
mRecipeAdapter.add(values[0]);
}
@Override
protected void onPostExecute(String result) {
//after execution update listview with new entries
if(result.equals("get_info")){
listView.setAdapter(mRecipeAdapter);
}
else{
Toast.makeText(ctx,result, Toast.LENGTH_LONG).show();
}
}
}
Upvotes: 0
Views: 49
Reputation: 21766
As per your attached image
, its states that you are getting NullPointerException
at your adapters getView()
method.
From my point of view, there are two possibilities.
1. RecipeHolder
is null
, as you did not set tag to recipeHolder
by using row.setTag(recipeHolder)
.
2. May be Recipe
object is null
.
When you are using ArrayAdapter
, its best practice to use this as below:
Update your RecipeAdapter
as below:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class RecipeAdapter extends ArrayAdapter<Recipe> {
public RecipeAdapter(Context context, int resource, ArrayList<Recipe> list) {
super(context, resource, list);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
RecipeHolder recipeHolder;
if(convertView == null){
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.display_entry_row,parent, false);
recipeHolder = new RecipeHolder();
recipeHolder.tx_id = (TextView) convertView.findViewById(R.id.t_id);
convertView.setTag(recipeHolder);
}
else{
recipeHolder = (RecipeHolder) convertView.getTag();
}
Recipe recipe = (Recipe) getItem(position);
recipeHolder.tx_id.setText(recipe.getId_entry().toString());
return row;
}
static class RecipeHolder {
TextView tx_id;
}
}
Update BackgroundTask
as below:
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.widget.ListView;
import android.widget.Toast;
public class BackgroundTask extends AsyncTask<String, Recipe, String> {
Context ctx;
RecipeAdapter mRecipeAdapter;
Activity activity;
ListView listView;
List<Recipe> listRecipe;
BackgroundTask(Context ctx){
this.ctx = ctx;
activity = (Activity)ctx;
listRecipe = new ArrayList<Recipe>();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
String method = params[0];
DatabaseOperations dbOperations = new DatabaseOperations(ctx);
//adds information into database
if (method.equals("add_information")){
String entry = params[1];
String ingred = params [2];
String direc = params [3];
SQLiteDatabase db = dbOperations.getWritableDatabase();
dbOperations.putInformation(db, entry, ingred, direc);
return "One Row Inserted";
}
//gets information from database and places inside listview
else if (method.equals("get_info")){
listView = (ListView) activity.findViewById(R.id.listVrecipe);
SQLiteDatabase db = dbOperations.getReadableDatabase();
Cursor cursor = dbOperations.getInformation(db);
// Adapter
mRecipeAdapter = new RecipeAdapter(ctx, R.layout.display_entry_row, listRecipe);
String entry;
//loops through all row information
while (cursor.moveToNext()){
//grabs entry id
entry = cursor.getString(cursor.getColumnIndex(TableData.TableInfo.EntryID));
Recipe recipe = new Recipe(entry);
// Add recipe to list
listRecipe.add(recipe);
mRecipeAdapter.notifyDataSetChanged();
//publishProgress(recipe);
}
return "get_info";
}
return null;
}
@Override
protected void onProgressUpdate(Recipe... values) {
//mRecipeAdapter.add(values[0]);
}
@Override
protected void onPostExecute(String result) {
//after execution update listview with new entries
if(result.equals("get_info")){
listView.setAdapter(mRecipeAdapter);
} else {
Toast.makeText(ctx,result, Toast.LENGTH_LONG).show();
}
}
}
Hope this will help~
Upvotes: 1