I have create PreferenceFragment class that reads mypreferences from an xml file
Basically list of Links
In MainActivity class I have create private class AsyncTask that I use to fetch data from website.
MainActivity onCreate method Iam calling execute() method:
new asynObj().execute();
And for onSharedPreferenceChanged() method I call method inside MainActivity:
onSharedPreferenceChanged(){
// I call method to fetch new Data
refetchData()
}
refetchData() method I use it to grab new data from different website, but the problem is that UI does not change again.
public void reloadData() {
new asynObj().execute();
}
My problem is that I want each time onSharedPreferenceChanged() changes I will call reloadData() and fetch new data and use it to update the UI.
My code works fine except for re fetching new data each time
If you are displaying your data in a ListView or RecyclerView, make sure you are calling notifyDataSetChanged in your adapter.
Related
I have displayed some data in a Listview using ListAdapter. Now I want the listview to refresh automatically after x seconds. How can this be done?
I am using AsyncTask to fetch data from Server.
I have tried this:
public void reloadDeviceData() {
handler.postDelayed(runnable = new Runnable() {
public void run() {
new GetDevices().execute(); // this method will contain your almost-finished HTTP calls
handler.postDelayed(this, TIME);
}
}, TIME);
}
What is happening is that the listview does not refresh but instead add items after the current listview.
GetDevices is the class which extends AsyncTask here.
When you get the response from API. just update the adapter list by using follwing line adapter.list.clear() then after adapter.list.addAll(apiList) and then after You just have to notify the listview adapter.
adapter.notifydatasetchanged();
I would recommend :
use recyclerview for performance point of view .
Check Delta difference between new and old list and add /update those items only. For difference you can use either basic collections class methods or DiffUittls lib
I have a simple implementation of RecyclerView with an adapter inside the onResponse method of network call. How can I remove all previous RecyclerView items or refresh RecyclerView?
I have used adapter.notifyDataSetChanged(); and recyclerView.invalidate(); but none of them worked.
I will suggest you use a different approach
use asynchronous method
use variable which array of object, save data you get from network call in that variable
each you call a new request, clear the variable, add data from network call in that variable and refresh the recyclerView
Create a new instance of your adapter and then call recyclerview.setAdapter(newAdapter);
This will remove your old adapter and set the new adapter with the updated items.
If you just want to update the items in the current adapter then create a method inside your adapter to do so:
public void addItems(ArrayList<EventObject> eventList) {
this.eventList.addAll(eventList);
notifyDataSetChanged();
}
And then call adapter.addItems(moreItems);
You need to clear your list before calling notifyDataSetChanged().
Use the following line of code
adapter.clearData();
Don't forget to add this method
public void clearData() {
int size = this.myList.size();
this.myList.clear();
this.notifyItemRangeRemoved(0, size);
}
}
Create your adapter once, outside your OnResponse method. Inside your adapter, have a method for setting the items like:
public void setItems(ArrayList<MyObject> items){
this.items = items;
notifyDataSetChanged();
}
Then in your onResponse method you can call adapter.setItems(items);
Following Steps will help you
After successfully receive response, clear your data set using .clear() method.
Add Newly received data to the model.
Notify the adapter.
Suggestion-
Don't instantiate your adapter, each time after receiving the data.
Use a public method inside your adapter to do this operation also adding the data.
I want to populate a listView with data retrieved from DB asynchronously,
the problem Is that if I set the adapter, it throws null pointer because the data not arrieved yet, when I recieve data one method is executed, so what I can call in this method to populate my listview? I tried passing the layout to this class to populate directly the listview when the data is recieved but don't worked (nothing happened)
I thought using AsyncTask was a good idea adding wait() and when this "retriever data method" is triggered call notify() but I don't know how to call notify() from an asynctask from another class...
I'm also not sure if asynktask is the best way of doing this, any ideas?
I'm using retrofit2 if it helps
Code of listview create/populate
private List<TmOfsDTO> prepareList() {
List<TmOfsDTO> list;
try {
// Create list of items
ListObtainer listObtainer = new ListObtainer(this);
list = listObtainer.getTmOfsDTOList(user); // this method returns list of objects from DB
} catch (Exception e) {
list = null;
e.printStackTrace();
}
return list;
}
private void populateListView(List<TmOfsDTO> lista) {
// Build Adapter
OrderAdapter orderAdapter = new OrderAdapter(this, 0, lista);
// orderAdapter.getView()
Log.d("LSO", ".....");
// Configure listview
//View rootView = View.inflate(this, R.layout.activity_ordenes, null);
ListView listView = (ListView) findViewById(R.id.lvOrdenes);
listView.setAdapter(orderAdapter);
//listView.invalidateViews();
//listView.refreshDrawableState();
Log.d("LSO", ".......");
Last update:
**
I was doing right the notify when I was recieving data, passing the adapter to the class and calling:
orderAdapter.notifyDataSetChanged();
but the problem is I was missing to add each item with:
orderAdapter.add(orden);
before notify, now seem to work good**
As you logcat show above the lista is null. You are passing this list to the adapter. But if you have not initialized the variable lista it will throw a null pointer exception.
Suggest to initialize the List you passing to the adapter. Then when the data comes in you add the data lista and call the method adapter.notifyDataSetChanged()
Following seems to cause the null pointer exception
} catch (Exception e) {
list = null;
e.printStackTrace();
}
So beside initializing you should also not assign null.
You'd be best using a RecyclerView, anyway. This is part of the new support libraries and is way more efficient than the older ListView.
Some key questions here are whether or not the database is local. If your have an sqlite3 database on the phone that you're loading from then you should have written some classes that load the database information into objects that you can store into an array and pass into the RecyclerView.Adapter very easily.
If you are loading this remotely, then you would be 100% better off syncing the data onto your phone using an AsyncTask before trying to load the RecyclerView, otherwise you'll get those errors.
You could load ONE item into an ArrayList from a remote database, pass that to the RecyclerView, and then carry on loading from the remote database and notifying the RecyclerView of a change upon each item being added to the list.
Create a different constructor for your adapter, one that does not receive data to display in it. When you have that, it will not crash.
To get your data inside, create a local List of your items and populate it with something like:
public void setData(List<MyObject> data){
this.mData = data;
notifyDataSetChanged();
}
Also, don't forget to handle possible null pointer errors in methods such as getItem.
lets say we are in viewDidLoad method. I'd suggest you to do the following:
in your adapter class create public method: setData, which calls adapter.notifyDataSetChanged()
send request to backend by passing callback function
display loading/progress dialog
initialize adapter by passing empty array(not null)
when callback is fired and you get the list call adapter's setData and hide the progress dialog.
If you are using Fragments just call setAdapter() another time after data extraction
My implementation of ArrayAdapter is such that it listens for changes in the under lying data. So any changes in the data, the adapter is notified and it calls the notifydataSetChanged()
public class MyAdapter extends ArrayAdapter implements ObjectStateListener {
#Override
public void onObjectStateChanged() {
/*Call appropriate functions as the underlying data as changed.
A good way of doing that would be to retrieve only the positions of the filtered values
so that the original dataholder can be used but display only certain indices
*/
Log.v(TAG, "FilterCriteria changed. Trigger fired");
this.filterPositions = Helper().getFilteredPositions(filterCriteria, mAppartments);
Log.v(TAG, "CALLING NOTIFYDATASETCHANGED()...");
notifyDataSetChanged();
Log.v(TAG, "FINISHED CALLING NOTIFY DATASET CHANGED");
}
}
In the above code the function onObjectStateChanged() is called whenever there is change in the data and in turn it calls notifyDataSetChanged(). To test if the onObjectStateChanged() is called correctly, I have put a bunch of Log statements as you can see. All those logs appear in logcat. But getView() is not getting called after calling notifyDataSetChanged() and hence the listview is not getting refreshed.
Why is this happening? notifyDataSetChanged() is supposed to ensure that getView() gets called and the new data is reflected in the ListView right?
Definition of ObjectStateChangeListener
public interface ObjectStateListener {
public void onObjectStateChanged();
public void listenForStateChange(Object o);
}
If you are deleting or inserting a new value on the list then whenever there is change in adapter list notifystatechange() will be called so just after inserting or deleting the value call notifystatechange () it will refresh the listview.
I've had to stop using notifyDataSetChanged() on my AutoCompleTextViews as they're not refreshing either. I just keep a local copy of the adapter and then reset it with the new dataset when it's changed.
Be sure your ArrayAdapter is set to notify on change (it is by default), and you technically shouldn't even need to make that call to notifyDataSetChanged() based on the docs: http://developer.android.com/reference/android/widget/ArrayAdapter.html
First update the data where you have kept it's reference in the adapter and then call the notifyDataSetChanged(). You will have to pass in the new data as well.
I'm trying to change Roman's Nurik WizardPager so that in one of the steps display some data from my database.
I'm taking a Model and an UI from the library and I modify them so I can have a
DisplayOrderPage with a parameter ArrayList for my data
public DisplayOrderPage(ModelCallbacks callbacks, ArrayList<Salads> ord , String title) {
super(callbacks, ord, title);
}
and a DisplayOrderFragment which is going to display the data.
I can get an ArrayList with my data from my database in the MainActivity but I don't know how to pass that data to the SandwichWizardModel since it's not an Activity.
you can do one thing.. also pass the context of the activity as parameter. And declare a method in the activity which change the gui within a handler .. like this
in Activity
changeGUI(){
new Handler().post(new Runnable(){
// change gui
}
}
and call like
methodInCLasse(this, arrayList);