I have been getting this exception, DatabaseObjectNotClosedException:
close() was never explicitly called on database '/data/data/com.project.test/databases/database'
E/SQLiteDatabase(13921): android.database.sqlite.DatabaseObjectNotClosedException:
Application did not close the cursor or database object that was opened here
I tried closing the database helper and cursors, but I will get runtime exception. This happens when I leave the activity and revisit it after hitting the back button.
How can I close my cursors and helpers properly?
I have tried two methods:
first, closing the cursors after each individual use, and closing the database helper onpause.
second, closing the cursors onpause along with the databasehelper, but both didn't work.
can someone help me with this?
EDIT:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = this.getActivity();
context = this.getActivity().getApplicationContext();
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mDbHelper = new DatabaseHelper(context);
mDbHelper.open();
populateList();
}
public void populateList() {
directoryCursor = mDbHelper.fetchAllRootDirectories();
activity.startManagingCursor(directoryCursor);
adapter = new DirectoryListAdapter(this.getActivity(), directoryCursor);
this.setListAdapter(adapter);
}
......
private UpdateDatabaseListener updateDatabaseListener = new UpdateDatabaseListener() {
public void onUpdate(int from, int to) {
.....
findExistingRecordCursor = mDbHelper.findExistingRecords(from, to);
activity.startManagingCursor(findExistingRecordCursor);
if(findExistingRecordCursor.getCount() == 0) {
....
}
}
}
I have a database helper opened in the onCreate() function.
cursors used when populating the listview,
cursors used to find existing records,
cursors to get information.
UPDATE:
I have tried closing onPause and onDestroy, it still crashes with runtimeexception.
Are you closing the SQLiteDatabase object or not. If not try to close SQLiteDatabase Object like this
SQLiteDatabase db = SQLiteHelper classobject.getWriteableDatabase();
// block of code
db.close();
and run your application.
Could you please post your code so that it will be more helpful to understand your problem.
Sorry for the late reply.
From what I see, you have opened the db using
mDbHelpher.open()
After that you did populatelist()
did you try doing mDbHelpher.close() after that?
Same thing with the cursors. Because your error clearly says that the db or the cursor was left open.
As soon as you are done using the db, you should close. This should not give the problem even after you visit another activity and then press back button.
Also you said you get runtime exception when you close the db or the cursor. Is it the same exception or different?
Related
We are using RealChangeListener to listen data changes and updating listview by calling notifydatasetgchanged().
Initial sync time we do get many records from server(per batch 100 records), loop thru results updating Realm like below in background thread.
for(int i=0;i<results.size();i++)
{
// processing and validation
....
db.beginTransaction();
db.copyToRealm(processedObject);
db.commitTransaction();
}
In activity, we are registered realmResults change listener like below code
#Override
public void onStart() {
super.onStart();
mEntityDataProvider = new EntityDataProvider();
mEntityDataProvider = mEntityDataProvider.getListAsync();
mEntityDataProvider.addChangeListener(realmEntityChangeListener);
}
private RealmChangeListener<RealmResults<Entity>> realmEntityChangeListener = new RealmChangeListener<RealmResults<Entity>>() {
#Override
public void onChange(RealmResults<Entity> realmResults) {
if (mEntityListAdapter!= null) {
mEntityListAdapter.setData(realmResults);
mEntityListAdapter.notifyDataSetChanged();
}
}
};
Questions:
Is it best practice to call notifyDataSetChanged() in
reamlChangeListner?
For every commitTransaction() i think
realmChangeListener will be called, calling notifyDataSetChanged() calling many times is it fine?
If above practice is not good to do,
suggest me if any alternatives I need to consider.
Thanks
Yes
I think you can put the loop between beginTransaction()/commitTransaction() to avoid refresh the UI too many times.
See https://realm.io/docs/java/latest/#adapters, You can just use the adapters from Realm. And in the mEntityListAdapter.setData(realmResults); doesn't seem to be necessary to be called every time if the it is on the same RealmResults.
I am writing an android app. For that I need to populate an SQLite database with data from a txt file. So in the onCreate function of the database, I am creating the database and then populating it with the data. This is what the onCreate's declaration looks like:
public void onCreate(SQLiteDatabase db) {
But when I use this line inside onCreate,:
db = this.getWritableDatabase();
I get this error at runtime in Logcat: "java.lang.IllegalStateException: getDatabase called recursively(812)".
So now I am unable to populate the database from inside onCreate, and am stuck. Any help will be appreciated.
onCreate() gets called the first time you call getReadableDatabase or getWriteableDatabase. What is certainly happening is that onCreate is getting called recursively because the db hasn't been created yet and your
db = this.getWritableDatabase();
call triggers the creation inside the creation.
If you need to prefill the db, just use the db argument of onCreate as a writeable database.
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(YOUR_STATEMENT);
.
.
}
If you need to perform a lot of db operations, using
db.beginTransaction();
.
.
db.setTransactionSuccessful();
} catch (SQLException e) {
} finally {
db.endTransaction();
}
is generally faster.
This is my method in DBMethods class:
public void getResult(EditText keyWord2){
EditText keyWord = null;
String SQL ="localSearch.php?query="+keyWord.getText();
mDb.rawQuery(SQL, null);
}
And this is my method in which I am opening Database and all that in webServices class.
public void startSearch(View v){
keyWord = (EditText)findViewById(R.id.searchField);
String data = null;
DBMethods mDbHelper = new DBMethods(this);
mDbHelper.createDatabase();
mDbHelper.open();
mDbHelper.getResult(keyWord);
mDbHelper.close();
}
When I try to fetch data from the database by entering some keyword in the search bar, a force close error occurs.
EditText keyWord = null;
String SQL ="localSearch.php?query="+keyWord.getText();
Keyword is null, this will give null pointer exception.
I think your SQL variable must be
localSearch.php?query="+**keyWord2**.getText();
Make sure that you uninstall the already installed same application in your Emulator. Because once we Run our app that Sqlite DB installed in our Emulator and can't be edited. So uninstall your app and then Run again your app after changing .
The onCreate of my userDatabase that extends ContentProvider is not properly called
Here is some of my userBatabase code:
public class userDatabase extends ContentProvider {
private MainDatabaseHelper mOpenHelper;
public userDatabase(){}
public static final class MainDatabaseHelper extends SQLiteOpenHelper{...}
#Override
public boolean onCreate() {
mOpenHelper = new MainDatabaseHelper(getContext());
return true;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
long id = mOpenHelper.getWritableDatabase().insert("Users", null, values);
return Uri.withAppendedPath(CONTENT_URI, "" + id);
}
...
}
In my main activity I call:
userDatabase cpDatabase = new userDatabase();
But when I try to call cpDatabase.insert(userDatabase.CONTENT_URI, values);
Everything crashes inside insert when mOpenHelper.getWritableDatabase().insert("Users", null, values); is called.
I found out that mOpenHelper.getWritableDatabase() was the issue, as it wont run even by itself, and then I found out this was because mOpenHelper was null.
I instantiate mOpenHelper in the constructor, so I figure its not running. A few log messages confirm this, when I call userDatabase cpDatabase = new userDatabase(); my log messages showed that the userDatabase() constructor ran normally, but the onCreate never ran, so the mOpenHelper never got instantiated.
(Note: with these log messages, I noticed that the constructor and the onCreate for my userDatabase got called when my app started. I have no idea why or where. I dont understand why this was run before i tried to create an instance. and even though it was run, mOpenHelper still wasn't initialized, and when i created an instance, the constructor ran but the onCreate didnt.)
What could possibly be happening, and how can I make my onCreate run?
Since you are using content providers, according to the documentation
This method is called for all registered content providers on the
application main thread at application launch time
And the way you try to use the content provider is seems wrong and,
You don't need to manually instantiate the content provider, once you made the request via the ContentResolver by passing the URI, the system inspects the authority of the given URI and passes the request to the content provider registered with the authority.
for example
getContentResolver().delete(uri, null, null);
Where the uri is, the full URI to query.
This tutorial will guide you in right direction
I have an onCreate method that runs the code below. In a nutshell the code retrieves data from the server and shows it on the screen for a messaging program. It only does it once, but I would like it to run the AsyncTask every 3 seconds (to try to simulate a chat). I'm pretty sure this is not the way to go about having a chat system but, I just need something that works for now (as a proof of concept) and I'll focus on the correct way of implementing it later.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat_box);// sd
final Functions function = new Functions();
final SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
whatroom = prefs.getString("chat", "null");
new AsyncTask<String, Void, String>() {
#Override
protected String doInBackground(String... args) {
return function.getInbox(args[0]);
}
#Override
protected void onPostExecute(String result) {
TextView inbox = (TextView) findViewById(R.id.inbox);
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar1);
progressBar.setVisibility(View.GONE);
inbox.setText(result);
}
}.execute(whatroom);
}
I've tried putting a simple while statement around the asynctask but, it just force closes.
You cannot reuse an AsyncTask instance. You would need to create fresh instances each pass of your loop.
Without additional information, it's difficult to give you a specific answer. However look into abstracting everything using a Loader, using a Service, etc
Regarding Loaders:
They are available to every Activity and Fragment.
They provide asynchronous loading of data.
They monitor the source of their data and deliver new results when the content changes.
They automatically reconnect to the last loader's cursor when being recreated after a configuration change. Thus, they don't need to re-query their data.