Поток службы Android, создающий веб-запрос, блокирует пользовательский интерфейс - PullRequest
1 голос
/ 03 января 2012

Сначала я объясню текущую ситуацию. У меня 2 разных потока в 2 сервисах (чтение из службы USB-портов и создание веб-запросов). Я запускаю их в onCreate моей деятельности, как:

serialServiceIntent = new Intent(NDKSerialActivity.this, SerialService.class);
startService(serialServiceIntent);
webServiceIntent = new Intent(NDKSerialActivity.this, RecordWebService.class);
startService(webServiceIntent);

Нет ничего плохого в последовательном обслуживании, но в RecordWebService, когда я делаю запрос, мой графический интерфейс останавливается, пока не придет ответ.

Код такой:

public class RecordWebService extends Service
{
public static final String SERVER_ADDRESS = "http://192.168.1.100:8080/MobilHM/rest";
private static final String TAG = RecordWebService.class.getSimpleName();
private RecordWebThread recordWebThread;

@Override
public void onStart(Intent intent, int startId)
{
    super.onStart(intent, startId);
    recordWebThread = new RecordWebThread(true);
    recordWebThread.start();
}

@Override
public void onDestroy()
{
    super.onDestroy();
    Log.i(TAG, "RecordWebService Destroyed");
}

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

и

public class RecordWebThread extends Thread
{
private static final String TAG = RecordWebThread.class.getSimpleName();
public boolean always;


public RecordWebThread(boolean always)
{
    this.always = always;
}

@Override
public void run()
{
    PatientRecord patientRecord = new PatientRecord();
    while (always)
    {
        RestClient restClient = new RestClient(RecordWebService.SERVER_ADDRESS + "/hello");
        try
        {
            restClient.execute(RequestMethod.GET);
        }
        catch (Exception e1)
        {
            Log.e(TAG, "", e1);
        }
        Log.i(TAG, "Server Response Code:->" + restClient.getResponseCode());
        Log.i(TAG, "Server Response:->" + restClient.getResponse());
        try
        {
            sleep(4 * 1000);
        }
        catch (InterruptedException e)
        {
            Log.e(TAG, "Web service interrupted", e);
        }
    }
}
}

Также я попытался удалить спящую часть и заставить поток работать с таймером и заданием таймера, например:

public void sendRecord()
{
    scanTask = new TimerTask()
    {
        public void run()
        {
            handler.post(new Runnable()
            {
                public void run()
                {
                    RestClient restClient = new RestClient(RecordWebService.SERVER_ADDRESS + "/hello");
                    try
                    {
                        restClient.execute(RequestMethod.GET);
                    }
                    catch (Exception e1)
                    {
                        Log.e(TAG, "", e1);
                    }
                    Log.i(TAG, "Server Response Code:->" + restClient.getResponseCode());
                    Log.i(TAG, "Server Response:->" + restClient.getResponse());
                }
            });
        }
    };
    t.schedule(scanTask, 1000, 4000);
}

но не повезло, мой графический интерфейс зависает, когда дело доходит до restClient.execute.

Вы можете найти RestClient.java @ http://www.giantflyingsaucer.com/blog/?p=1462

Как я могу сделать так, чтобы мои запросы не блокировали мою ветку графического интерфейса?

Edit:

public void sendRecord()
{
    scanTask = new TimerTask()
    {
        public void run()
        {
            RestClient restClient = new RestClient(RecordWebService.SERVER_ADDRESS + "/hello");
            try
            {
                restClient.execute(RequestMethod.GET);
            }
            catch (Exception e1)
            {
                Log.e(TAG, "", e1);
            }
            Log.i(TAG, "Server Response Code:->" + restClient.getResponseCode());
            Log.i(TAG, "Server Response:->" + restClient.getResponse());
        }
    };
    t.schedule(scanTask, 1000, 4000);
}

Без обработчика, я вызываю это в OnCreate моей деятельности, но все еще висит.

Ответы [ 2 ]

1 голос
/ 04 января 2012

Или вы можете использовать IntentService, который будет решать проблемы с потоками для вас.

Это пример класса:

public class MyService extends IntentService {

    public MyService() {
        super("MyService");
    }

    public MyService(String name) {
        super(name);        
    }

    @Override
    protected void onHandleIntent(Intent arg0) {

                //Do what you want
        }
}

Тогда вы просто позвоните:

Intent intent = new Intent(getApplicationContext(),MyService.class);
startService(intent);

Edit:

Чтобы повторять одно и то же каждые 4 секунды, вы должны сделать что-то вроде этого:

 PendingIntent serviceIntent= PendingIntent.getService(context,
                0, new Intent(context, MyService.class), 0);

   long firstTime = SystemClock.elapsedRealtime();
   AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);

   long intervalInSec = 4;

   am.setRepeating(AlarmManager.ELAPSED_REALTIME, firstTime, intervalInSec*1000, serviceIntent)

;

0 голосов
/ 03 января 2012

В вашем коде (2d версия) происходит следующее: вы создаете поток, и он просит поток пользовательского интерфейса выполнить некоторое сетевое взаимодействие. Просто исключите handler.post(...) при выполнении запроса. Позже вы можете использовать это для простого runnable для обновления вашего интерфейса с результатами запроса.

...