0

J'ai créé une SQLiteDatabase qui contient des informations provenant des entrées de l'utilisateur. L'utilisateur saisit des données sur sa propre recette pour un repas qu'il souhaite partager avec d'autres sur Facebook. Ces données utilisateur sont stockées puis affichées dans une liste. Cela fonctionne très bien pour la plupart, mais lorsque la liste est défilée pour observer plus d'entrées, un nullpointer se produit. Je stocke 3 types d'informations textuelles dans cette base de données, mais je veux seulement que listview affiche l'ID d'entrée des lignes et affiche le reste de l'information lorsque l'on clique sur l'élément.Android: SQLiteDatabase

Le message d'erreur:

enter image description here

C'est la classe de l'adaptateur, il se réfère à:

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; 

} 
} 

Ceci est la ligne, il se réfère:

recipeHolder.tx_id.setText(recipe.getId_entry().toString()); 

Le Tâche de recette avec getter et 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; 
} 
} 

Et si nécessaire ma tâche de fond pour la base de données elle-même:

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(); 

    } 



} 
} 
+0

C'est peut-être dans la méthode ** 'getView' ** de ** RecipeAdpater **, que si la clause else est utilisée, l'identifiant de ** TextView ** n'est pas obtenu. Essayez d'ajouter ** 'recipeHolder.tx_id = (TextView) row.findViewById (R.id.t_id); ** dans la clause Else ou en le déplaçant alternativement afin qu'il soit utilisé dans les deux scénarios, par ex. après la clause Else mais avant que le texte de TextView ne soit défini. – MikeT

+1

Je ne vois pas de 'row.setTag (recipeHolder)'. –

+0

Merci, c'était moi qui ne réglait pas le tag cela a résolu le problème. –

Répondre

1

Comme par vos attachés image, ses états que vous obtenez NullPointerException à vos adaptateurs méthode getView(). De mon point de vue, il y a deux possibilités.

1.RecipeHolder est null, comme vous ne l'avez pas défini étiquette à recipeHolder en utilisant row.setTag(recipeHolder).

2. peut être objet Recipe est null.

Lorsque vous utilisez ArrayAdapter, ses meilleures pratiques à l'utiliser comme ci-dessous:

Mettez à jour votre RecipeAdapter comme ci-dessous:

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; 
    } 
} 

Mise à jour BackgroundTask comme ci-dessous:

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(); 
     } 
    } 
} 

Espérons que ce sera lui lp ~

+0

Je viens d'ajouter row.setTag (recipeHolder); après l'autre dans RecipeAdapter et cela a fonctionné pour moi, n'est-ce pas une solution? –

+0

Oui, c'est la solution. En outre, je viens d'ajouter la meilleure pratique lorsque vous utilisez ArrayAdapter. – FAT

+0

Merci, extrêmement utile –