gpt4 book ai didi

java - 使用多个服务或在单个服务中执行所有操作哪个更好?

转载 作者:行者123 更新时间:2023-12-01 14:50:54 24 4
gpt4 key购买 nike

我正在开发一个基于套接字的应用程序,在该应用程序中我不断更新房间的状态,例如有多少盏灯打开和关闭。我有 7 个此类房间,我需要更新每个房间的状态。

所以我的问题是我应该为每个房间创建一个单独的服务还是应该在单个服务中执行所有操作?就性能而言,哪种方式更方便。

这是我的单人间服务等级。

public class UpdateUiService extends Service 
{
@Override
public void onCreate() {
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
try {
s = new Socket("192.168.1.19,502);
i = s.getInputStream();
o = s.getOutputStream();
System.out.println("connected");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

@Override
public void onStart(Intent intent, int startId) {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000); // 1 second

}

private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo();
handler.postDelayed(this, Integer.parseInt(interval_dinning));
}
};

private void DisplayLoggingInfo() {
try {
byte[] data1 = new byte[1024], packet1 =
{
(byte) 0x00,(byte) 0x00,(byte) 0x00,
(byte) 0x00,(byte) 0x00,(byte) 0x06,
(byte) 0x01,(byte) 0x01,(byte) 0x00,
(byte) 0x00,(byte) 0x00,(byte) 0x19
};

o.write(packet1);
i.read(data1, 0, 1024);

byte_to_hex = ConversionMethods.bytesToHex(data1).substring(18, 26);

char[] arr = byte_to_hex.toCharArray();
for (int i = 0; i < arr.length - 1; i += 2) {
char temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}

swapped_result = new String(arr);
result = ConversionMethods.hexStringToNBitBinary(swapped_result, 32);
int counter_ = 0;
for( int i=0; i<result.length(); i++ )
{
if( result.charAt(i) == '1' )
{
counter_++;
}
}
status=Integer.toString(counter_);

} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

intent.putExtra("counter", String.valueOf(++counter));
intent.putExtra("status", status);
sendBroadcast(intent);
}
}

我正在启动此服务并在我想要显示此值的 Activity 中获取广播 Intent 。这是update UI from background service的引用链接.

如何使用多线程实现这一点。我的最终目标是读取套接字并获取状态,仅此而已。

请为我指出正确的方向。任何建议和想法将不胜感激。

谢谢

最佳答案

问题

a)从您的代码中看不出来是什么在启动您的服务。是启动一次还是多次。

根据当前代码,看起来它会向 ip 发送一些内容,读取结果,发送一个广播,仅此而已。

那么,问题是,您需要只更新一次灯光状态还是需要不断/定期更新它们?

想法

a) 在这种情况下,如果您只需要更新一次灯光状态,并且它是从 UI 触发并更新 UI,那么使用 AsyncTask 会更好。这是专门为此设计的。

您是否想要 7 个并发 AsyncTask(如果您想并行更新灯光状态),或者您可以拥有一个 AsyncTask,它将串行更新灯光状态并在每个灯光更新后向 UI 线程报告,这取决于您。已更新。

b) 在这种情况下,如果您需要持续跟踪灯光状态,那么您最好选择一项服务。但是,您需要在此服务中有一个长时间运行的线程。因此,您应该在 onStart 中启动一个线程。

一般来说,它应该(假设每 10 秒一次)调用一些方法来引发所有通信等等。

在该方法中,您可以激发 X 个线程(每个房间一个),并在这些线程中执行所有操作(写入套接字、读取、解析等),或者您可以在第一个线程中执行所有这些操作。您在这里可以选择与 AsyncTask 相同的选择来并行或串行执行此操作。

c) 此外,您可能希望保持所有套接字处于 Activity 状态并重用它们,以便在需要更新灯光状态时不会每 5 秒重新连接一次。

一般评论

a) 您正在使用已弃用的 onStart()。您应该使用 onStartCommand()

b)我知道它可能是一个原型(prototype),但是您展示的这段代码质量相当低。如果你不清理它,你将来会有很多 bug 需要追查:

您的代码如下:

  • 很多神奇的数字
  • 函数命名错误(例如 DisplayLoggingInfo,它不显示任何内容,而是读/写套接字、执行一些转换并发送广播)
  • 长方法 (DisplayLoggingInfo)

更新 1

这是适合您的示例应用程序。请注意,这是一个原型(prototype)。您可能有兴趣添加更多检查,将其分离到更多类等等。

MyService.java

package com.example.servicesample;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import java.lang.Thread;
import android.support.v4.content.LocalBroadcastManager;

public class MyService extends Service implements Runnable {
public static final String ROOM_STATUS_BROADCAST = "com.example.room_status_broadcast";
public static final String ROOM_STATUS_BROADCAST_EXTRA_ROOM_NUMBER = "roomnumber";
public static final String ROOM_STATUS_BROADCAST_EXTRA_STATUS = "status";

static final int NUM_ROOMS = 7;
static final int TIME_FOR_A_REST = 5000; //ms

Thread mThread = null;
Boolean mRunning = false;

@Override
public void onCreate() {
}

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
start();

return START_STICKY;
}

@Override
public void onDestroy() {
stop();
}

private synchronized void start()
{
if (mThread != null)
return;

mRunning = true;
mThread = new Thread(this);
mThread.start();
}

private synchronized void stop()
{
if (mThread == null)
return;

mRunning = true;

try
{
mThread.join();
} catch (InterruptedException e) {}
mThread = null;
}


public void run()
{
while (mRunning)
{
for (int i = 0; i < NUM_ROOMS; i++)
updateRoomStatus(i);

try
{
Thread.sleep(TIME_FOR_A_REST);
} catch (InterruptedException e) {}
}
}

Boolean getRoomStatus(int roomNumber)
{
// Do real communication here (instea of just assigning true)
// It makes sense to move all communication to a separate class from here
Boolean newRoomStatus = true;

return newRoomStatus;
}

void updateRoomStatus(int roomNumber)
{
Boolean newRoomStatus = getRoomStatus(roomNumber);
broadcastRoomStatus(roomNumber, newRoomStatus);
}

void broadcastRoomStatus(int roomNumber, Boolean newRoomStatus)
{
Intent intent = new Intent(ROOM_STATUS_BROADCAST);
intent.putExtra(ROOM_STATUS_BROADCAST_EXTRA_ROOM_NUMBER, roomNumber);
intent.putExtra(ROOM_STATUS_BROADCAST_EXTRA_STATUS, newRoomStatus);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

}

MyActivity.java

package com.example.servicesample;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.Menu;
import com.example.servicesample.MyService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;

public class MainActivity extends Activity {

private IntentFilter mIntentFilter = new IntentFilter(MyService.ROOM_STATUS_BROADCAST);


private BroadcastReceiver mReceiver = new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
MainActivity.this.receivedBroadcast(intent);
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

startMyService();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

void startMyService()
{
// You can move this code to be executed on a button click or something else
// It will start a service
startService(new Intent(this, MyService.class));
}

@Override
protected void onResume()
{
super.onResume();

LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, mIntentFilter);
}

@Override
protected void onPause()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);

super.onPause();
}

private void receivedBroadcast(Intent i) {
Integer roomNumber = i.getIntExtra(MyService.ROOM_STATUS_BROADCAST_EXTRA_ROOM_NUMBER, 0);
Boolean roomStatus = i.getBooleanExtra(MyService.ROOM_STATUS_BROADCAST_EXTRA_STATUS, false);

// Let's do here whatever we want with received status (as example, update UI)
Log.d("SomeTag", "Room number "+roomNumber.toString() + " got new status " + roomStatus.toString());
}

}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.servicesample"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.servicesample.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<service android:name=".MyService"/>

</application>

</manifest>

关于java - 使用多个服务或在单个服务中执行所有操作哪个更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14869079/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com