Correct architecture when accessing data from many different fragments - android

I am working on a Android app which have 5 fragments and some java classes.
I have to be able to read and edit an arraylist containing pojo's from across these fragments and classes. For example updating from the internet and then updating recyclerView in one of the fragments or sorting the objects in a recyclerView in one fragment and have those changes updated in the recyclerView in another fragment.
I have been looking at notifyDatasetChanged, but cannot get it right, when starting an update in the background and then wants it to update onSucceed in the active fragment.
I have been looking on RxJava with the Arraylist as observable, but once again I ran into problems when I wanted to subscribe from multiple fragments.
And of course I did a arraylist in a singleton, but I am pretty sure that is bad coding :-)

I would put the data that is going to be accessed by all of the fragments in a Service. Each Fragment can bind to the service to retrieve a reference to the data and to register a listener (you will have to make a custom one to handle the events that you are interested in) that will tell each Fragment to update its own view. Each Fragment would implement its own Adapter that would wrap the shared data that lives in the Service.

Related

What is the best approach to edit object elements in different fragments

I'm developing an android application in which is needed one object which contains an arraylist of objects to be edited.
The idea is each of the objects in the arraylist is to be edited in a different fragment.
The app is using ORM to sore objects in database, so I need each object from this arraylist to be edited in different fragments and when save button is pressed to collect the objects from the fragments, to update the main object and save it.
Now I'm creating the fragments and using setters I'm setting the objects for each fragment in the main activity:
DailyFragment fragment2 = new DailyFragment();
fragment2.setdaySchedule(daySchedule);
fragment2.setmDayIndex(1);
Using this approach in each fragment I have reference to the needed element of the arraylist, so it is not needed anything to be done when the main object is saved.
I need advise if there are better ways this to be achieved?
I would consider moving your data out of the fragments.
Look into using something like dependency injection (dagger) to create places to keep and modify your data.
Ideally your fragments contain little more than what is needed to display information correctly. If you bundle everything into activities/fragments you'll continuously be hampered by the need to communicate between them.

How to restore Activity with my current Listview Data while switching between activities?

Hello Everyone,
I had do a search on activity retain state.So I am getting to options/solutions for that:-
Using savedInstanceState() and retainInstanceState() methods.
Using Parent Child hierarchy declare in manifest and its working.
(Example Url:-How can I return to a parent activity correctly? I had same problem mention in Note scetion of the answer.That case is match with my problem.
So,I want to retain the activity states just like Whats app(call/chats/contacts fragments).
But In My scenario,I am fetching the contacts from server.So how can I persist my data while switching between chat and my fragment activity?
So while timing to fetch new data of my contact list from server.I want to save ui of my listview/recyclerview with old data previously I had.
Also suggest which method is good from above two methods or need to implement in other way.

Does Android development have any concept analogous to WPF data binding?

I have a List of items that I want in a ListView, and I can make it work with setting a custom adapter every time the List grows, but the program flow is kind of weird and I have problems with persistence. (If I switch tabs, the UI gets rebuilt with an empty ListView.)
Now, in my day job I'm a C# developer, so when I look at this problem I see a WPF ListView bound to an ObservableCollection. Does Android/Java have something like that, a "fire and forget" connection between a UI element and a data structure?
You don't need to replace the adapter every time you change the data. The adapter "adapts" between data and view. There is no need to change the adapter as long as the way it adapts does not change.
Activity / Fragment lifecycle is not necessarily the lifecycle of your data collection. You can for example make a singleton data collection somewhere and use an adapter to display that collection all the time. Call .notifyDataSetChanged() on the adapter if you changed the data.
A persistent data collection in Android is probably best backed by a database. Take a look at LoaderManager & ContentProvider to provide and load data then displayed via CursorAdapter.
There is no automatic way of keeping a bunch of data available outside of your Activity / Fragment / .. lifecycle and it can get quite complicated but that's basically what you have to do if you want to keep data for longer than a given lifecycle. Singletons, Activity#onSaveInstanceState(), Activity#getLastNonConfigurationInstance(), Fragment#setRetainInstance(), ... are useful utilities to keep data in memory, databases are good for persistent data.
You have to do a little bit work yourself but it's possible. Use a ContentProvider as your DataSource. How the data is stored is up to you. I would prefer a SQLite-DB. A content provider has the possibility to add ContentObservers. (See this related question.)
You can write a CourserAdapter to fetch the Data from your content provider. And your ContentObserver should call notifyDataSetChanged() on your adapter. This closes the circle and your UI refreshes itself.
In Addition to zapls answer:
You can also write an adapter which contains a BroadcastReceiver. When your DataSource changes you can send a LocalBroadcast. The broadcast handler just calls notifyDataSetChanged() of your adapter. I think this would work around most of the lifecycle problems because only active elements will get the broadcast.
The google documentation has an example for such a solution.

Multiple ArrayAdapter, single array

I have an ArrayList containing data for displaying. The content changes asynchronously.
I want to display the data in two Activities, both are using an ArrayAdapter (not the same class).
The problem is that ArrayAdapter provides synchronized access and notifications through add, insert and remove. So synchronized access is only possible through one and not two adapers.
The ArrayAdapter itself is not resusable since diffent views are used.
So the question is: what is the recommended architecture for having one ArrayList with multiple ArrayAdapter's?
Update
I would like to clarify. At the moment I have only one ArrayAdapter.
the data is stored in an ArrayList
a service is updating the data in the background via the ArrayAdapter
both Activity and service are accessing the ArrayList via the ArrayAdapter (multithreading synchronisation issues), but this is no issue because ArrayAdapter does the locking
Now I have another activity which should also display the same ArrayList and I don't know what to do. Clearly I need another ArrayAdapter, because the second activity has another layout. This means that two activities and a service are accessing the same ArrayList. The synchronisation of the ArrayAdapter is not sufficient any more, because the locking is in the ArrayAdapter, which means if service and activity 1 are using ArrayAdapter 1, ArrayAdapter 2 will still access and modify the ArrayList.
The content changes asynchronously.
I'm not sure I understand how you use the ArrayList between the two activities. (static field?)
The problem is that ArrayAdapter takes ownership for the array (it
duplicates it).
I don't believe it duplicates it. It stores a reference to it. (correct me if I am wrong)
When Activity2 is activated and creates ArrayAdapter2, the ArrayList
still belongs to ArrayAdapter1.
Both ArrayAdapters should have a reference to the same ArrayList at this point. This means that a change in the ArrayList would be reflected in both adapters.
Use one global array adapter for two activities and observe you async data.
It is not a problem. After changes in arrayList through one adapter, call notifyDataSetChanged() for the other one. That is all you need, IMHO. At least, it is enough for my ArrayList that is also in different Activity with its adapter. And I change it "by hand" and notify the adapter later, too.
The serious problem will be if you'll want to have one ListView with two adapters. But that is a senselees task, I think.
Updating the answer up to the updated question:
So, the problem is not in the two activities that are using the same arraylist by different ArrayAdapters, but in three components using possibly two different arrayadapters. But if you are using the second adapter only for displaying of the same list, as you are writing here, you needn't any additional synchronization at all. Simply call adapter2.notifyDataSetChanged() after every significant change.
The problem could arise only if you are doing simultaneous changes through two different adapters. Each wouldn't be notified in time on the changes made by the other one. As for synchronization between Activities in the case of probable simultaneous writing, you can reach it by notifying after every change focus from one Activity to another.
But writing synchronization between service+adapter1 and activity+adapter2 could be reached only if you'll find youself some important points in your code where the mutual notifications and locking/unlocking should be made.

Keeping ListFragments in a FragmentPager in sync

Let's say I have a list of homogenous items which is likely to be changed in the lifetime of my Activity by user interaction or OS events. The Activity contains a FragmentPager which shows a number of ListFragments.
These fragments share the previously mentioned data but display it in different ways. E.g. they differ in sorting order or display only a subset of the data. Currently each fragment keeps a separate list containing the respective part of the data in the respective order.
When the data changes, basicly every fragment has to be updated. This means resorting or adding/removing items from some of the fragments. What is the best practice to keep the data in the different fragments consistent?
Currently I have some sort of an observer object, which is notified when something changes and subsequently notifies the connected fragments. But there are a couple of problems:
When the app just started, some of the fragments haven't been created by the FragmentPager, so notifying them is impossible.
When swiping through the fragments some of them get paused. In this state, they can't update their list. Should they disconnect from the observer in this case? This leads to:
When a change happens, while a fragment is disconnected, it basicly misses it.
And so on...
If I understood your ViewPager shows the same data (or it's portion) but in different views. So, I belive ViewPager shouldn't act in any way when data is changed, it's responsibility of Adapter.
About points below you said:
a) creating of fragments inside ViewPager can be managed by you. Just see javadoc of ViewPager::setOffscreenPageLimit(int limit) method.
b) I think you should do nothing with UI when data changed but fragment is in paused state. If you want to update do it in onResume(). Or better to set some field in DB (if you have) to "updates present" state and check it when Activity(Fragment) appears.
c) As in previous option - if fragment disconnected just ignore updates. Or if you really interested in that update use sticky BroadcastReciver (be carefull sticky BR is expensive thing)
You can keep your data in Application class, update only visible fragments when data has changed, and always ask for the new data in Fragment's onResume(), that'll do it
What I would do is have each ListFragment use a Loader to load its data. Then, instead of having the observer notify the Fragment (which might have been killed) to refresh its data, register an observer for each Loader so that it will know when the data source has changed, and will re-query when one has been detected. (If your data source is an SQLite database and you are using a ContentProvider, the CursorLoader will do all of this for you).
This is the implementation I would recommend because
Each Fragments behavior remains self-contained (i.e. each is a re-usable component that is not tied to any specific ViewPager or Activity).
It avoids the complexities of having to deal with potentially destroyed Fragments within your ViewPager.
If you need a quick fix, you could probably get away with forcing the Fragments to remain in memory using ViewPager#setOffScreenPageLimit(int limit) as Ivan suggests... however, this isn't as clean of a solution in my opinion.

Categories

Resources