Obslužné rutiny HTTP se používají ke generování obsahu odpovědi pro požadavek HTTP. Ke konfiguraci obsluhy požadavku můžeme použít obslužné rutiny HTTP. Při zpracování jednoho požadavku můžeme použít více různých modulů, ale k požadavku lze přiřadit pouze jeden http handler.

Obslužná rutina HTTP je třída, která implementuje rozhraní System.Web.IHttpHandler. Toto rozhraní definuje jednu metodu a jednu vlastnost:

  • ProcessRequest(context) : tato metoda bere jako parametr objekt kontextu požadavku HttpContext a generuje odpověď klientovi
  • IsReusable: Tato vlastnost označuje, zda bude tento handler používán jinými požadavky

Obslužnou rutinu HTTP vybere systém poté, co dojde k události MapRequestHandler. A ihned po výběru obslužné rutiny se spustí událost PostMapRequestHandler

Přímé generování odpovědi handlerem nastává po události PreRequestHandlerExecute – po této události je zavolána metoda ProcessRequest a je vygenerována odpověď. A ihned po vygenerování odpovědi dojde k události PostRequestHandlerExecute

Podívejme se na příklad. Vytvořme si vlastní jednoduchý Http handler.

Chcete-li to provést, nejprve definujte adresář v projektu Manipulátory, který bude obsahovat soubory handleru. Poté do tohoto adresáře přidáme novou třídu UserInfoHandler:

public class UserInfoHandler : IHttpHandler < public void ProcessRequest(HttpContext context) < string result +context.Request.UserHostAddress+"

"; výsledek+ +context.Request.UserAgent+"

"; context.Response.Write(result); > public bool IsReusable > >

Obslužná rutina jednoduše vrátí ip a data řetězce user-agent klientovi.

Nyní musí být tento handler připojen ke zpracování požadavku. To lze provést dvěma způsoby. Prvním způsobem je zavolat psovoda prostřednictvím obsluhy trasy. Chcete-li to provést, otevřete soubor RouteConfig a změňte jeho obsah následovně:

pomocí LifeCycleApp.Handlers; pomocí systému; pomocí System.Collections.Generic; pomocí System.Linq; pomocí System.Web; pomocí System.Web.Mvc; pomocí System.Web.Routing; jmenný prostor LifeCycleApp ); > > // class handler třídy CustomRouteHandler : IRouteHandler > >

Výraz routes.Add(new Route(“handler/”, new CustomRouteHandler())) přidá novou trasu, která zpracovává třídu CustomRouteHandler. Tento obslužný program směrování bude volat výše definovaný obslužný program HTTP.

Druhým způsobem je definovat handler v souboru web.config. Chcete-li to provést, v konfiguračním souboru v uzlu system.webServer (pokud neexistuje, musíte jej vytvořit) napíšeme definici handleru:

Všechny handlery jsou specifikovány v elementu handlers. Každá definice má následující atributy:

  • jméno : jedinečný název handleru
  • cesta : URL požadavek, který bude zpracován handlerem
  • sloveso: typ požadavku, například GET. Můžeme také zadat jakýkoli typ požadavku – v tomto případě se používá hvězdička (*).
  • typ : úplný typ třídy handler
ČTĚTE VÍCE
Kolik je celkem kostí?

Kromě registrace do web.config musíme přidat i ignorování trasy v souboru RouteConfig.cs, jinak směrovací systém tuto trasu nezpracuje správně:

public class RouteConfig ); >>

Třída android.os.Handler je další vývoj vláken, který zjednodušuje kód. Psovod lze použít k naplánování spuštění kódu v určitém okamžiku v budoucnu. Třídu lze také použít k předání kódu, který by měl být spuštěn v jiném vláknu programu.

Handler

Podívejme se na nejjednodušší možný příklad pro seznámení

private Handler mHandler; boolean gameOn; long startTime; @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startTime = System.currentTimeMillis(); mHandler = new Handler()< public void handleMessage(Message msg)< super.handleMessage(msg); if(gameOn) < long seconds = ((System.currentTimeMillis() - startTime)) / 1000; Log.i("info", "seconds text-warning">Периодическое выполнение задачи 

При сложных вычислениях может понадобиться очередь Runnable-объектов. Помещая объект в очередь, вы можете задать время его запуска. Для демонстрации использования обработчика потока напишем программу, запускающую фоновый процесс, который будет каждые 200 миллисекунд получать текущее время и обновлять текст. Нам понадобится кнопка Пуск и две текстовые метки, в которых будет отображаться время и количество нажатий кнопки:

package ru.alexanderklimov.handler; import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.TextView; public class MainActivity extends AppCompatActivity < // считаем нажатия кнопки private int mButtonPressed = 0; // счетчик времени private long mTime = 0L; private TextView mCounterTextView; private TextView mTimeTextView; // обработчик потока - обновляет сведения о времени // Создаётся в основном UI-потоке private Handler mHandler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTimeTextView = (TextView) findViewById(R.id.textViewTime); mCounterTextView = (TextView) findViewById(R.id.textViewCounter); if (mTime == 0L) < mTime = SystemClock.uptimeMillis(); mHandler.removeCallbacks(timeUpdaterRunnable); // Добавляем Runnable-объект timeUpdaterRunnable в очередь // сообщений, объект должен быть запущен после задержки в 100 мс mHandler.postDelayed(timeUpdaterRunnable, 100); >> // Описание Runnable-объекта private Runnable timeUpdaterRunnable = new Runnable() < public void run() < // вычисляем время final long start = mTime; long millis = SystemClock.uptimeMillis() - start; int second = (int) (millis / 1000); int min = second / 60; second = second % 60; // выводим время mTimeTextView.setText("" + min + ":" + String.format("%02d", second)); // повторяем через каждые 200 миллисекунд mHandler.postDelayed(this, 200); >>; @Override protected void onPause() < // Удаляем Runnable-объект для прекращения задачи mHandler.removeCallbacks(timeUpdaterRunnable); super.onPause(); >@Override protected void onResume() < super.onResume(); // Добавляем Runnable-объект mHandler.postDelayed(timeUpdaterRunnable, 100); >public void onClick(View v) < mCounterTextView.setText("" + ++mButtonPressed); >> 

На экране будет отображаться время и одновременно мы можем нажимать на кнопку. Эти действия не мешают друг другу, так как работают в разных потоках.

Handler and Runnable

Кроме метода postDelayed() вы можете использовать метод postAtTime():

postAtTime(Runnable r, long uptimeMillis) 

В этом случае объект r добавляется в очередь сообщений, запуск объекта производится во время, заданное вторым параметром.

Самый простой способ помещения объекта в очередь - метод post(), когда указывается только помещаемый объект без указания времени выполнения объекта:

post(Runnable r) 

Пример с индикатором прогресса

Всё, что вам нужно - создать экземпляр класса Handler в классе активности. Поток будет работать с объектом Handler, который в свою очередь, будет обновлять шкалу индикатора в основном потоке активности.

Чтобы послать сообщение в объект Handler, сначала необходимо вызвать метод obtainMessage(), чтобы извлечь объект Message из глобального пула сообщений.

Для вставки сообщения в очередь сообщений объекта Handler существует несколько методов:

  • sendMessage() — помещает сообщение в очередь немедленно (в конец очереди)
  • sendMessageAtFrontofQueue() — помещает сообщение в очередь немедленно и, кроме того, помещает это сообщение впереди очереди (по умолчанию оно ставится в конец очереди), таким образом ваше сообщение берет приоритет над всеми другими
  • sendMessageAtTime() — помещает сообщение в очередь в установленное время в миллисекундах
  • sendMessageDeiayed() — помещает сообщение в очередь после задержки, выраженной в миллисекундах

Чтобы обрабатывать эти сообщения, для объекта Handler необходимо реализовать метод обратного вызова handleMessage(), который будет вызываться каждым сообщением из очереди сообщения.

Для примера создадим приложение с ProgressBar, который будет отображать ход выполнения длительной задачи (это будет простой цикл с приостановкой потока на 1 секунду в каждой итерации цикла) и обновлять степень завершения этой задачи через объект Handler в классе активности.

package ru.alexanderklimov.progressbar; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.ProgressBar; public class ProgressBarDemoActivity extends Activity < ProgressBar mProgressBar; int mProgress = 0; @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mProgressBar = (ProgressBar) findViewById(R.id.progressBarHorizontal); new Thread(myThread).start(); >private Runnable myThread = new Runnable() < @Override public void run() < while (mProgress < 100) < try < myHandler.sendMessage(myHandler.obtainMessage()); Thread.sleep(1000); >catch (Throwable t) < >> > Handler myHandler = new Handler() < @Override public void handleMessage(Message msg) < mProgress++; mProgressBar.setProgress(mProgress); >>; >; > 

ProgressBar

Splash-screen

Очень часто программисты используют Handler для реализации окна приветствия, которое автоматически закрывается и следом запускается основная активность игры или приложения.

public classSplashActivity extends Activity < @Override protected voidonCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); newHandler().postDelayed(new Runnable() < @Override public void run() < startActivity(newIntent( SplashActivity.this, MainMenuActivity.class)); finish(); >>, 2000); > >