Reputation: 11678
I have a background service which receive messages from a server and with those message it updates inner properties of objects which are shown in a ListView.
I always uses the runOnUiThread method to run the listArrayAdapter.notifyOnDataSetChanged() command.
From some reason sometimes the ListView is refreshed and it does show me the property update and sometimes it doesn't..
For testing i've added a "refresh" Button to my ListView and when it pressed the listArrayAdapter.notifyOnDataSetChanged() is executed.
Every click on the button the view is refreshed perfectly..
I can't really understand why when trying to refresh from the service it doesn't always work but i think i maybe not always runs on the UIThread...
I'm really hopeless and will glad to get help..
My Code
ServerConnectionManager.java - extends Service
//example of a command executed when a specific message received from the server:
//app is the Application variable
public void unFriend(int userId)
{
serverResponseManager.onUnFriend(app.getApplicationFriend(userId),false);
}
ServerResponseManager.java - a class that handle all application responses to server messages:
public void onUnFriend(FacebookUser facebookUser, boolean isYouRemovedClient) {
//this is the property which will effect the ListView view when calling the
//arrayListAdataper.notifyOnDataSetChanged();
facebookUser.setApplicationFriend(false);
app.getApplicationFriends().remove(facebookUser);
app.getDatabaseManager().deleteApplicationFriend(facebookUser.getId());
//if the application is currently running in the UI (not on the background) it will run a method inside the BaseActivity
if (app.isApplicationInForeground())
{
app.getCurrentActivity().onUnFriend(facebookUser);
if (isYouRemovedClient)
app.showToast(facebookUser.getName() + " has removed from your friends", true);
else
app.showToast(facebookUser.getName() + " has removed you from friends", true);
}
}
BaseActivity.java - an Activity which set all default configuration for all Activities which extends it
//in this exemple the BaseActivity method does nothing but the ListViewActivity.java method override it
public void onUnFriend(FacebookUser facebookUser)
{
}
ListViewActivity.java - extends BaseActivity and have a ListView in it which should reflect the change in the FacebookUser object property which being made in public void onUnFriend(FacebookUser facebookUser, boolean isYouRemovedClient) in ServerResponseManager.
@Override
public void onUnFriend(FacebookUser facebookUser)
{
updateView();
}
private void updateView()
{
runOnUiThread(updateViewRunnable());
}
private Runnable updateViewRunnable()
{
Runnable run = new Runnable() {
@Override
public void run() {
listArrayAdapter.notifyDataSetChanged();
}
};
return run;
}
Upvotes: 3
Views: 4900
Reputation: 3017
Instead use
notifyDataSetChanged on onDestroy of service.
the list view will get refreshed
Upvotes: 1
Reputation: 3561
You could use a Cursor in your ListView to display your Data. The Service writes/updates the Data in your ContentProvider. At the End of your Database Transaction you simple use:
getContext().getContentResolver().notifyChange(PROVIDER_URI,null);
and your ListView gets updated automaticly.
Upvotes: 1
Reputation: 7075
A Service should usually independent from UI concerns. A great way to decouple services and UI related stuff is the event bus pattern. For Android, check out https://github.com/greenrobot/EventBus.
In the ServerConnectionManager, you could post an event:
EventBus.getDefault().post(new UnfriendEvent(userId));
Now register your activity to the event bus, and the event will be delivered to the activity by calling the onEvent method:
public void onEventMainThread(UnfriendEvent event) {...}
Like this, you decouple your components leading to a neat and clean software design, which is very flexible to changes.
Upvotes: 1
Reputation: 1327
You can use this tutorial for proper architecture of your code
developing an app with a background service
It shows how to receive notifications from the service and update the UI.
runOnUiThread is mostly used before AsyncTask calls are made. I think you should use a handler instead (it updates the UI and allows the thread to run). Try using the handler and see what happens
Upvotes: 0
Reputation: 16082
Don't mix business logic. It looks so complicated that is hard to read.
Activity
where ListView
is, create and register BroadcastReceiver
with IntentFilter
for your update events. onReceive
method of your BroadcastReceiver
handle update events, for example update list.Upvotes: 9