My firebase contains different data trees like Users, hobbies, class, scores etc. I want to get values from two sets of data “Users” and “hobbies”.
What is the best way to get values from the two tables?
Should I use firebaseDatabase.getReference() and then
dataSnapshot.child("Users").child(“name”).getValue().toString();
dataSnapshot.child("hobbies ").child(“track”).getValue().toString();
Or do I have to firebaseDatabase.getReference(“Users”) and firebaseDatabase.getReference(“hobbies”);
Since I noticed that firebaseDatabase.getReference() seem to refer to all data including the ones that are not needed(class, scores etc). Will this cause the app to slow down or does it have any implications?
If you attach a listener to a DatabaseReference, it will download/read all data under that reference. So if you attach a listener to FirebaseDatabase.getInstance().getReference(), you are reading all data in your database.
If you only need a subset of all data in your app, it's more efficient to only load that data. This means that you'll need to attach a separate listener to each branch of data that you need.
Related
Now I am working on Android application which has one main Activity that is displaying some data via GLSurface. This data can be changed in many ways. For this I have several fragments with some lists of variants with extra logic. Problem is that I need somehow transfer data from one place to another.
For example:
I have fragment with list of elements. I used RecyclerView with custom adapter. I am filling list with data from DB. SomeThingDBEntity for example. When I am getting it from Room DB (using Room entities), but it has some extra fields that only required for showing elements in RecyclerView. I need to send user's choice from adapter to fragment, then from fragment to activity, than activity sends it to some class that incapsulates logic of work with GLSurface. SomeThingGLentity for example. Now I am passing only fields, that requered by SomeThingGLentity for showing data (int, String etc.), but in future this list can grow. I can also send directly SomeThingDBEntity and get required fields only in the end when apply changes to SomeThingGLentity. But is it OK to use Room DB entity this way?
Is there any better way of doing this? I can also create third class which will only contain required fields. But where to place and how to call it? Maybe there are some patterns or guidelines of best way of doing it...
It looks like you need a data mapper. Something similar to this - https://github.com/android10/Android-CleanArchitecture/blob/master/data/src/main/java/com/fernandocejas/android10/sample/data/entity/mapper/UserEntityDataMapper.java.
If you use this approach, you will be able to encapsulate the transformation logic from your DBEntity to your BusinessEntity, and if you will change the data format in one of them, only your mapper will need to be edited.
According to a response made by Yigit Boyar from Google, Live Data is not the best use case for a chat app, because it may lose displaying some items if they come at the same time. He recommends using the new Google's Paging Library. I've been using ItemKeyedDataSource for my inbox(all the people that have message the user), and the inside chat(the messages themselves). The problems are the following:
1- From the chat, when the user scrolls downwards, the user retrieves old messages, which means that the insertion of those messages should be in position 0 of the adapter, not sequentially like the paging library does. How can I alternate the position of the inserted items to be sequentially for new messages, and in position 0 for old messages?
2- From the inbox(people that have message the user), again I'm using ItemKeyedDataSource here, the problem is that I want to maintain the multiple document listener from the repository (I'm using Firebase Firestore), so I can detect every time a new person talks to the user. The problem is that callback.onResult is called only once, and fails when Firebase sends another user. How can I maintain an update-able list?
I understand that this answer is probably too late, but maybe it can help someone in future.
Position of item in RecyclerView is determined by the position of corresponding data object (of type T) inside PagedList<T>. PagedList is designed to look alike good old List<T>, but can be thought of as an "endless" list of elements.
PagedList gets its elements by pages on demand through something called DataSource.Factory. A Factory is used because DataSource by itself can only grow in one direction. If you need to prepend elements in PagedList, or change or remove existing elements you must invalidate the DataSource and a new instance will be created through DataSource.Factory.
So, to insert your data elements where you want them you should implement your own DataSource and DataSource.Factory by subclassing these base classes.
Note: Room, data persistence library from AndroidX, provides facilities to automatically generate instances of these classes for your data. You can write SQL query like this:
SELECT * FROM messages WHERE threadId=:threadId ORDER BY timestamp DESC
then get DataSource.Factory from this, use the factory to create LivaData<PagedList<Message>> and finally use the paged list to display messages in a RecyclerView in a chat application. Then, when you insert, update or remove data inside DB these changes will automatically propagate to the UI. This can be very useful.
I recommend you to read a few related examples a do codelabs:
https://codelabs.developers.google.com/codelabs/android-paging/#0
https://github.com/googlesamples/android-architecture-components/tree/master/PagingSample
https://github.com/googlesamples/android-architecture-components/tree/master/PagingWithNetworkSample
I was reading the doc about observing queries.
Query<Task> query = taskBox.query().equal(Task_.completed, false).build();
subscription = query.subscribe().observer(data -> updateUi(data));
From what i understand , this code returns all the data every time. but for RecyclerView add/remove animation to work, we need to know which data is changed and we need to know what kind of change is happened to data (remove/change/add).
is there anyway to get changed data only?
It's not a responsibility of ObjectBox to define a change. There is DiffUtil that responsible for that in android. If you google that you can find tons of examples (e.g. sample). The only advice there is to put DiffUtil payload to background thread if your list contains lots of items or items are fat(contain dozens of fields).
Assume we have an Activity with n TextViews that represent one line notes. These notes are stored somewhere (local database, network etc), and each time onResume() being called, the proper number of TextViews are drawn according to that stored data.
Now, lets say the user want to delete a note, what would be the best way the resolve the specific TextView, back to its storage entity?
At the moment, the only way I know is by using View.Tag, and having some manager to translate it to data entity, but it look rather messy.
Are there any other options?
In Android, the Adapter acts a bridge between the view and the data model. You could display the n TextViews in either a ListView or a GridView, and when the user adds or deletes a note, the local or server database is first updated. Upon completion of the web service call and/or the local database update, the new data is added to the underlying Adapter. The View is then refreshed by calling adapter.notifyDataSetChanged(). This would be the way to do it.
Approaches:
If updating the local SQLite database, you could consider using a
CursorAdpater
to hold the data for the View, as it directly maps the entries in
the local database to the View.
If making use of a ContentProvider, it is even possible to combine
a CursorAdapter with a
LoaderManager
and a
CursorLoader:
these plug into the Activity / Fragment life-cycle and monitor
the underlying ContentProvider for changes that are published
automatically to the View on a separate thread.
It is also possible to use a
Filter
in conjunction with the Adapter to define a dynamic mechanism that
sorts the data entries on-the-fly. The filtering is performed by the
Filter on a separate thread, as per a query entered by the user,
possibly in an
AutoCompleteTextView.
References:
See the Retrieving a List of
Contacts
tutorial. The example here retrieves a set of contacts from the
contacts ContentProvider based on a dynamic, alphabetical search by
the user. It makes use of CursorAdapter, CursorLoader and
LoaderManager to monitor and update the data, and it displays the
search results in a ListView.
See also the Android Realtime (Instant) Search with Filter Class example, which shows how a Filter is to be used.
Android AutoCompleteTextView with Custom Adapter filtering.
Android AutocompleteTextView using ArrayAdapter and Filter.
My music app is referencing persistently stored data. All are currently stored as text files:
Favorites - single text file array. App starts, reads the text file, stores in memory. Array is checked when ListView is expanded. If array changes text file is rewritten.
Last Played - single text file array list. Updated every 5 seconds. Retains the history of the played songs to allow the user to return to any album and resume position.
Playlists - currently individual text files, one for each list. List of playlists generated from file names when required. Each playlist text file has array list inside it. Read Write when required.
Most Played - single text file array list. Updated once per song played.
I am wondering whether this data would warrant the need to change to a database, or whether I have taken the right approach. I don't foresee the need for adding additional data so this should be the most I would need.
Advice please!
You can store the text files in SharedPreference and it should work well.
Database if preferable if a lot of data needs to be stored. Using a database is more optimal than parsing a string.
The correct approach is to create a class for each of the things you want to represent, e.g. favourites. Each class has a save() and reload() method. The point is that you can change the underlying storage mechanism in the save() and reload() methods without having to change the rest of your code. Imagine in the future, you want to enable saving to Dropbox. You would simply change these methods and your app would just work (OK, you'd need to add stuff to get Dropbox account details but you get the idea).
You could go further and define Interfaces for loading and saving. That interface can use a single class responsible for nothing except saving and loading. As long as any consumer and provider classes adhere to the interface, you can mix and match, and even implement storage approaches yet to be invented, without recoding your app. You only have one class to work with if, and whenever, you change your storage approach.
class StorageManager(){
enum DataType {Favourites, MostPlayed, PlayList };
...
public save(DataType dataType){
if (dataType == DataType.Favourites){
saveFavouritesToDB();
...
...
}
This approach gives you maximum flexibility, maximum future proofing and better maintainability.
I think it would be better to go with Database.
The database should provide you with some optimizations, performance improvements and basically you don't have to reinvent the wheel (doing read / write operations on the disk, use some buffers before rewriting, and the like).
Plus, I think you will love the way all code will be organized and split into its own layers once you start using this way.