2

我是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

您可以使用靜態內存在您的服務和其他應用程序(活動)之間共享。如果您不打算將此服務公開給外部應用程序,那麼共享靜態內存比通過捆綁包序列化/反序列化數據更好。

對於要暴露於外界的組件,鼓勵使用基於分組的方法。典型的應用程序通常只在應用程序清單文件中顯示主要活動。

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實例。

相關問題