I am developing an Activity with a fixed and a dynamic layout part. The dynamic part (and thus the number and type of created widgets) is based on database values this way:
For every database row, I will have a group of widgets. And the components of each group depend on the object type (determined from one of the columns) of that database row.
For saving / restoring instance state, all widgets need to have IDs. I would like to ensure that my own IDs will never conflict with IDs that from the generated R class.
For better handling within the app (finding which widget maps to which field in which data object), a numbering scheme like ID = row * 100 + fieldindex would be helpful. Fieldindex is not exactly a colum number. Every object type should have its own fieldindices.
As the ID values in generated R seem not to have consecutive numbers, I can not just predefine a pool of IDs in R and used these without the need of an additional mapping.
Second reason against a predefined pool: The big number of fieldindices would result in a large ID pool. Third, the size of the ID pool would limit the row count that can be displayed.
Is there a safe number range I can use for my own layout component's IDs ?
Looking at R.java in the gen/ folder, I have the impression that generated IDs are all greater than 0x7f000000. Is that guaranteed ?
And if yes, is the range from 0x00000000 up to 0x7f000000 free to use or is it reserved for android's internal purposes ?
Why do you want to avoid the same id? Only thing that necessary is:
An ID need not be unique throughout the entire tree, but it should be unique within the part of the tree you are searching. So, you can use your formula
ID = row * 100 + fieldindex
I will work fine, even if it is not unique in project.
Related
I am trying to make blocks of data (10 each) as query.
The limitToLast() and limitToFirst() work without each other but crashes the app when together.
query = db_reference_type.limitToLast((int) (long_total_buildings - (long_list_page * 10))).limitToFirst(10);
With long_list_page = 0 and long_total_buildings = 10
query = db_reference_type.limitToLast(10).limitToFirst(10);
The app just crashes when the program gets to that line.
There is no way to combine limitToFirst() and limitToLast() in a single query. You seem to be building a pagination system, and looking for an offset() condition, which doesn't exist in Firebase.
It's easier to understand what is possible once you know how Firebase processes your request.
When it receives a query at a location, Firebase retrieves an index of the items on that location on the property that you order the query on (or on the key if no order is specified).
It then finds the value that you've indicated you want to start returning items from. So this is a value of the property that you order the query on (or on the key if no order is specified).
It then finds the value that you've indicated you want to end returning items at. This too is a value of the property that you order the query on (or on the key if no order is specified).
So at this point the database has a range of values in the index, and by association the keys of the items matching those values.
It then clips the items in the range by either the number of items from the start (if you use limitToFirst()) or from the end (if you use limitToLast).
And then finally it returns the remaining items that match all criteria.
Note that the value you pass to limitToFirst/limitToLast is only used in the last step of this process. It is not used in step 3, which is what you seem to be trying.
Editing my previous question, which boils down to this:
Given the following data structure (object composition):
is it bad design, or is it acceptable, that instead of two related tables, I store the sets of Reminders into a string column of Event table in some serialized way (e.g. JSON):
given that it would simplify my application significantly?
The reasons why I am considering this are:
I don't need the flexibility of accessing Reminders separately;
I always need to query all Reminders per Event and process them in code (e.g. choose the next three reminders based on time and weekday_flags — which is not trivial to do with a where clause);
In the end I need to display a list of Events with associated Reminders as stated above, so ideally I already have a dataset (cursor) with size matching the number of Events that I can feed to the adapter, and not the large join result that needs further processing and re-indexing;
Reminder entity is small and is not going to have more fields in the future, and there usually won't be more than 3-4 reminders per event, therefore storing them as a serialized string is not a size or migration concern.
As pointed out by Christophe Beyls here, the system's serialization/parceling mechanisms cannot be used to persist data because they might change eventually. So it's either JSON or some custom lightweight delimited format.
I'm building an app for Android where I'm reading the instances table to get all events.
I've used the "unique" row id as a way to reference to different instances, however I've now found that the row id changes over time, it actually seems to increment by 2 every now and then. Is there a reason for this behaviour? What is the recommended way to handle instances and how to uniquely reference each instance?
This is the only code I use when creating the meeting objects in the app.
int columnID = cursor.getColumnIndex(CalendarContract.Instances._ID);
String uniqueid = cursor.getString(columnID);
meeting.setUniqueId(uniqueid);
I think you should be using CalendarContract.Instances.EVENT_ID instead as the documentation describes that as the unique ID for events: EVENT_ID
_ID might be changing because they are adding/removing rows under the hood without caring for the changes.
For my Android app, I want to save data using sqlite with this format:
name, date, attr1, attr2, attr3,...
These are the requirements:
each date can only contain each name once
there can be a variable number of attributes(numbers) for each name
each specific name has the same number of attributes
The app will be used to track events throughout the day. Events can have zero or more numeric properties.
The questions are: is sqlite the best way to store things here? If so how do I design my database? What other ways are there to store this kind of data?
is sqlite the best way to store things here?
This will depend on a number of other factors, such as how the data will be queried and used, the volume of transactions, data growth and retention, etc. From what you've described, though, SQLite is a great option, offering functionality out-of-the-box that supports some of your requirements directly, and is commonly used in such cases.
If you don't have much experience with relational databases, implementing this functionality may seem difficult at first, but like learning a new language or framework, it will get easier with time.
If so how do I design my database?
Let's step through each of your enumerated requirements...
each date can only contain each name once
SQLite supports the UNIQUE constraint. For example, if your columns were named name and date, you could add the following to your CREATE TABLE statement:
UNIQUE(name, date)
(A more complete CREATE TABLE statement is in the next example below, and it includes this constraint.)
This constraint prevents the insertion of rows with name/date pairs that already exist. Using android.database.sqlite.SQLiteDatabase, if you attempt to insert a row into the table with a duplicate name/date pair, a SQLiteConstraintException will be thrown at runtime. You will need to handle this exception in your java code.
there can be a variable number of attributes(numbers) for each name
This is a textbook case for normalizing the database, putting your data into multiple tables. For example:
CREATE TABLE names (
name_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
name TEXT NOT NULL,
date DATETIME,
UNIQUE(name, date));
CREATE TABLE attrs (
name_id INTEGER NOT NULL,
attr_value INTEGER NOT NULL,
FOREIGN KEY(attr_value) REFERENCES names(name_id));
Your queries that retrieve attribute data would then JOIN the two tables. Since you indicated that "Events can have zero or more numeric properties", a LEFT OUTER JOIN might be most appropriate, as it will return names and dates even if there are no attributes.
Here's an example query, by name:
SELECT n.name, n.date, a.attr_value
FROM names AS n
LEFT OUTER JOIN attrs AS a
ON n.name_id = a.name_id
WHERE n.name = 'SMITH'
ORDER BY n.name, n.date, a.attr_value;
This query would return results like the following:
name date attr_value
--------------- ---------- ------------
SMITH 2015-02-13 1027
SMITH 2015-02-13 4426
SMITH 2015-02-13 8390
SMITH 2015-02-20 4426
SMITH 2015-02-20 8152
SMITH 2015-02-20 9328
You can then iterate through and process these results in java. If your results include multiple names and/or dates, then in your loop you should keep track of the last used name and date. If the name/date in the current record is the same, the attribute belongs to the current one. If the name/date is different, then this is a new one.
Note that this approach to your database design is flexible, allowing you to query on the attributes, for instance, to see what name/date pairs are associated.
Also note that there is a FOREIGN KEY constraint on the attrs table, meaning that if you attempt to insert a record into that table with a name_id that does not exist in the names table, a SQLiteConstraintException will be thrown at runtime. You will need to handle this exception in your java code.
each specific name has the same number of attributes
You will need to accommodate this requirement in your java code, probably doing some checks in the database prior to performing an INSERT.
What other ways are there to store this kind of data?
Flat files, JSON, XML, third-party data stores (with their own libraries), to name a few.
I'm not sure but I think the best way to achieve your requirement is to use sqlite and to solve your problem you can have 3 columns only. One for the name and one for the date and the other contains a JSON array that represents the rest of the attributes.
I am fetching my data with id which is Integer primary key or integer.
But after deleting any row...
After that if we make select query to show all.
But it will give force close because one id is missing.
I want that id can itself take auto increment & decrement.
when i delete a record at the end(i.g. id=7) after this i add a row then id must be 7 not 8. as same when i delete a row in middle(i.g. id=3) then all the row auto specify by acceding.
your idea can help me.
Most systems with auto-incrementing columns keep track of the last value inserted (or the next one to be inserted) and do not ever reissue a number (give the same number twice), even if the last number issued has been removed from the table.
Judging from what you are asking, SQLite is another such system.
If there is any concurrency in the system, then this is risky, but for a single-user, single-app-at-a-time system, you might get away with:
SELECT MAX(id_column) + 1 FROM YourTable
to find the next available value. Depending on how SQLite behaves, you might be able to embed that in the VALUES list of an INSERT statement:
INSERT INTO YourTable(id_column, ...)
VALUES((SELECT MAX(id_column) + 1 FROM YourTable), ...);
That may not work; you may have to do this as two operations. Note that if there is any concurrency, the two statement form is a bad ideaTM. The primary key unique constraint normally prevents disaster, but one of two concurrent statements fails because it tries to insert a value that the other just inserted - so it has to retry and hope for the best. Clearly, a cell phone has less concurrency than, say, a web server so the problem is correspondingly less severe. But be careful.
On the whole, though, it is best to let gaps appear in the sequence without worrying about it. It is usually not necessary to worry about them. If you must worry about gaps, don't let people make them in the first place. Or move an existing row to fill in the gap when you do a delete that creates one. That still leaves deletes at the end creating gaps when new rows are added, which is why it is best to get over the "it must be a contiguous sequence of numbers" mentality. Auto-increment guarantees uniqueness; it does not guarantee contiguity.