android - 如何以正确的方式在服务及其应用程序之间传递数据?

标签 android android-intent chat android-service android-asynctask

我是安卓新手。在我的应用程序中,我创建了多对多聊天,并且需要从服务器更新消息列表。为此,我创建了一项每秒从服务器更新的服务。

我的问题是我不知道如何将数据传递回应用程序。我知道我应该使用 Intent 和广播接收器来完成此操作,但是我坚持使用 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;

最佳答案

该服务是否仅限本地(我假设"is")?

与仅本地服务的通信可以通过传回 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 接口(interface) - 但对于“本地”版本,此模式工作得很好并且不涉及滥用全局 Application 实例。

关于android - 如何以正确的方式在服务及其应用程序之间传递数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9257241/

相关文章:

javascript - Symfony 5 与 Pusher 私有(private)聊天

vb.net - 如何在 VB.NET WinForms 应用程序中创建聊天气泡

android - 如何以编程方式删除 ImageButton 的填充?

android - 如何读取NFC标签的NDEF Msg和Records?

Android Activity 服务通信

android - 如何从 sony smartwatch 2 更改主机应用程序中的文本?

android - ACTION_SEND 不分享网址,没有解释

audio - Dialogflow,从音频中检测意图

asp.net - 与 ASP.NET 和 SQL Server 聊天

android - OnProvideAssistDataListener 示例