0

私は、オンとオフのライトの数など、部屋のステータスを継続的に更新する 1 つのソケット ベースのアプリケーションを開発しています。この種の部屋が 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);
    } 
}

そして、私はこのサービスを開始し、この値を表示したいアクティビティでブロードキャストされたインテントを取得しています。バックグラウンド サービスから UI を更新するための参照リンクは次のとおりです。

マルチスレッドを使用してこれを達成するにはどうすればよいですか。私の最終的な目標は、ソケットを読み取り、その結果としてステータスを取得することです。

正しい方向に私を指摘してください.どんな提案やアイデアでも大歓迎です.

ありがとう

4

2 に答える 2

1

質問

a)サービスを開始しているものがコードから明らかではありません。それは1回または複数回開始されますか。

現在のコードに基づくと、IPに何かを送信し、結果を読み取り、1つのブロードキャストを送信するように見えます。それだけです。

では、質問です。ライトのステータスを1回だけ更新する必要がありますか、それとも定期的/定期的に更新する必要がありますか?

アイデア

a)ライトのステータスを一度だけ更新する必要があり、UIからトリガーされてUIを更新する場合は、このために特別に設計されたAsyncTaskを使用するとはるかに効果的です。

また、7つの同時AsyncTask(ライトのステータスを並行して更新する場合)を使用するか、ライトのステータスを順次更新して各ライトが更新された後にUIスレッドに報告する1つのAsyncTaskを使用するかはあなた次第です。

b)この場合、ライトのステータスを継続的に追跡する必要がある場合は、サービスを利用することをお勧めします。ただし、このサービスには長時間実行されるスレッドが必要です。したがって、onStartでスレッドを開始する必要があります。

一般に、(たとえば10秒に1回)すべての通信などを引き起こす何らかのメソッドを呼び出す必要があります。

この方法では、Xスレッド(部屋ごとに1つ)に拍車をかけ、これらのスレッドですべての操作(ソケットへの書き込み、読み取り、解析など)を実行するか、この最初のスレッド内でこれらすべてのアクションを実行できます。ここでは、AsyncTaskの場合と同じように、これを並列または直列に実行することができます。

c)また、ライトのステータスを更新する必要がある場合は、すべてのソケットを有効にして再利用し、5秒ごとに再接続しないようにすることもできます。

一般的なコメント

a)非推奨のonStart()を使用しています。onStartCommand()を使用する必要があります

b)プロトタイプである可能性があることは理解していますが、あなたが示したこのコードの品質はかなり低いです。クリーンアップしないと、将来追跡するバグがたくさんあります。

あなたはコードにあります:

  • たくさんのマジックナンバー
  • 誤った名前の関数(何も表示せず、ソケットの読み取り/書き込み、変換、ブロードキャストの送信を行うDisplayLoggingInfoなど)
  • 長いメソッド(DisplayLoggingInfo)

アップデート1

これがあなたのためのサンプルアプリです。これはプロトタイプであることに注意してください。チェックを追加したり、クラスに分けたりすることもできます。

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>
于 2013-02-21T23:52:47.747 に答える
0

Service各部屋に 1 つ、またはすべての部屋に1 つのパフォーマンスについて質問している場合は、Service7 つのサービスが非常に過剰であると考えます。理解しておく必要があることの 1 つは、 aServiceは新しい ではないということThreadです。サービスは と同じスレッドで実行されますActivity。やりたいことは、複数のソケットで接続をリッスンする 1 つの Service を用意し、確立された接続 (部屋) ごとに新しいスレッドを作成することです。他の人が示唆しているAsyncTaskように、メインスレッドへのコールバックを提供するため、バックグラウンドプロセスを処理するのに最適な方法です。ただし、処理できるスレッド数などの制限があります。部屋ごとに 1 つのスレッドを話している場合、これは問題になりません。そうでない場合は、部屋の接続ごとにブロック スレッドを使用することを検討してください。

于 2013-02-27T21:24:25.970 に答える