Using large databases in Android Apps - android

I have an Android App that uses an SQLite database. The problem is that the database has gotten to be quite large (41.6 MB) and I'm starting to wonder if I am correctly loading it into the app.
Right now what I'm doing is in the onCreate() method of my app's splash screen I'm opening the database, querying it, saving the data as objects, then closing the database. It takes a noticeable amount of time on a cold launch. Ideally I want to do all of this on the first launch and save the data somewhere on the device to speed up future launches. Is there a way I can do that?

I have same problem before.Probably thats the same case. Mine one because I pinging too many times of the Backend API and there is one more problem where you insert into your Object. probably when you insert it, The data that should just insert once, you insert it too many times on the for loop if there are many object that you are going to insert. Probably you can put your code when inserting it. lots of dev doesn't care about that but actually thats really annoying to user.
in my case because of this :
manager.removeAllStop();
manager.removeAllUpload(); //--> remove the data before insert the new one
for (Stop stop : SomeStopsList) { //--> when I want to loop through and want to add it to other object
**manager.insertAppTourStopList(appTourStopList);** //--> PROBLEM HERE !!!! THIS COULD BE OUTSIDE FROM THE LIST BECAUSE YOU WANT THIS TO BE ADDED ONCE ONLY
ArrayList<Upload> uploadList = new ArrayList<Upload>(); // --> new object
for (Upload uploadData : stopList.uploads) { //--> get the list and loop
Upload upload = new Upload(); //--> create new object
upload.setStopId(stopList.getId()); //--> insert it
}
}

Related

Firebase multiple query bottleneck

I have ViewPager which holds 2 different fragments. In both of the fragments, I'm trying to query firebase database with addValueEventListener. Here is the reference -
public static DatabaseReference getDatabase() {
if (mDatabase == null) {
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
mDatabase = FirebaseDatabase.getInstance().getReference();
}
return mDatabase;
}
In first Fragment there is something like 500+ items (takes about 8 seconds to load up), and in the second there is like 20-30. The problem is that second fragment always wait for 1st one to finish and just then queries the second one. Is there a way I can separate or do something about it? I really need the second Fragment to load up faster. Thanks in advance.
If I had to solve this problem, I would think the overall situation a bit differently like #Mark suggested in the comments. I would have implemented a paginated query on Firebase so that I would not have to get all 500+ rows at a time.
Besides that, I would like to keep an offline storage of the data which are fetched from Firebase. So that, each time the application loads, the data is being populated in both fragments which were fetched earlier. I would run the query in the background asynchronously and the user would not have to wait for the query to finish to see the data in both fragments. Once the query is finished loading, I would have updated the views accordingly with the newly fetched data along with updating the local cache which will be needed to serve the data next time you launch the application.
If you are not interested in loading data in the background and showing the initial items from the cache and stick to your current implementation, then I would like to suggest you, manage all these things from the activity that contains the ViewPager. Just get the queries executed one after one, or asynchronously and get the results published to the fragments once the results are received from Firebase using BroadcastReceiver or something like that.
Hope that helps!

Android - Best way to watch a SQLite database for new rows and then perform a task

New Android app "developer" here, working on my first app.
As the title suggests I am trying to find the best way to handle updates to my SQLite database and perform an action based on new rows.
New rows can be added one of two ways:
1) a content observer that auto-adds new enteries when a photo is taken
2) via the share intent
Only my app can add entries to the database.
Right now I have an asynctask that loops in the background once every 1000ms, checks if a new image is added to the database, checks a couple variables and if everything is good to go it performs a HttpPost task.
This works as expected.
I come from a web dev history with very minimal threading experience. I've read articles on threads, Semaphores and handlers but I'm really struggling on making sense of them and which would be best for my needs or if what I am currently doing is ok.
Does Thread.sleep(1000); prevent the device from entering deep sleep? Thus killing the battery.
What I am really looking for is some guidance, possibly some examples, I like to think of my self as a quick learner but my lack of experience with threading is preventing me from truly understanding what is best for what I am trying to accomplish.
Images are added to the database using the following method:
public class DatabaseHelper extends SQLiteOpenHelper {
...
// Adding new Image
public void addImage(Image image) {
Log.d(TAG, "adding image: "+image._uri);
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_URI, image._uri); // image uri
values.put(KEY_TRIES, image._tries); // upload tries
values.put(KEY_UPLOADED, image._uploaded); // upload status
values.put(KEY_DATE_ADDED, Calendar.getInstance().getTimeInMillis());
values.put(KEY_DATE_UPLOADED, image._date_uploaded);
// Inserting Row
db.insert(TABLE_IMAGES, null, values);
Log.d(TAG, "image added");
}
}
If I understand right, you already have an event when a new content relevant to your app appears. Launch an upload if a connection is available. If there is no connection available just cache it in the database (by using a similar database structure or using a column to indicate upload status, say Unix Epoch for cached photos).
From then on you may just add an inexact alarm through AlarmManager that tries to upload cached data.

Is closing a database opened with window.openDatabase necessary?

The code at the moment reads something in the order of...
DoAnything() {
OpenTheDatabase()
// ... Do all the things! ...
}
However, the database object is never closed. This is worrisome.
The database is opened as follows:
var db = window.openDatabase( ... paramters ... );
No .closeDatabase function exists, or the documentation is incomplete. I thought the following might suffice:
db=null;
I see that sqlite3_close(sqlite3*) and int sqlite3_close_v2(sqlite3*) exist, but I'm unsure how to apply them in this case.
How do I close the database, and is it necessary?
Generally you only have one database connection that you open on app startup, and there is no need to close it while the app is open. It's a single threaded, single user app, so a lot of the normal rules about database connections don't apply.
When the app shuts down, you can rely on the browser to close everything - given the average quality of code on the web, browsers have to be pretty good at cleanup.
Setting db to null and letting the garbage collector do its thing will probably also work, but it is better not to create the extra objects in the first place.

Downloading data in separate thread before initializing a ListView

I'm having issues with multithreading in my application. I know there are many posts on Threads/AsyncTasks/etc, but none seem to address my specific problem.
Basically, I get a query string in my search Activity, then send it to my results Activity, where the string is used as a SQL query, the results are returned as an array of JSON objects, then I display these objects in a ListView (which is part of the results Activity). All of my SQL connection and retrieval is done in a separate class that I call at the start of the results Activity.
MySQLRetrieve data = new MySQLRetrieve();
ArrayList<Tile> tiles = data.getResults(nameValuePairs, isLocationSearch);
The above code is how I get the SQL response and convert into an ArrayList, which I then use the populate my ListView with. getResults() takes care of all of this.
I already have separate threads working to download images into the ListView, but what I can't get to work is getting the SQL query and result to run in it's own Thread. What I want to achieve is this:
User enters search query in search Activity.
Intent is sent to results Activity, and it starts immediately.
ProgressDialog (just the animated spinner thing, not a loading bar) displays while the SQL query is taking place.
ListView populates with objects from the JSON array, lazy loading images as they come.
I have steps 1,2, and 4 working well, but 3 is the problem. I've looked up AsyncTasks, which seem to be the answer, but I just can't get them to work. Does anyone have a solution to this problem? I need to do this, so when starting the results Activity, the UI changes immediately to the results Activity and doesn't have to wait until the SQL response is returned.
And yes, I've already read the painless-threading post.
Thank you.
I would recommend against creating that ArrayList<Tile> to reduce memory consumption (and code size) and instead directly bind the SQLite Cursor to the ListView using a CursorAdapter.
That alone might just increase the performance enough that you don't need to do any async loading.
If you still want async loading, check out the LoaderManager framework (available since Android 3.0/ API level 11, with Android support package down to 1.6/4) which will automagically do asynchronous loading of your Cursor -- either using the built-in CursorLoader (if you happen to have a ContentProvider), or the SimpleCursorLoader created by a fellow SO user (if you don't).

How to load data to make them visible in an ActivityList?

I'm relatively new to Android and have the following question. I have a local DB on the device from which I want to display the content in an ActivityList. Let's say there is a table "person" on the DB containing general information like "name, surname etc."
Every row in the table should be displayed as an item within the ActivityList.
I know that there exists a sort of Adapter with which I can directly fill the ActivityList with my table data, but is this the way to do it?
Isn't it better to load all the data at startup and then hold them for the entire session and pass the data from one activity to another(or make them static..) if necessary, instead of loading the data every time I change to another Activity?
If I would have a normal Java application I would load the Data at startup and then just work with the loaded objects (at least for reasonable data sets).
Doesn't it make sense for an Android App too?
I will up-rate every answer that makes sense to me.
Thanks!
Slash
I would have a look at the ContentProvider.
You can use it to query your database and then show the content in the ListView using a CursorAdapter.
You need to use an Adapter if you want to work with ListView. So, that is a must. And you can set the Adapter data from your Activity.
As for the "sense" question, it probably makes sense. But as always it depends on a few things:
Will this data be used through out the application? Then it absolutely makes sense to load it once and use it everywhere. How you do that is up to your needs, static access or passing the data, all should work.
And DB access is always expensive. And if you have lots of rows, the loading process from the database can be extremely slow. So, again, load it once and use it everywhere is a good plan.
But be careful about blocking the UI thread when you load this data. You should never access DB from your UI thread. Instead use a worker thread or AsyncTask.

Categories

Resources