Sqlitedatabase Close() Function Causing Nullpointerexception When Multiple Threads

Error java.lang.NullPointerException in SQLiteDatabase Android

All the things you have did correctly, but missed one small thing within your onCreate() of DataHandler.java.

 @Override
public void onCreate(SQLiteDatabase db)
{
try{
//db.execSQL("TABLE_CREATE");
// Here you passing `TABLE_CREATE` string instead of passing `TABLE_CREATE` variable's string. So kindly remove quotes surrounded by 'TABLE_CREATE' and try.
db.execSQL(TABLE_CREATE);
}
catch(SQLException e)
{
e.printStackTrace();
}
}

And change this,

public static final String TABLE_CREATE = "create table mytable (name text not null, email text not null);";

to

public static final String TABLE_CREATE = "create table mytable (name text not null, email text not null)";

DatabaseHandler.close() - Null pointer exception even if checked

I was wondering about the exact same thing (see included code above). It just does not make sense that this is happening.

Android Error when closing the application

I feel the issue is either database instance or any other object became null but you are calling some method using that object. Always check for null before using any methods of any object. see the sample example

example

if(database != null){
database.close();
}

NullPointerException on getReadableDatabase()

As your class which is not an Activity this.getReadableDatabase(); is firing NullPointerException as it is not getting context to open database.

Use context to open database. try with following :

DatabaseHandler dbz = new DatabaseHandler(Activity.this);

public Context context;

public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// assigning context Change your constructor
this.context = context;
}

// Open database using context object
SQLiteDatabase db = this.getReadableDatabase();

Intermittent NPE when inserting data into SQLite

As mentioned here SQLiteDatabase close() function causing NullPointerException when multiple threads

The reason for your bug could be that you close the database at some point. Probably concurrently while the task that fails was not finished.

I've followed the stacktrace a bit and this is what roughly happens:

  • AlbumsData.insertOrIgnore(AlbumsData.java:89)
    You call insertWithOnConflict, which builds the resulting sql string ("INSERT OR IGNORE INTO...") then wraps that together with the values from your ContentValues into a SQLiteStatement.
  • SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1844) - The resulting statement is to be executed now
  • SQLiteStatement.executeInsert(SQLiteStatement.java:112) - before the actual insert can happen, the database needs to acquire a lock.
  • SQLiteStatement.acquireAndLock(SQLiteStatement.java:247) - some checks happen here, the database object is as far as I can see not null at that point. Code decides that it has to start a transaction. The database object itself is as far as I can see not locked at that point.
  • SQLiteDatabase.beginTransactionNonExclusive(SQLiteDatabase.java:605) - just forwarding
  • SQLiteDatabase.beginTransaction(SQLiteDatabase.java:690) - after some checks (not sure if database has to exist here) it will try to execute execSQL("BEGIN IMMEDIATE;")
  • SQLiteDatabase.execSQL(SQLiteDatabase.java:1965) - just forward
  • SQLiteDatabase.executeSql(SQLiteDatabase.java:2025) - builds another SQLiteStatement out of "BEGIN IMMEDIATE;. This one should be executed now
  • SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:96) - starts with checking the database lock, this seems to be okay and the database should not be null here. The statement is then executed and finally the database is to be unlocked again.
  • SQLiteStatement.releaseAndUnlock(SQLiteStatement.java:290) - cleans up some stuff and in the end fails with NPE because the database is null.

Line numbers don't match so there are probably vendor modifications / additions in that code.

As you can see, the code crashes before actually using the data you supplied. It was about to do

BEGIN TRANSACTION IMMEDIATE; -- crash
INSERT INTO table (...) VALUES (...);
-- (end transaction)

That makes it in my opinion a framework bug. The database object that is internally handled there should not be able to be null somewhere down the line, especially when it seems that it was not null further up in the stack.

I also think that it is possible that another hidden exception could be the root cause for this. There are a lot of try { /* do stuff */ } finally { /* clean up */ } blocks within the code and the finally part will be executed even if the try part throws an exception. Now the finally block could cause another exception and the result is AFAIK that the original exception is replaced by the new exception from the finally block.

Especially executeUpdateDelete() is like

try {
acquireAndLock(WRITE);
// actual statement execution
} finally {
releaseAndUnlock();
}

if the database is closed at that point, acquireAndLock or any code in the try part could fail and that could leave the database object at null which causes releaseAndUnlock to fail again. You should get the same stacktrace.

Apart from that, don't do empty catch blocks like catch (SQLiteException e) { /* empty */ }. Log them with ACRA if possible / you don't do that already.

sporadic NullPointerException despite the fact, that the Object is not null

Found the solution:
The Problem was that the DbHelper Object was created on the UI thread but closed in the asyncTask worker thread.
After I moved the .close() into the onPostExecute() method the exception disappeared.

private class processCursorTask extends AsyncTask<Integer[], Void, Dataset[]> {
private DbHelper mDb;

processCursorTask(DbHelper db) {
super();
mDb=db;
}

@Override
protected Dataset[] doInBackground(Integer... args) {
Dataset[] res=mDb.getCursorFiltered(args);
return res;
}

protected void onPostExecute(Dataset[] result) {
mDb.close();
setListView(result);
}
}

Android NULL Pointer Exception and Fragment data transmission

Your init() function is probably try to find views inside fragments in view pager. However, at that moment, the fragments are not inflated yet, so your views in the activity are null and trying to do operation on them gives NPE. You should use onCreateView() of Fragment classes to find those views. Then you may notify main activity via callback mechanism.

For example, create FirstFragment as follows:

public class FirstFragment extends Fragment {

private OnFirstFragmentReadyListener callback;

@Override
public void onAttach(Context context) {
super.onAttach(context);

// This makes sure that the container activity has implemented the callback.
try {
callback = (OnFirstFragmentReadyListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement OnFirstFragmentReadyListener");
}
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_first, container, false);
return rootView;
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

// Notify the parent activity that the fragment is inflated.
callback.onFirstFragmentReady();
}

public interface OnFirstFragmentReadyListener {
void onFirstFragmentReady();
}
}

Let the layout of FirstFragment as follows (referenced above as fragment_first):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/first_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</RelativeLayout>

Assume we created two more similar fragment classes named as SecondFragment and ThirdFragment. Then the activity should be like this:

public class MainActivity extends AppCompatActivity implements FirstFragment.OnFirstFragmentReadyListener,
SecondFragment.OnSecondFragmentReadyListener, ThirdFragment.OnThirdFragmentReadyListener {

...

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager =(ViewPager) findViewById(R.id.pager);
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);

// Don't call these functions here, spread them into callbacks.
// init();
// Action();
}

@Override
public void onFirstFragmentReady() {
TextView firstTextView = (TextView) findViewById(R.id.first_label);
...
// Now you have the views from FirstFragment instance.
// You can now call setText() or setOnClickListener() here.
}

@Override
public void onSecondFragmentReady() {
TextView secondTextView = (TextView) findViewById(R.id.second_label);
...
// Now you have the views from SecondFragment instance.
// You can now call setText() or setOnClickListener() here.
}

@Override
public void onThirdFragmentReady() {
TextView thirdTextView = (TextView) findViewById(R.id.third_label);
...
// Now you have the views from ThirdFragment instance.
// You can now call setText() or setOnClickListener() here.
}
}

Although this code works, this may not be the best way. I think it is better to do operations on views like setting texts or assigning OnClickListeners in fragments itself. If you need to notify a fragment after an action happened in the parent activity, you can implement public methods inside fragments and you can call them from the parent activity when needed.



Related Topics



Leave a reply



Submit