I've pool of words (around 200 now) that I want to display randomly each day without repetition.
In shared preference I store the date of last displayed word and if the date today is same, I display the same word that was displayed last time, it today is another day I need to get another random word from the pool and display it.
I've tried to achieve this via two methods:
Method 1: Using sqlite db
Pre fill a db in assets folder (db has a table with two columns, words and isUsed)
on onCreate(SQLiteDatabase database) copy pre filled db to /data
use sqlite to get a random entry from db and update its isUsed couter to true
shave this word in shared preference so that if user opens the app again in the same day then show this word
If I've to update the words in db then(by 150):
create another db in assets folder with new words
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) copy this db to /data
copy each words in the original db row by row keeping the isUsed column intact
Instead of using pre filled db I can insert 200 words using SQL statement in oncreate and later update the other 150 with sql statements in onUpgrade.
Method 2: Using shared preferences
use to save 200 words
Create a string with random numbers upto 200 and save it in shared preference
pop one random number each day and show word with that index. If it is the same day then don't pop but show the last word
If I've to update the words(by 150):
check by how much the words number increased and generate those increased numbers in random order and shuffle it back to the original random string array
So my question is I feel none of this algo is good enough. Is there any better way to achieve this and if not should I go with method 1, method 1 but without pre filled db or method 2?
Why not just load strings from simple text file in assets during onCreate/onUpgrade, shuffle them and insert into database? Then when you need to know which word to show, just calculate number of days from application installation (N) and show N-th word.
I feel the Method 1 WITH pre-filled table is the best bet. That will helps you in the sens e of expandability and randomness.
Any huge task in onCreate should be avoided, since it'll lag your application. And an SQLLite db will be helpful if you need to increase the number of words later.
The method kriomant suggested is good, but lags the freedom of randomness. We can predict the text after two complete cycles if one sits and tries for it :-)
Related
QUESTION: Im making a flashcard app and when the user clicks "easy" for example, I want to increase the time of the card, then that card won't appear until the time goes reaches 0.
e.g. "Card 1" has a time of 0 at default , user clicks "I know button" and the time on that card increases to 5 mins (5:00), then that card wont appear again for 5 minutes until timer is back to 0, is this possible to do?
is this possible to do?
I believe that if you consider what SQLite is capable of and what an Android App is capable of then Yes. However using SQLite alone then No.
Typically, to get your outcome, the time would remain constant in the database but you would extract and thus show only the rows that met the criteria e.g. the time stored is less than or equal to the current time.
Clicking I know would then update the respective row and set the value to the current time plus 5 minutes, thus an extract, which could be timer based would then not show the respective row as it's then greater than the current time.
As for the timer SQLite does not have a built in timer. It is a database manager whose job is to store and retrieve structured data.
As an example consider the following, which shows the principle:-
DROP TABLE IF EXISTS flashcard;
CREATE TABLE IF NOT EXISTS flashcard (cardtitle TEXT, cardtimer INTEGER);
INSERT INTO flashcard VALUES ('Card1',strftime('%s','now')),('Card2',strftime('%s','now','+1 minute')),
('Card3',strftime('%s','now','+2 minute'));
SELECT *,strftime('%s','now') FROM flashcard WHERE cardtimer <= strftime('%s','now');
UPDATE flashcard SET cardtimer = strftime('%s','now','+5 minutes') WHERE cardtitle = 'Card1';
SELECT *,strftime('%s','now') FROM flashcard WHERE cardtimer <= strftime('%s','now');
This:-
drops and creates a table with 2 columns,
a column named cardtitle that stores the title of the card
a column named cardtimer for the time when the card can be displayed on or after
adds 3 rows with unique titles the time fors the first being the current time, the time for the second 1 minute later,and for the third another minute later.
An extract (SELECT query) that displays only the rows where the timer is now or earlier (irrespective of when it is run).
this shows just the first of the 3 rows as the others are in the future
An Update that changes the time of the first row to be 5 minutes from now
Another Extract using the same query as per 3
this shows nothing because now all 3 rows are in the future
Running the above results in :-
i.e. just Card1 is extracted
Then :-
i.e. all of the cards are now in the future.
However if the same extract is then run a while later (but sooner then 5 minutes later), as can be seen some 139 seconds later, then :-
If then after 5 minutes and the same extract is run then :-
I have a method that use the SELECT query and use the data containing
I only use the SELECT query for my app to fetch the data
The problem is that my new database is too slow for processing the method
I had an old DB file which i was using before i made my own one
It took 0.063548225 s on average to process with the old DB
And it took 4.202198266 s on average like 70 times longer process time than with the old one
I first thought it's because of the number of raws's difference between those DB files
So i tested again after deleting many rows in my new DB file
And weird thing is that it took time longer than the one with more rows like 5.903229880 s
my old DB created with these queries
CREATE TABLE korean_english (word TEXT, def BLOB)
CREATE INDEX idx_korean_english_word ON korean_english(word ASC)
and it contains 49,757 rows in the table
It took 0.063548225 s with this
and my new DB
CREATE TABLE korean_english ( word TEXT, def TEXT, num INTEGER )
and it contains 599,251 rows
It took 4.202198266 s with this
and my new reduced DB
DELETE FROM korean_english WHERE ROWID > 50000
so it contains 50,000 rows
I'm pretty sure it's about DB files because i just changed the DB file nothing else more
I really don't know why it takes time so much longer and even with less rows
OVERVIEW:
I have a database that contains more than 128,000 records, and each record contains about 12 columns (8 string columns with lengths of about 1-2 words each column, and 4 columns containing reference or indices of 4 images respectively).
GOAL:
What I want basically is that when the user chooses a chapter contained in a spinner, the app shall retrieve the data relevant to the chapter chosen and display it on the screen (this is oversimplification though).
WHAT I DID but FAILED:
Creating a class for each column. (This taught me, in the hard way, the 64KB limit thing in Java.)
Creating an XML resource file for each column. (Failed because apparently, there's a limited number of ID, in effect resources, in an app)
WHAT I'M PLANNING TO (LEARN AND) DO:
Create an SQLite Database. (But I worry how would I prepopulate it with my data? Wouldn't this lead to the 64KB limit error?)
Create a text file for each column and store them as raw resources then retrieve them using input stream. (I, TBH, don't know what I'm talking about here. I picked this up while reading some sites yesterday).
So, what should I do?
(MORE DETAILS):
My app has a spinner containing 114 chapter titles
When the user chooses a chapter, the verses of the chapter will be displayed in the screen.
Each token (or say, word) of each verse is clickable.
Each token (including its details) represents one record in the database.
When the user clicks the token, the details about it will be displayed.
The details consist of 8 string columns, and 4 columns containing reference to the 4 images (image of a page of a dictionary).
The total aggregate size of the images is about 90 MB.
First of all you have to create Datebase from Server Side and you have to manage same Database from Android Side like SQLite.
When your application load first time, you have to copy all the data from server in chunks.(Manage OutOfMemoryError)
then you can use all the data from SQLite so it will work speedy.
After all you have to sync do sync process as i have mentioned here.
Thanks you.
I have more than 5000-6000 records in SQLite table. When I delete this all records it takes very long time and causes screen pause and starts releasing resources.
I tried it with AsyncTask but still the same problem. So can anyone tell how should I delete this thousands of records without blocking app.
I am no expert to Sqlite but in general there are 3 ways to do that.
As every body commented Truncate if you are going to delete all record.
If you are going to majority of the records you can store the non-delete files in tempTable and then truncate your actual table finally insert all the records from temp to actual table
This one is what I use most of the time. Use a Top XXX delete statement in your case you can delete 200 records in every 2min. (I am assuming you don t insert more than 200 records in 2 min). The AsyncTask is the way for that kind of approach.
In T-SQL I use the following sql to it is up to you
Delete From tUser
where UserId in (
Select top 200 UserId
From tUser
where LastLoggin< GetDate()-120
)
If you want to delete all records in a table you could try dropping the table:
http://www.sqlite.org/lang_droptable.html
and later re-creating an empty table:
http://www.sqlite.org/lang_createtable.html
I have a .csv file that I turned into an SQLite database with the first column as a date and time (as a TEXT datatype because it's in the format 7/20/2011 12:00:00 PM), the second column as the subsecond (a REAL, like 0.142857), and the rest of the columns as data about that time. I will be using it as a read-only db in my Android app, in which the user selects a start time and an end time and then the data is displayed graphically for that time period.
This is my first time using a database and I'm not sure how to work with this. I believe I need a unique NUMERIC primary key for each row but simply labeling them by row number is a waste of space. The first column is not unique and is a TEXT datatype anyway, though if the subsecond was to be somehow incorporated then it would be unique. But I really can't re-write the database because it has 65534 rows... How do you suggest I access specific times in this database?
In Android you need a column named _ID in your database (else you'll face some issues later on). You will use that as the primary key.
Dates and times can be stored in SQLite in the form of a text column in the following format (See http://www.sqlite.org/datatype3.html):
TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS")
If your database is static, simply use a tool such as SQLite Database Browser to convert it to a format convenient for Android.
If your database is local and external(not remote), than you must have _id and another another table android_metadata which will hold the locale.
If your database was remote. Yes, you can it is only matter of speed if you are write, since you don't. Using WHERE clause will do the work.
Every date can be converted to numeric timestamp quite easy:
Date date = new Date();
long timestamp = date.getTime();
Date otherDate = new Date(timestamp);
Numbers are MUCH easier and faster to process than text fields. If you are completely sure, that you have unique data within column you can use it as primary key.
Importing csv file into table should be also easy:
//just open file in some known way and read it line by line
// we have declared String[] data, String line is line read from your csv somewhere earlier
// in code
data = line.split(",");
//here you have to process values, and execute insert statement
You have to create indexes on every column which will be used to search or order data. Please be also aware, that rows in table has no "default", "natural" or any other order. If you execute this same select statement twice you can get two totally different results in meaning of sorting. So simple select statement should look like that:
select
_id, other_colum_name, some_other_column
from
table_name
where
column_name = 5
and other_column_name = 3
order by
column_name;