In my app I get some data from server in json. Then I fetch fields from json and fill my RecyclerView list with custom adapter. This list is filled with data about jobs. When I click on a job of my recyclerView I move from hosting fragment to dialogfragment for viewing it. This dialogFragment contains homesUp button after pressing which I return to hosting activity. At this dialogFragment I have button which send request to server about this job for adding it to another DB at server.
But when I press this button and send request to the server then after returning to hosting activity I see that data of selected isn't changed. I have several ways of solving this problem:
Add to my Singleton class variable of ArrayList which will be filled by data of shown job and then I will check whether my Arraylist from Singleton contains this id
another method - notifyItemChanged()
All these methods don't work because my list is filled by old data and I only dismiss dialogFragment and return to fragment which contains the list with old data.
Only one way - send request to server for filling the list again.
So, I need your help or useful advice :)
You need to broadcast changed data from dialog fragment to previous screen. For doing this can use LocalBroadcastManager or rxjava or even live data.
Or create a pagedlistadapter from paging library released in android architecture complement and load data directly from query.
Reference: https://developer.android.com/topic/libraries/architecture/paging
Related
I have a question that is more related to proper design and architecture of MVVM than to coding itself. In my project I have a situation that on ViewModel is suplying data, that are later used in RecyclerView.Adapter to create a proper view.
However I wonder if this would be also correct (from proper 'way of doing things' POV) if some of the data would be supplied in form of id's to be further fetched from Room or external server? For instance during onBindViewHolder use some LiveData with observe() to update certain fields on succesfull load.
Doing data fetch in the views is a no-go. It defeats the very purpose of MVVM and in particular the Android Jetpack efforts. One of the big reason is the data needs to survive configurations. Putting "data fetching" mechanism in the view defeats that as the view can be destroyed and recreated anytime when need be.
So I would suggest you make sure all calls to the network or any other source of data for that matter revolve around the ViewModel and never a view. Let the VM feed the data to the View through observer.
Exception to what I have just said is such use case as loading images with Picasso or Glide where by you feed them URL and they load image. But that's a different thing as they are designed to handle that.
UPDATE with followup Questions
it's ok to put observe() still inside Adapter, during the binding process?
No! Data sent to the adapter must be complete in the purpose it is supposed to serve. For example, if you have to do list app and your Top-Level Activity displays all Todos, then you must feed adapter will complete data (Title, Created time, et al).
The data that are not going to be displayed (like descriptions or sub-to-do-lists) and aren't necessary to identify specific to do should not be fetched (unless you want to store them for sole purpose of avoiding a second network call and pass them to the next activity as serialized data).
When user clicks specific To-Do, then launch new activity with its own ViewModel that will fetch details for that activity (assuming you passed some ID with intent).
If the first, then I understand that observe() should not only update data, but also populate it later to Observer and call notifyDataSetChanged(), right?
Observe is a way to post data to the view when either it have changed or the old view was destroyed and so the new view is being given the same old data that survived the "view death". So it is in the same method where updating data of the Adapter should be done and hence call to notifyDataSetChanged() or similar methods.
I hope that makes it clear.
I think it's best to keep the ViewModel separate from the Adapter. From what I'm gathering you want to basically have each list item load it's own data from Room by having each list item observe on a particular ID for that item. This sounds rather inefficient as you're basically having each item execute a query on the database (or network call) to retrieve just one item for all items that are going to be displayed, think about how it will scale if you were displaying a 100 items. I think it's best that you just execute one query to get the list of data and set the data to the list items in the adapter, keep it simple. Note that onBindViewHolder() doesn't just get called once but multiple times when you're scrolling the screen, so it could get quite ugly if you're trying to lazily load every list item.
I am new to android development and I want to perform a network call of calling firebase database to fill array list with records. I want to create different fragment based on the object properties present in arraylist. Network calls take too much time, so what is the proper way to perform such task.
Here is the steps you should do:
In first time:
In your Activity just run a background service that will fetch the list of Objects. After fetching list you store the list item's in local storage like shared preferences or database. After saving data you open your fragment.
After First Time:
Check is there you have saved list item? if list contains data then directly open your desired fragment. At the same time you update the list items using service call.
Here is some related links:
https://www.tutorialspoint.com/android/android_services.htm
https://www.tutorialspoint.com/android/android_shared_preferences.htm
Hope this will help you.
We are using Retrofit and Activeandroid for my project.
Currently we are facing an issue.
The pattern which we follow in our project is, We get data from server and save it into local database and after data saved we call routine which fetches data from database and populate UI this all happens in single Activity..
Now we have an activity which makes 3 server request, and due to which the amount of code in activity increased.
We are trying to reduce Activity code by creating fragment for the activity and giving responsibility of fetching data and displaying data to Fragment. Rest call will be made by activity. Now once the data is loaded from all the 3 request we need to inform fragment about data is loaded, what is the best way for this.
And is it even possible to send data to fragment once it is loaded.. or the approach we are following is not correct..
Please guide us on this..
Edit1
I read about EventBus. Can event bus solve this problem or it will effect the efficiency.
If you are storing those Fragment instances in your Activity then it will be much easier.
1) Create loadNewdata(DataType data) method in your Fragment.
2) Pass the data into the Fragment after getting response from server in your Activity
((YourFragment)fragment).loadNewdata(yourData);
I would suggest to use Otto.
By this you do not need to store your data in local db(if you don't want it).Just simply post your responce whenever you received from rest API. As Otto also provides the functionality of sharing custom objects between fragments/Activity. It also helps you to make your code modular.
You will find a working example here & here.
You can use Interfaces for this and send data to activity.when response come back pass reference of to show which fragment data needs to be populate the UI.
I am trying to achieve Many to one mapping in ListView and populate elements relating to that item from the database
Hello I am trying to solve a problem which involves launching an activity on click of an item
I am successful on launching an activity on click of an element
I have a requirement and need some ideas on how to achieve that
As I said onclick of an item I launch an activity as many to one
mapping, Suppose I click an element Item-1 the activity should
populate the text-views in the new activity from elements related to
that activity
Again same if I click item-2 it should populate the text-views of in
the same new activity with elements related to that item 2 activity
from the database
Many to one mapping is must I am trying to achieve
Any ideas on how to achieve this
Any links to understand the concept will be helpful
Ps:: I am retrieving data from server as JSON resonse
1) You can use an array adapter or base adapter to populate your list view. Syntax and concepts are well explained on the developer's website.
2) For the list, setup an OnItemClickListener and inside the function, pass an intent to the next activity. While passing the intent, use the putExtra feature to pass your item selected details to the next activity.
3) In your next activity, get the data from the previous activity and use the data to traverse the JSON response from the server. Using an Async Task will be essential at this juncture. You can get an idea about Async Task by just googling it. Many great tutorials are available.
4) When you get any data from the server, create dynamic textViews to display your data.
References:
Developer's Website
Lets say I have 2 activities:
A: A ListView displaying articles titles. Data is fetched from a web server and converted from XML to a list of ArticleSummary. Only user titles and id are returned by the server. Click on a title starts activity B.
B: A form to edit an article. Article is fetched from server. When the user hits OK, modifications are sent to the server and activity closed.
When the user go back to activity A, I would like to update the article title without any additional web request.
I was thinking about the following solution:
When article is modified, send a broadcast event with article id and new attributes values.
Listen for this event on activity A
Update the ArticleSummary object
notify data changed on ListView
Is there a better approach ?
If you want to have a shared data model between different Activities, you can place it in an extension of the Application class. Or, you can use a singleton. Just reload the data from the shared location when the ListView activity is restarted.
As Fredley alluded to, if you have are communicating with a server you should be sure to do so in a separate background thread.
you can also use startActivityForResult() to launch activity and managed returned data.
Check the "Returning a Result from a Screen" section in the part below.
http://developer.android.com/guide/appendix/faq/commontasks.html