我是android的新手。在我的应用程序中,我创建了一个多对多聊天,并需要从服务器更新消息列表。为了做到这一点,我创建了一个服务,每秒从服务器更新。
我的问题是我不知道如何将数据传回给应用程序。我知道我应该使用意图和广播接收器,但是我坚持使用Bundle对象,我必须序列化以便将它传递给应用程序,这对我来说没有意义,因为这个操作不是那个高效。
现在我正在使用我的应用程序的参考(我认为它不是那么好,但不知道为什么),并且在服务中的服务器每次更新后我都会激活应用程序功能,并直接更新它的字段。此外,我想也许我的代码也会对初学者有所帮助:))
public class UpdateChatService extends Service {
private static final long DELAY_FOR_CHAT_TASK = 0;
private static final long PERIOD_FOR_CHAT_TASK = 1;
private static final TimeUnit TIME_UNIT_CHAT_TASK = TimeUnit.SECONDS;
//private Task retryTask; TODO: check this out
private ScheduledExecutorService scheduler;
private boolean timerRunning = false;
private long RETRY_TIME = 200000;
private long START_TIME = 5000;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
scheduleChatUpdate();
}
private void scheduleChatUpdate() {
BiggerGameApp app = (BiggerGameApp) getApplication();
this.scheduler = Executors.newScheduledThreadPool(3);
this.scheduler.scheduleAtFixedRate(new UpdateChatTask(app),
DELAY_FOR_CHAT_TASK, PERIOD_FOR_CHAT_TASK,
TIME_UNIT_CHAT_TASK);
timerRunning = true;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!timerRunning) {
scheduleChatUpdate();
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
if (scheduler != null) {
scheduler.shutdown();
}
timerRunning = false;
}
}
以下是服务中运行的异步任务的代码。 请告诉我我做错了什么,以及如何将数据从服务传递到应用程序。
public void run() {
try {
if (this.app.getLastMsgFromServer() == null) {
this.app.setLastMsgFromServer(new Message(new Player(DEFAULT_EMAIL), "", -1));
this.app.getLastMsgFromServer().setMessageId(-1);
}
Gson gson = new GsonBuilder()
.registerTypeAdapter(DateTime.class, new DateTimeTypeConverter())
.create();
ServerHandler serverHandler = new ServerHandler();
String jsonString = gson.toJson(this.app.getLastMsgFromServer());
// Sending player to servlet in server
String resultString = serverHandler.getResultFromServlet(jsonString, "GetListOfMessages");
if (resultString.contains("Error")) {
return;
}
// Parsing answer
JSONObject json = new JSONObject(resultString);
Status status = null;
String statusString = json.getString("status");
if (statusString == null || statusString.length() == 0)
return;
status = Status.valueOf(statusString);
if (Status.SUCCESS.equals(status)) {
ArrayList<Message> tempChat = null;
JSONArray jsonList = json.getJSONArray("data");
MyJsonParser jsonParser = new MyJsonParser();
tempChat = jsonParser.getListOfMessagesFromJson(jsonList.toString());
if (tempChat != null && tempChat.size() != 0) {
// After getting the chat from the server, it saves the last msg
// For next syncing with the server
this.app.setLastMsgFromServer(tempChat.get(LAST_MSG_INDEX));
tempChat.addAll(this.app.getChat());
if (tempChat.size() > SIZE_OF_USER_CHAT) {
tempChat = (ArrayList<Message>) tempChat.subList(0, SIZE_OF_USER_CHAT - 1);
}
this.app.setChat(tempChat);
this.app.updateViews(null);
}
}
return;
答案 0 :(得分:2)
服务是否仅限本地(我将假设“是”)?
通过传递android.os.Binder
的实例,可以完成与本地服务的通信,如下所示:
public class UpdateChatService extends Service {
public static final class UpdateChat extends Binder {
UpdateChatService mInstance;
UpdateChat(UpdateChatService instance) {
mInstance = instance;
}
public static UpdateChat asUpdateChat(IBinder binder) {
if (binder instanceof UpdateChat) {
return (UpdateChat) binder;
}
return null;
}
public String pollMessage() {
// Takes a message from the list or returns null
// if the list is empty.
return mInstance.mMessages.poll();
}
public void registerDataSetObserver(DataSetObserver observer) {
mInstance.mObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mInstance.mObservable.unregisterObserver(observer);
}
}
private ScheduledExecutorService mScheduler;
private LinkedList<String> mMessages;
private DataSetObservable mObservable;
@Override
public IBinder onBind(Intent intent) {
return new UpdateChat(this);
}
@Override
public void onCreate() {
super.onCreate();
mObservable = new DataSetObservable();
mMessages = new LinkedList<String>();
mScheduler = Executors.newScheduledThreadPool(3);
mScheduler.scheduleAtFixedRate(new UpdateChatTask(), 0, 1, TimeUnit.SECONDS);
}
@Override
public void onDestroy() {
super.onDestroy();
mScheduler.shutdownNow();
mObservable.notifyInvalidated();
}
class UpdateChatTask implements Runnable {
int mN = 0;
public void run() {
// This example uses a list to keep all received messages, your requirements may vary.
mMessages.add("Message #" + (++mN));
mObservable.notifyChanged();
}
}
}
此示例可用于向Activity
(在这种情况下为ListActivity
)提供,如下所示:
public class ChattrActivity extends ListActivity implements ServiceConnection {
LinkedList<String> mMessages;
ArrayAdapter<String> mAdapter;
UpdateChat mUpdateChat;
DataSetObserver mObserver;
Runnable mNotify;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMessages = new LinkedList<String>();
mNotify = new Runnable() {
public void run() {
mAdapter.notifyDataSetChanged();
}
};
mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mMessages);
getListView().setAdapter(mAdapter);
// Bind to the Service if you do not need it to persist when this Activity
// dies - otherwise you must call #startService(..) before!
bindService(new Intent(this, UpdateChatService.class), this, BIND_AUTO_CREATE);
}
/**
* @see android.app.ListActivity#onDestroy()
*/
@Override
protected void onDestroy() {
super.onDestroy();
if (mUpdateChat != null) {
mUpdateChat.unregisterDataSetObserver(mObserver);
unbindService(this);
}
}
public void onServiceConnected(ComponentName name, IBinder service) {
mUpdateChat = UpdateChat.asUpdateChat(service);
mObserver = new DataSetObserver() {
@Override
public void onChanged() {
String message;
while ((message = mUpdateChat.pollMessage()) != null) {
mMessages.add(message);
}
runOnUiThread(mNotify);
}
@Override
public void onInvalidated() {
// Service was killed - restart or handle this error somehow.
}
};
// We use a DataSetObserver to notify us when a message has been "received".
mUpdateChat.registerDataSetObserver(mObserver);
}
public void onServiceDisconnected(ComponentName name) {
mUpdateChat = null;
}
}
如果您需要跨进程进行通信,则应考虑实现AIDL接口 - 但对于“本地”版本,此模式可以正常工作。不涉及滥用全局Application
实例。
答案 1 :(得分:0)
您可以使用服务与其他应用程序(活动)之间共享的静态内存。如果您不打算将此服务公开给外部应用程序,那么共享静态内存比通过bundle序列化/反序列化数据更好。
鼓励基于捆绑的方法用于暴露于外部世界的组件。典型的应用程序通常只有应用程序清单文件中公开的主要活动。
答案 2 :(得分:0)
如果你的服务没有用,那么静态内存和回调功能都可以。 如果没有,您可以发送广播。