Houman Hr Houman Hr - 29 days ago 5
Android Question

I'm making an app which uses SQLite and when I run it, it crashes

I get this error:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.houman.mymovielist/com.example.houman.mymovielist.MainActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'int android.database.Cursor.getColumnIndex(java.lang.String)' on a null object reference


My code:

MainActivity.xml

public class MainActivity extends AppCompatActivity {

ImageView hamber;
DrawerLayout drawerLayout;
NavigationView navigationView;
DBOperators dbOperators = new DBOperators();
RecyclerView recyclerView;
RecyclerAdaptor recyclerAdaptor;


SQLiteDatabase db;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navi_activity);

recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

DBHelper dbHelper = new DBHelper(this);

db = dbHelper.getWritableDatabase();

Cursor cursor = getEmAll();

recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerAdaptor = new RecyclerAdaptor(this,cursor);
recyclerView.setAdapter(recyclerAdaptor);


hamber = (ImageView) findViewById(R.id.hamber);
drawerLayout = (DrawerLayout) findViewById(R.id.drawerMain);
navigationView = (NavigationView) findViewById(R.id.navi);

hamber.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
drawerLayout.openDrawer(Gravity.RIGHT);
}
});

navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();

if(id==R.id.addNewNavi){
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
MainActivity.this.startActivity(intent);
}
return true;
}
});
}

@Override
public void onBackPressed() {
if(drawerLayout.isDrawerOpen(Gravity.RIGHT)){
drawerLayout.closeDrawer(Gravity.RIGHT);
}else {
super.onBackPressed();
}
}

public Cursor getEmAll(){

return db.query(Contracts.Movies.TABLE_NAME,
null,
null,
null,
null,
null,
Contracts.Movies._ID
);
}

public long addNew(String movieName,String movieGenre,String movieRate,String movieCountry,String movieLang,String movieSummary){
ContentValues cv = new ContentValues();
cv.put(Contracts.Movies.MOVIE_NAME,movieName);
cv.put(Contracts.Movies.MOVIE_GENRE,movieGenre);
cv.put(Contracts.Movies.MOVIE_RATE,movieRate);
cv.put(Contracts.Movies.MOVIE_COUNTRY,movieCountry);
cv.put(Contracts.Movies.MOVIE_LANG,movieLang);
cv.put(Contracts.Movies.MOVIE_SUMMARY,movieSummary);
return db.insert(Contracts.Movies.TABLE_NAME,null,cv);
}


my db helper class:

public static final String DB_NAME = "moviesDb.db";
public static final int DB_VERSION = 1;

public DBHelper(Context context) {
super(context,DB_NAME,null,DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
String query = "CREATE TABLE " + Contracts.Movies.TABLE_NAME + "("
+ Contracts.Movies._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ Contracts.Movies.MOVIE_NAME + " TEXT, "
+ Contracts.Movies.MOVIE_GENRE + " TEXT, "
+ Contracts.Movies.MOVIE_RATE + " TEXT, "
+ Contracts.Movies.MOVIE_COUNTRY + " TEXT, "
+ Contracts.Movies.MOVIE_LANG + " TEXT, "
+ Contracts.Movies.MOVIE_SUMMARY + " TEXT, "
+ Contracts.Movies.IMAGE_ADDRESS + " TEXT"
+");";
db.execSQL(query);

String query2 = "CREATE TABLE " + Contracts.Genres.TABLE_NAME + "("
+ Contracts.Genres._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ Contracts.Genres.GENRE_NAME + " TEXT, "
+ Contracts.Genres.MOVIE_ID + " INTEGER "
+");";
db.execSQL(query2);

String query3 = "CREATE TABLE " + Contracts.Settings.TABLE_NAME + "("
+ Contracts.Settings.THEME + " TEXT "
+");";
db.execSQL(query3);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXIST " + Contracts.Movies.TABLE_NAME);
db.execSQL("DROP TABLE IF EXIST " + Contracts.Genres.TABLE_NAME);
db.execSQL("DROP TABLE IF EXIST " + Contracts.Settings.TABLE_NAME);
onCreate(db);
}


my contract class:

public static final class Movies implements BaseColumns{

public static final String TABLE_NAME = "moviesTable";
public static final String MOVIE_NAME = "movieName";
public static final String MOVIE_GENRE = "genre";
public static final String MOVIE_RATE = "rate";
public static final String MOVIE_COUNTRY = "country";
public static final String MOVIE_LANG = "lang";
public static final String MOVIE_SUMMARY = "summary";
public static final String IMAGE_ADDRESS = "imgAdd";
}

public static final class Genres implements BaseColumns{

public static final String TABLE_NAME = "genreTable";
public static final String GENRE_NAME = "genreName";
public static final String MOVIE_ID= "movieId";

}

public static final class Settings{

public static final String TABLE_NAME = "settingsTable";
public static final String THEME = "theme";

}


and my recycler view adapter class:

Context context;
Cursor cursor;
String mName = cursor.getString(cursor.getColumnIndex(Contracts.Movies.MOVIE_NAME));
String mGenre = cursor.getString(cursor.getColumnIndex(Contracts.Movies.MOVIE_GENRE));
String mRate = cursor.getString(cursor.getColumnIndex(Contracts.Movies.MOVIE_RATE));
String mCountry = cursor.getString(cursor.getColumnIndex(Contracts.Movies.MOVIE_COUNTRY));
String mLang = cursor.getString(cursor.getColumnIndex(Contracts.Movies.MOVIE_LANG));
String mSummary = cursor.getString(cursor.getColumnIndex(Contracts.Movies.MOVIE_SUMMARY));
String mImg = cursor.getString(cursor.getColumnIndex(Contracts.Movies.IMAGE_ADDRESS));

String mDetails = "Genre: " + mGenre + System.getProperty("line.seprator") +
"Rate: " + mRate + System.getProperty("line.seprator") +
"Country: " + mCountry + System.getProperty("line.seprator") +
"Language(s): " + mLang;

public RecyclerAdaptor(Context context, Cursor cursor) {
this.context = context;
this.cursor = cursor;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.rv_layout,parent,false);
return new MyViewHolder(view);
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {

if(!cursor.moveToPosition(position))
return;
holder.name.setText(mName);
holder.details.setText(mDetails);
holder.summary.setText(mSummary);
holder.itemImage.setImageResource(Integer.getInteger(mImg));

}

@Override
public int getItemCount() {
return cursor.getCount();
}

public class MyViewHolder extends RecyclerView.ViewHolder {

ImageView itemImage;
TextView name,details,summary;
public MyViewHolder(View itemView) {
super(itemView);
itemImage = (ImageView) itemView.findViewById(R.id.itemImg);
name = (TextView) itemView.findViewById(R.id.itemName);
details = (TextView) itemView.findViewById(R.id.itemDetails);
summary = (TextView) itemView.findViewById(R.id.itemSummary);
}
}

Answer Source

You placed cursor.getString(cursor.getColumnIndex outside of any methods before you ever created an actual Cursor object to get the columns of.

You don't need fields to store those values, so remove those lines

See suggestions for your Adapter from here Using the recyclerview with a database

For example, you need to use the onBindViewHolder method for when to extract data from your Cursor