I have an activity that in onCreate calls an API and populates a RecyclerView with product names, current stock, and an EditText to insert a value for each product.
You can then hit an add or subtract button at the top of the activity and all products with an inserted value will have their stock updated in the database by the given values via the API.
I do not pass the on screen stock values to the API (as another user may have changed it in the meantime), simply the inserted values, product ids and whether to increment/decrement the database value.
Currently, after I send the update request and it is successful, I call finish() and just reload the activity to get the updated data.
I'm wondering if it would be better to make an API call for the data after the update request and then just update the RecyclerView, it would almost be duplicate code of the onCreate but would prevent reloading the activity.
Does anyone have any insight as to the efficiency of this vs reloading the activity? It seems like reloading would be the more inefficient option but i'm not too sure.
Assume in your onCreate method you have something like this:
onCreate() {
setContentView(xx);
callApiGetDataAndSetDataToRecyclerView();
}
If so, pls try to change the code like below after I send the update request and it is successful:
doAfterUpdateRequestSuccessful() {
List<Object> latestData = callApiGetData() // this should not be in the ui thread, I believe you are clear about it but just want to repeat
recyclerViewAdapter.setData(latestData);
recyclerViewAdapter.notifyDataSetChanged();
}
Then your recycler view will be updated with latest data.
And like #ADM's comment, finish and recreate the activity is never a solution for updating recycler view, the ux will be very very bad.
Reload the activity is not so efficient. You should instead move your fetch data and render logic to an independent method and invoke this method from onCreate and every time you want to refresh the rendered data.
Related
If I need to display data coming from an API in a Fragment (using an AsyncTask), let's say a list of items in a RecyclerView, I believe it shouldn't be done in onCreate() or onCreateView() since theoretically the view elements are being initialized and may not be ready to use if the call to the API is faster. Am I correct?
(I assume it's kind of impossible to get a response from an API in less time than it takes for Android to create the view though).
There is onActivityCreated() and onStart() but I am still confused about when the parent Activity calls them.
The thing I want to avoid is reloading data (making a call to the API) if it's not necessary, for instance because of an orientation change or going back to this Activity after a click on the back button from a possible "next" Activity.
Thanks.
If it is your first "window" (Activity or whatever) the only way I know is showing a loading text, image, etc.
If it isn't your first view you can load your data in another window and store it to later usage when the user reaches the View to show the info.
You can load it right in your onCreate, onStart or so, but as you said probably you won't have time to download the info, so again, show a loading page or whatever you want while your data comes.
To avoid initialization errors call your AsyncTask after initializing the elements. And to avoid calling the API multiple times save your data locally while the app is opened, it depends on your app requirements
I have three tabs in my view. Every time when I press the each tab some layout will be inflated and a web service call is done. I am populating some data into my inflated view through this web service call. Everything is working fine. But the problem is I don't want to call the web service every time when I press the tab for the second time. Previous data should be populated automatically without making a call to the web service. I don't think I can use onResume() method for this. Googled out many pages to find this answer but nothing is helpful. Please post the code if necessary. Thanks in advance.
These are my workarounds till now.
TabHost setCurrentTab only calls oncreate method for Activity in Tab once
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
http://jnastase.alner.net/archive/2010/10/27/handling-orientation-change-in-android.aspx
Your webservice should return some data, keep this data to your local memory and check every time either this data is null or not, if null then call service otherwise inflate from local data.
First of all, you should know the state of your 'call': not calling, pending, called. You must store it somewhere (activity, shared preferences, database etc) then making a call. Now, for data: you should implement some caching (again, in activity, shared preferences, database or even in plain files).
Then, in any state of a call, you can show data from cache, if it exists, and when call is done you can store new data in cache and show it.
whenever any changes made in one tab, store value in some variable, whenever next time the page is initialized, initialize with old selected value. Please try it out.. It may solve the problem..
I have an array adapter which is used in my listview. The adapter is periodically updated by fetching or removing contents from a server. I have used a scheduledthreadpoolexecutor to periodically update the adapter and then use adapter.notifydatasetchange();
The list view gets refreshed and removes any items etc, but for example if two items where removed from the list when I scroll the listview on android and get close to the end of the listview the application crashes. I guess something does not get updated in the listview and it things that the size of the list is the initial size.
Do you have something to recommend?
Regards,
Aris
Hi all,
I actually found a solution to my problem and forgot to check here for any replies.
Thank you all for your suggestions.
Basically scheduledthreadpoolexecutor called a runnable (lets call it updateRunnable) to do the updates.
What I did was the following:
In the updateRunnable, when it gets the new data and stores them in the array adapter, it then calls another runnable (lets call it updateListView) using runOnUiThread and in updateListView I set the adapter of the listview.
This solved my problem
If your data is at all database-like, which I assume, given your use of a ListView, then you'll want to refactor your background service into a model that uses a ContentProvider and SyncAdapter to stay in sync with the server, and then automatically notify the ListView through binding it with a CursorAdapter which uses its implementation of ContentObserver to automatically update the list when the underlying DB changes.
Why does ContentResolver.requestSync not trigger a sync? tells you how to set up the ContentProvider.
How to handle REST calls, data persistence, syncing and observing ContentProvider tells you a little more about how list update notification operates once the ContentProvider is syncing.
It's a lot of infrastructure work to get set up, but once you do, there's so much that's wonderfully automatic about the SyncAdapter model.
I had a similar problem once. Since the ListView keeps updating you can
1) display the Listview just as the activity starts in OnCreate, and
2) call this SAME activity so as to display refreshed data in the listview.
but after calling the same activity again, finish() the current instance first immediately since you can get multiple instances of it one over the other.
I have question regarding my previous ListView activity.
I have my ListView which is continue updating using socket connection, now when I click on any of the list row i can go to my next screen now when i come back to my previous ListView screen my ListView is start updating again but i want to keep updating my ListView in a background when i am on my nextscreen.
Something like i want to keep my previous screen alive when i am on my nextscreen.
Sounds to me like your the code you are using to load the data for your ListView is tied to your Activity.
For instance you have an AsyncTask or Thread in your Activity that cointains your ListView and you use it to download data, or do whatever is needed to get the data to populate the list. I also assume you start it in one of the Activity lifecycle methods e.g. onCreate().
If that is the case then you should consider seperating the code used for getting the data for the list from your activity code.
One way to do this is to use a Service which will be able to run independantly of the rest of your application and do all the heavy lifting involed with fetching the data for your list. You can communicate with the service from anywhere in your application. The Service can save the data to a database. Then all you have to do in your Activity is query the database and populate the adapter to get the latest data without much delay.
You can read more about services here:
http://developer.android.com/reference/android/app/Service.html
You could (and probably should) do what Paul suggested or you could change to way you switch your screens by using Fragments or a ViewFlipper. This way you still run your AsyncTask or Thread while doing something else on a different page.
I have a general scenario, but couldn't make out how to handle it.
I have a ListView with each item having different clickable views. Of which 1 is add as friend button beside the user name in the item.
So, in the ListViewAdapter's getView() i implemented onClick for this button this way.
onClick(){
//make the button invisible, for UX
//change the value of is_friend = 1, in the Adapter ArrayList, which will be helpful when listView is scrolled and getView is called again, to make it visible or invisible.
//Send the info to the server as an AsyncTask
}
This works fine.
Problem:
instead of clicking the add as friend button, I can click the user name go to his profile and click the add as friend button in that Activity.
Now when i comeback to the ListView, the add as friend button is still visible, because the adapter ArrayList has old data taken from server and i am not even changing them.
I thought of StartActivityForResult when user name is clicked. But i might not comeback to the ListView as soon as i click add as friend, there are lot of other actions on a user's profile.
A familiar case easily handled by many apps. Any idea on how this is done?
Thank You
EDIT:
Though the answers given below work. They are not the best way to do.
So, a better way might be to make a call to a static method of the listViewAdapter to update that value only in its ArrayList??
The comment of gsingh2011 is valid. However, I am guessing that your remark will be something like "I populate the ArrayList by querying the server and I don't want to do that to often".
More generally speaking, the comment of gsingh can be translated to this: you should base your adapter and 'ViewProfileActivity' on the same data. You can do this by sharing the ArrayList between the two (as a static, or a public member or whatever you want). When you then change something from your 'ViewProfileActivity', your ListView will automatically update once you switch back to it (because getView() will be called on its adapter again, which will generate a view based on the new data).
The text above is an answer to your question, but let me just add some other remarks:
you say you are sending info to a server in an asynctask. You should change this to using an (Intent)Service for that. You don't have any guarantees that your data will be fully sent when your Activity is put in the background. If you delegate this server synchronization to a Service, it will make sure your process is kept around long enough for your send to finish.
once you have that service, that would be a nice place to put your "shared data" as discussed above. You could also use a small database for that and let the service only handle the synchronization between your local database and the remote server. Then you have something that is beginning to look like a REST implementation, where your device is caching remote data locally, but in the end is only visualizing the state of the remote server. You can look up an excellent google i/o presentation on dealing with REST servers. This presentation is also nice if you are not interested in the REST part, because (maybe more importantly) it shows you what things you have to take into account when you want to have guarantee of successful persistence of data.