Środowisko Xamarin dla deweloperów języka Java
Jeśli jesteś deweloperem języka Java, możesz wykorzystać swoje umiejętności i istniejący kod na platformie Xamarin, korzystając z zalet ponownego użycia kodu w języku C#. Składnia języka C# jest bardzo podobna do składni języka Java i że oba języki zapewniają bardzo podobne funkcje. Ponadto poznasz funkcje unikatowe dla języka C#, które ułatwią ci tworzenie aplikacji.
Omówienie
Ten artykuł zawiera wprowadzenie do programowania w języku C# dla deweloperów języka Java, koncentrując się przede wszystkim na funkcjach języka C#, które napotkasz podczas tworzenia aplikacji platformy Xamarin.Android. Ponadto w tym artykule wyjaśniono, jak te funkcje różnią się od ich odpowiedników w języku Java i wprowadzono ważne funkcje języka C# (istotne dla platformy Xamarin.Android), które nie są dostępne w języku Java. Dołączono linki do dodatkowych materiałów referencyjnych, dzięki czemu można użyć tego artykułu jako punktu "skokowego" do dalszej analizy języka C# i platformy .NET.
Jeśli znasz język Java, będziesz czuć się natychmiast w domu ze składnią języka C#. Składnia języka C# jest bardzo podobna do składni języka Java — C# to język "klamrowy", taki jak Java, C i C++. Na wiele sposobów składnia języka C# odczytuje się jak nadzbiór składni języka Java, ale z kilkoma nazwami i dodanymi słowami kluczowymi.
Wiele kluczowych cech języka Java można znaleźć w języku C#:
Programowanie obiektowe oparte na klasach
Silne wpisywanie
Obsługa interfejsów
Typy ogólne
Wyrzucanie elementów bezużytecznych
Kompilacja środowiska uruchomieniowego
Język Java i C# są kompilowane w języku pośrednim, który jest uruchamiany w zarządzanym środowisku wykonywania. Zarówno język C#, jak i Java są statycznie typizowane, a oba języki traktują ciągi jako niezmienne typy.
Oba języki używają hierarchii klas z jednym rootem. Podobnie jak język Java, język C# obsługuje tylko pojedyncze dziedziczenie i nie zezwala na metody globalne.
W obu językach obiekty są tworzone na stercie przy użyciu słowa kluczowego new
, a obiekty są wyrzucane z pamięci, gdy nie są już używane. Oba języki zapewniają obsługę formalnych wyjątków z try
/catch
semantykami. Obie zapewniają obsługę zarządzania wątkami i synchronizacji.
Istnieje jednak wiele różnic między językiem Java i językiem C#. Na przykład:
W języku Java można przekazywać parametry tylko według wartości, natomiast w języku C# można przekazywać odwołania, a także według wartości. (Język C# udostępnia
ref
słowa kluczowe iout
do przekazywania parametrów według odwołania; w języku Java nie ma odpowiedników tych parametrów).Język Java nie obsługuje dyrektyw preprocesora, takich jak
#define
.Język Java nie obsługuje niepodpisanych typów liczb całkowitych, podczas gdy język C# udostępnia niepodpisane typy liczb całkowitych, takie jak
ulong
,uint
ushort
ibyte
.Język Java nie obsługuje przeciążenia operatora; W języku C# można przeciążać operatory i konwersje.
W instrukcji Języka Java
switch
kod może należeć do następnej sekcji przełącznika, ale w języku C# koniec każdejswitch
sekcji musi zakończyć przełącznik (koniec każdej sekcji musi zamknąć się instrukcjąbreak
).W języku Java określasz wyjątki zgłaszane przez metodę ze
throws
słowem kluczowym, ale język C# nie ma pojęcia sprawdzonych wyjątków —throws
słowo kluczowe nie jest obsługiwane w języku C#.Język C# obsługuje zapytanie zintegrowane z językiem (LINQ), które umożliwia używanie zarezerwowanych słów
from
,select
iwhere
do pisania zapytań względem kolekcji w sposób podobny do zapytań bazy danych.
Oczywiście istnieje wiele innych różnic między językiem C# i Językiem Java, niż opisano w tym artykule. Ponadto zarówno java, jak i C# nadal ewoluują (na przykład Java 8, który nie znajduje się jeszcze w łańcuchu narzędzi systemu Android, obsługuje wyrażenia lambda w stylu C#), więc te różnice zmienią się w czasie. W tym miejscu opisano tylko najważniejsze różnice występujące obecnie przez deweloperów języka Java dla platformy Xamarin.Android.
Przejście z języka Java do programowania w języku C# stanowi wprowadzenie do podstawowych różnic między językiem C# i Językiem Java.
Funkcje programowania zorientowanego obiektowo przedstawiają najważniejsze różnice cech obiektowo-obiektowe między dwoma językami.
Różnice słów kluczowych zawierają tabelę przydatnych odpowiedników słów kluczowych, słów kluczowych tylko w języku C#oraz linki do definicji słów kluczowych języka C#.
Język C# oferuje wiele kluczowych funkcji platformy Xamarin.Android, które nie są obecnie łatwo dostępne dla deweloperów języka Java w systemie Android. Te funkcje mogą pomóc w pisaniu lepszego kodu w krótszym czasie:
Właściwości — dzięki systemowi właściwości języka C#można bezpiecznie i bezpośrednio uzyskiwać dostęp do zmiennych składowych bez konieczności pisania metod ustawiających i getter.
Wyrażenia lambda — w języku C# można używać metod anonimowych (nazywanych również lambdami), aby wyrazić funkcjonalność bardziej zwięźle i wydajniej. Możesz uniknąć konieczności zapisywania obiektów jednorazowego użycia i przekazać stan lokalny do metody bez konieczności dodawania parametrów.
Obsługa zdarzeń — język C# zapewnia obsługę programowania opartego na zdarzeniach, w którym obiekt może zostać zarejestrowany w celu powiadamiania o wystąpieniu zdarzenia zainteresowania. Słowo
event
kluczowe definiuje mechanizm emisji multiemisji, którego klasa wydawcy może używać do powiadamiania subskrybentów zdarzeń.Programowanie asynchroniczne — funkcje programowania asynchronicznego języka C# (
async
/await
) zachowują elastyczność aplikacji. Obsługa na poziomie języka tej funkcji sprawia, że programowanie asynchroniczne jest łatwe do zaimplementowania i mniej podatne na błędy.
Na koniec platforma Xamarin umożliwia korzystanie z istniejących zasobów Java za pośrednictwem technologii znanej jako powiązanie. Możesz wywołać istniejący kod Java, struktury i biblioteki z języka C#, korzystając z generatorów automatycznych powiązań platformy Xamarin. W tym celu wystarczy utworzyć bibliotekę statyczną w języku Java i uwidocznić ją w języku C# za pomocą powiązania.
Uwaga
Programowanie w systemie Android używa określonej wersji języka Java, która obsługuje wszystkie funkcje języka Java 7 i podzbiór języka Java 8.
Niektóre funkcje wymienione na tej stronie (takie jak var
słowo kluczowe w języku C#) są dostępne w nowszych wersjach języka Java (np. var
w języku Java 10), ale nadal nie są dostępne dla deweloperów systemu Android.
Przechodzenie z języka Java do programowania w języku C#
W poniższych sekcjach opisano podstawowe różnice między językami C# i Java. w dalszej sekcji opisano różnice obiektowe między tymi językami.
Biblioteki a zestawy
Język Java zwykle pakuje klasy pokrewne w plikach .jar . Jednak w językach C# i .NET bity wstępnie skompilowanego kodu są pakowane do zestawów, które są zwykle pakowane jako pliki .dll . Zestaw jest jednostką wdrożenia kodu C#/.NET, a każdy zestaw jest zwykle skojarzony z projektem języka C#. Zestawy zawierają kod pośredni (IL), który jest kompilowany w czasie just in time w czasie.
Aby uzyskać więcej informacji na temat zestawów, zobacz temat Zestawy i globalna pamięć podręczna zestawów.
Pakiety a przestrzenie nazw
Język C# używa słowa kluczowego namespace
do grupowania powiązanych typów. Jest to podobne do słowa kluczowego package
Języka Java. Zazwyczaj aplikacja platformy Xamarin.Android będzie znajdować się w przestrzeni nazw utworzonej dla tej aplikacji. Na przykład następujący kod w języku C# deklaruje WeatherApp
otokę przestrzeni nazw dla aplikacji do raportowania pogody:
namespace WeatherApp
{
...
Importowanie typów
W przypadku używania typów zdefiniowanych w zewnętrznych przestrzeniach nazw te typy są importowane za pomocą using
instrukcji (która jest bardzo podobna do instrukcji Języka Java import
). W języku Java możesz zaimportować pojedynczy typ z instrukcją podobną do następującej:
import javax.swing.JButton
Możesz zaimportować cały pakiet Java z instrukcją podobną do następującej:
import javax.swing.*
Instrukcja języka C# using
działa w bardzo podobny sposób, ale umożliwia importowanie całego pakietu bez określania symbolu wieloznakowego. Na przykład na początku plików źródłowych platformy Xamarin.Android często zobaczysz serię instrukcji using
, jak pokazano w tym przykładzie:
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Net;
using System.IO;
using System.Json;
using System.Threading.Tasks;
Te instrukcje importuje funkcje z System
przestrzeni nazw , Android.App
, Android.Content
itp.
Typy ogólne
Zarówno język Java, jak i język C# obsługują typy ogólne, które są symbolami zastępczymi, które umożliwiają podłączenie różnych typów w czasie kompilacji. Jednak typy ogólne działają nieco inaczej w języku C#. W języku Java funkcja wymazywania typów udostępnia informacje o typie tylko w czasie kompilacji, ale nie w czasie wykonywania. Natomiast środowisko uruchomieniowe języka wspólnego platformy .NET (CLR) zapewnia jawną obsługę typów ogólnych, co oznacza, że język C# ma dostęp do informacji o typie w czasie wykonywania. W codziennych programach deweloperskich platformy Xamarin.Android znaczenie tego rozróżnienia nie jest często widoczne, ale jeśli używasz odbicia, ta funkcja będzie zależeć od tej funkcji w celu uzyskania dostępu do informacji o typie w czasie wykonywania.
W środowisku Xamarin.Android często jest widoczna metoda FindViewById
ogólna używana do uzyskiwania odwołania do kontrolki układu. Ta metoda akceptuje ogólny parametr typu, który określa typ kontrolki do wyszukania. Na przykład:
TextView label = FindViewById<TextView> (Resource.Id.Label);
W tym przykładzie FindViewById
kodu pobiera odwołanie do kontrolki TextView
zdefiniowanej w układzie jako Etykieta, a następnie zwraca je jako TextView
typ.
Aby uzyskać więcej informacji na temat typów ogólnych, zobacz temat Generics (Ogólne). Należy pamiętać, że istnieją pewne ograniczenia dotyczące obsługi platformy Xamarin.Android dla ogólnych klas języka C#; Aby uzyskać więcej informacji, zobacz Ograniczenia.
Funkcje programowania zorientowanego obiektowo
Zarówno java, jak i C# używają bardzo podobnych idiomów programowania obiektowego:
Wszystkie klasy są ostatecznie pochodne od pojedynczego obiektu głównego — wszystkie obiekty Java pochodzą z
java.lang.Object
klasy , podczas gdy wszystkie obiekty języka C# pochodzą zSystem.Object
klasy .Wystąpienia klas są typami referencyjnymi.
Podczas uzyskiwania dostępu do właściwości i metod wystąpienia należy użyć operatora "
.
".Wszystkie wystąpienia klas są tworzone na stercie
new
za pośrednictwem operatora .Ponieważ oba języki używają odzyskiwania pamięci, nie ma możliwości jawnego zwolnienia nieużywanych obiektów (tj. nie ma słowa kluczowego
delete
, ponieważ istnieje w języku C++).Klasy można rozszerzyć za pomocą dziedziczenia, a oba języki zezwalają tylko na jedną klasę bazową na typ.
Można zdefiniować interfejsy, a klasa może dziedziczyć z (tj. implementować) wiele definicji interfejsu.
Istnieją jednak również pewne istotne różnice:
Język Java ma dwie zaawansowane funkcje, których język C# nie obsługuje: klasy anonimowe i klasy wewnętrzne. (Jednak język C# zezwala na zagnieżdżanie definicji klas — zagnieżdżone klasy języka C#są podobne do statycznych klas zagnieżdżonych języka Java).
Język C# obsługuje typy struktury stylu C (
struct
), a język Java nie.W języku C#można zaimplementować definicję klasy w osobnych plikach źródłowych przy użyciu słowa kluczowego
partial
.Interfejsy języka C# nie mogą deklarować pól.
Język C# używa składni destruktora w stylu C++, aby wyrazić finalizatory. Składnia różni się od metody języka Java
finalize
, ale semantyka jest prawie taka sama. (Należy pamiętać, że w języku C#destruktory automatycznie wywołają destruktor klasy bazowej — w przeciwieństwie do języka Java, w którym jest używane jawne wywołaniesuper.finalize
.
Dziedziczenie klas
Aby rozszerzyć klasę w języku Java, należy użyć słowa kluczowego extends
. Aby rozszerzyć klasę w języku C#, należy użyć dwukropka (:
), aby wskazać wyprowadzenie. Na przykład w aplikacjach platformy Xamarin.Android często są widoczne wyprowadzenia klas przypominające następujący fragment kodu:
public class MainActivity : Activity
{
...
W tym przykładzie MainActivity
Activity
dziedziczy z klasy .
Aby zadeklarować obsługę interfejsu w języku Java, należy użyć słowa kluczowego implements
. Jednak w języku C#wystarczy dodać nazwy interfejsów do listy klas do dziedziczenia, jak pokazano w tym fragmentcie kodu:
public class SensorsActivity : Activity, ISensorEventListener
{
...
W tym przykładzie SensorsActivity
dziedziczy Activity
i implementuje funkcje zadeklarowane w interfejsie ISensorEventListener
. Należy pamiętać, że lista interfejsów musi pochodzić po klasie bazowej (lub zostanie wyświetlony błąd czasu kompilacji). Zgodnie z konwencją nazwy interfejsów języka C# są poprzedzone wielkimi literami "I"; dzięki temu można określić, które klasy są interfejsami bez wymagania słowa kluczowego implements
.
Jeśli chcesz zapobiec dalszemu podklasowaniu klasy w języku C#, poprzedzasz nazwę klasy — w języku Java poprzedzasz nazwę sealed
klasy nazwą final
klasy .
Aby uzyskać więcej informacji na temat definicji klas języka C#, zobacz tematy Klasy i dziedziczenie .
Właściwości
W języku Java metody mutatora (setters) i metody inspektora (getters) są często używane do kontrolowania sposobu wprowadzania zmian w składowych klasy, ukrywając i chroniąc te elementy członkowskie przed kodem zewnętrznym. Na przykład klasa systemu Android TextView
udostępnia getText
metody i setText
. Język C# udostępnia podobny, ale bardziej bezpośredni mechanizm znany jako właściwości.
Użytkownicy klasy języka C# mogą uzyskać dostęp do właściwości w taki sam sposób, jak w przypadku uzyskiwania dostępu do pola, ale każdy dostęp faktycznie powoduje wywołanie metody przezroczyste dla obiektu wywołującego. Ta metoda "pod okładkami" może implementować skutki uboczne, takie jak ustawianie innych wartości, wykonywanie konwersji lub zmienianie stanu obiektu.
Właściwości są często używane do uzyskiwania dostępu do elementów członkowskich obiektów interfejsu użytkownika (interfejs użytkownika) i modyfikowania ich. Na przykład:
int width = rulerView.MeasuredWidth;
int height = rulerView.MeasuredHeight;
...
rulerView.DrawingCacheEnabled = true;
W tym przykładzie rulerView
wartości szerokości i wysokości są odczytywane z obiektu przez uzyskanie dostępu do jego MeasuredWidth
właściwości i MeasuredHeight
. Gdy te właściwości są odczytywane, wartości ze skojarzonych (ale ukrytych) wartości pól są pobierane za kulisami i zwracane do obiektu wywołującego. Obiekt rulerView
może przechowywać wartości szerokości i wysokości w jednej jednostce miary (np. pikseli) i przekonwertować te wartości na lot do innej jednostki miary (np. milimetrów), gdy MeasuredWidth
uzyskuje się dostęp do właściwości i MeasuredHeight
.
Obiekt rulerView
ma również właściwość o nazwie DrawingCacheEnabled
— przykładowy kod ustawia tę właściwość w celu true
włączenia pamięci podręcznej rysunku w pliku rulerView
. W tle skojarzone pole ukryte jest aktualizowane przy użyciu nowej wartości, a prawdopodobnie inne aspekty rulerView
stanu są modyfikowane. Na przykład gdy DrawingCacheEnabled
jest ustawiona wartość false
, rulerView
może również wymazać wszystkie informacje pamięci podręcznej rysunku już zebrane w obiekcie.
Dostęp do właściwości może być tylko do odczytu/zapisu, tylko do odczytu lub zapisu. Ponadto można użyć różnych modyfikatorów dostępu do odczytu i zapisu. Można na przykład zdefiniować właściwość, która ma publiczny dostęp do odczytu, ale prywatny dostęp do zapisu.
Aby uzyskać więcej informacji o właściwościach języka C#, zobacz temat Właściwości .
Wywoływanie metod klasy bazowej
Aby wywołać konstruktor klasy bazowej w języku C#, należy użyć dwukropka (:
), a następnie base
słowa kluczowego i listy inicjatorów. To base
wywołanie konstruktora jest umieszczane bezpośrednio po liście parametrów konstruktora pochodnego. Konstruktor klasy bazowej jest wywoływany we wpisie do konstruktora pochodnego; kompilator wstawia wywołanie do konstruktora podstawowego na początku treści metody. Poniższy fragment kodu ilustruje konstruktor podstawowy wywoływany z konstruktora pochodnego w aplikacji platformy Xamarin.Android:
public class PictureLayout : ViewGroup
{
...
public PictureLayout (Context context)
: base (context)
{
...
}
...
}
W tym przykładzie PictureLayout
ViewGroup
klasa pochodzi z klasy . Konstruktor PictureLayout
pokazany w tym przykładzie akceptuje context
argument i przekazuje go do konstruktora ViewGroup
za pośrednictwem wywołania base(context)
.
Aby wywołać metodę klasy bazowej w języku C#, użyj słowa kluczowego base
. Na przykład aplikacje platformy Xamarin.Android często tworzą wywołania metod bazowych, jak pokazano poniżej:
public class MainActivity : Activity
{
...
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
W tym przypadku metoda zdefiniowana OnCreate
przez klasę pochodną (MainActivity
) wywołuje OnCreate
metodę klasy bazowej (Activity
).
Modyfikatory dostępu
Języki Java i C# obsługują public
modyfikatory dostępu , private
i protected
. Język C# obsługuje jednak dwa dodatkowe modyfikatory dostępu:
internal
— Składowa klasy jest dostępna tylko w bieżącym zestawie.protected internal
— Składowa klasy jest dostępna w ramach zestawu definiującego, klasy definiującej i klasy pochodne (klasy pochodne zarówno wewnątrz, jak i na zewnątrz zestawu mają dostęp).
Aby uzyskać więcej informacji na temat modyfikatorów dostępu w języku C#, zobacz temat Modyfikatory dostępu.
Metody wirtualne i zastępowane
Zarówno język Java, jak i język C# obsługują polimorfizm, czyli możliwość traktowania powiązanych obiektów w ten sam sposób. W obu językach można użyć odwołania klasy bazowej do odwoływania się do obiektu klasy pochodnej, a metody klasy pochodnej mogą zastąpić metody jej klas bazowych. Oba języki mają koncepcję metody wirtualnej — metody w klasie bazowej, która ma zostać zastąpiona przez metodę w klasie pochodnej.
Podobnie jak język Java, język C# obsługuje abstract
klasy i metody.
Istnieją jednak pewne różnice między językami Java i C# w zakresie deklarowania metod wirtualnych i zastępowania ich:
W języku C#metody są domyślnie niewirtualne. Klasy nadrzędne muszą jawnie oznaczyć, które metody mają zostać zastąpione za pomocą słowa kluczowego
virtual
. Z kolei wszystkie metody w języku Java są domyślnie metodami wirtualnymi.Aby zapobiec zastąpieniu metody w języku C#, po prostu pozostaw słowo
virtual
kluczowe . Natomiast język Java używa słowa kluczowegofinal
do oznaczania metody "przesłonięcia nie jest dozwolone".Klasy pochodne języka C# muszą używać słowa kluczowego
override
, aby jawnie wskazać, że wirtualna metoda klasy bazowej jest zastępowana.
Aby uzyskać więcej informacji na temat obsługi polimorfizmu w języku C#, zobacz temat Polymorphism (Polimorfizm ).
Wyrażenia lambda
Język C# umożliwia tworzenie zamknięć: wbudowane, anonimowe metody, które mogą uzyskiwać dostęp do stanu metody, w której są ujęte. Używając wyrażeń lambda, można napisać mniej wierszy kodu, aby zaimplementować te same funkcje, które mogły zostać zaimplementowane w języku Java z wieloma wierszami kodu.
Wyrażenia lambda pozwalają pominąć dodatkową ceremonię związaną z tworzeniem klasy jednorazowej lub anonimowej, tak jak w języku Java — zamiast tego możesz po prostu napisać logikę biznesową kodu metody w tekście. Ponadto, ponieważ lambdy mają dostęp do zmiennych w otaczającej metodzie, nie trzeba tworzyć długiej listy parametrów, aby przekazać stan do kodu metody.
W języku C#wyrażenia lambda są tworzone za pomocą =>
operatora , jak pokazano poniżej:
(arg1, arg2, ...) => {
// implementation code
};
W środowisku Xamarin.Android wyrażenia lambda są często używane do definiowania procedur obsługi zdarzeń. Na przykład:
button.Click += (sender, args) => {
clickCount += 1; // access variable in surrounding code
button.Text = string.Format ("Clicked {0} times.", clickCount);
};
W tym przykładzie kod wyrażenia lambda (kod w nawiasach klamrowych) zwiększa liczbę kliknięć i aktualizuje button
tekst, aby wyświetlić liczbę kliknięć. To wyrażenie lambda jest rejestrowane z obiektem button
jako procedura obsługi zdarzeń kliknięcia, która ma być wywoływana za każdym razem, gdy przycisk zostanie naciśnięty. (Procedury obsługi zdarzeń zostały wyjaśnione bardziej szczegółowo poniżej). W tym prostym przykładzie sender
parametry i args
nie są używane przez kod wyrażenia lambda, ale są one wymagane w wyrażeniu lambda, aby spełnić wymagania dotyczące podpisu metody na potrzeby rejestracji zdarzeń. Pod maską kompilator języka C# tłumaczy wyrażenie lambda na anonimową metodę wywoływaną za każdym razem, gdy mają miejsce zdarzenia kliknięcia przycisku.
Aby uzyskać więcej informacji o wyrażeniach języka C# i lambda, zobacz temat Lambda Expressions (Wyrażenia lambda).
Obsługa zdarzeń
Zdarzenie jest sposobem powiadamiania zarejestrowanych subskrybentów, gdy coś interesującego dzieje się z tym obiektem. W przeciwieństwie do języka Java, gdzie subskrybent zazwyczaj implementuje interfejs, który zawiera metodę Listener
wywołania zwrotnego, język C# zapewnia obsługę na poziomie języka na potrzeby obsługi zdarzeń za pośrednictwem delegatów. Delegat jest jak obiektowy wskaźnik funkcji bezpieczne dla typu — hermetyzuje odwołanie do obiektu i token metody. Jeśli obiekt klienta chce subskrybować zdarzenie, tworzy delegata i przekazuje delegata do obiektu powiadamiania.
W przypadku wystąpienia zdarzenia obiekt powiadamiania wywołuje metodę reprezentowaną przez obiekt delegata, powiadamiając o subskrybowaniu obiektu klienta zdarzenia. W języku C# programy obsługi zdarzeń są zasadniczo niczym więcej niż metodami wywoływanymi za pośrednictwem delegatów.
Aby uzyskać więcej informacji na temat delegatów, zobacz temat Delegaty .
W języku C# zdarzenia są multiemisji. Oznacza to, że więcej niż jeden odbiornik może być powiadamiany o wystąpieniu zdarzenia. Ta różnica jest obserwowana, gdy rozważasz różnice składniowe między rejestracją zdarzeń języka Java i języka C#. W języku Java wywołujesz metodę SetXXXListener
rejestrowania powiadomień o zdarzeniach. W języku C# operator służy +=
do rejestrowania powiadomień o zdarzeniach przez dodanie delegata do listy odbiorników zdarzeń.
W języku Java wywołujesz metodę SetXXXListener
wyrejestrowania, podczas gdy w języku C# używasz -=
elementu do "odejmowania" delegata z listy odbiorników.
W środowisku Xamarin.Android zdarzenia są często używane do powiadamiania obiektów, gdy użytkownik wykonuje coś w kontrolce interfejsu użytkownika. Zwykle kontrolka interfejsu użytkownika będzie mieć elementy członkowskie zdefiniowane przy użyciu słowa kluczowego event
. Do tych członków dołączasz delegatów do subskrybowania zdarzeń z tej kontrolki interfejsu użytkownika.
Aby zasubskrybować zdarzenie:
Utwórz obiekt delegata, który odwołuje się do metody, którą chcesz wywołać po wystąpieniu zdarzenia.
+=
Użyj operatora , aby dołączyć pełnomocnika do zdarzenia, do którego subskrybujesz.
W poniższym przykładzie zdefiniowano delegata (z jawnym użyciem słowa kluczowego delegate
) do subskrybowania kliknięć przycisków.
Ta procedura obsługi kliknięcia przycisku uruchamia nowe działanie:
startActivityButton.Click += delegate {
Intent intent = new Intent (this, typeof (MyActivity));
StartActivity (intent);
};
Można jednak również użyć wyrażenia lambda, aby zarejestrować się pod kątem zdarzeń, pomijając delegate
słowo kluczowe całkowicie. Na przykład:
startActivityButton.Click += (sender, e) => {
Intent intent = new Intent (this, typeof (MyActivity));
StartActivity (intent);
};
W tym przykładzie startActivityButton
obiekt ma zdarzenie, które oczekuje delegata z określonym podpisem metody: taki, który akceptuje argumenty nadawcy i zdarzenia i zwraca wartość void. Jednak ponieważ nie chcemy przechodzić do problemu, aby jawnie zdefiniować taki delegat lub jego metodę, deklarujemy podpis metody za pomocą wyrażenia (sender, e)
lambda i używamy wyrażenia lambda w celu zaimplementowania treści procedury obsługi zdarzeń.
Należy pamiętać, że musimy zadeklarować tę listę parametrów, mimo że nie używamy parametrów sender
i e
.
Należy pamiętać, że możesz anulować subskrypcję delegata (za pośrednictwem -=
operatora), ale nie można anulować subskrypcji wyrażenia lambda — próba wykonania tej czynności może spowodować przecieki pamięci. Użyj formy rejestracji zdarzeń lambda tylko wtedy, gdy program obsługi nie anuluje subskrypcji zdarzenia.
Zazwyczaj wyrażenia lambda służą do deklarowania programów obsługi zdarzeń w kodzie platformy Xamarin.Android. Ten skrócony sposób deklarowania programów obsługi zdarzeń może wydawać się na początku tajemniczy, ale oszczędza ogromną ilość czasu podczas pisania i odczytywania kodu. Dzięki rosnącej znajomości przyzwyczaisz się do rozpoznawania tego wzorca (który występuje często w kodzie platformy Xamarin.Android) i poświęcasz więcej czasu na myślenie o logice biznesowej aplikacji i mniej czasu na wadowanie za pomocą syntactycznego obciążenia.
Programowanie asynchroniczne
Programowanie asynchroniczne to sposób na poprawę ogólnej reakcji aplikacji. Funkcje programowania asynchronicznego umożliwiają kontynuowanie działania pozostałej części kodu aplikacji, gdy część aplikacji jest blokowana przez długotrwałą operację. Uzyskiwanie dostępu do internetu, przetwarzanie obrazów i odczytywanie/zapisywanie plików to przykłady operacji, które mogą spowodować, że cała aplikacja zawiesza się, jeśli nie jest zapisywana asynchronicznie.
Język C# obejmuje obsługę programowania asynchronicznego za pomocą async
słów kluczowych i await
. Te funkcje językowe ułatwiają pisanie kodu wykonującego długotrwałe zadania bez blokowania głównego wątku aplikacji. Krótko mówiąc, używasz słowa kluczowego async
w metodzie, aby wskazać, że kod w metodzie ma być uruchamiany asynchronicznie i nie blokuje wątku wywołującego. Słowo kluczowe jest await
używane podczas wywoływania metod oznaczonych znakiem async
. Kompilator interpretuje await
element jako punkt, w którym wykonanie metody ma zostać przeniesione do wątku w tle (zadanie jest zwracane do wywołującego). Po zakończeniu tego zadania wykonanie kodu zostanie wznowione w wątku obiektu wywołującego w await
punkcie kodu, zwracając wyniki async
wywołania. Zgodnie z konwencją metody uruchamiane asynchronicznie mają Async
sufiksy ich nazw.
W aplikacjach async
platformy Xamarin.Android i await
są zwykle używane do zwalniania wątku interfejsu użytkownika, dzięki czemu może reagować na dane wejściowe użytkownika (takie jak naciśnięcie przycisku Anuluj ), podczas gdy długotrwała operacja odbywa się w tle.
W poniższym przykładzie procedura obsługi zdarzeń kliknięcia przycisku powoduje asynchroniczną operację pobierania obrazu z sieci Web:
downloadButton.Click += downloadAsync;
...
async void downloadAsync(object sender, System.EventArgs e)
{
webClient = new WebClient ();
var url = new Uri ("http://photojournal.jpl.nasa.gov/jpeg/PIA15416.jpg");
byte[] bytes = null;
bytes = await webClient.DownloadDataTaskAsync(url);
// display the downloaded image ...
W tym przykładzie, gdy użytkownik kliknie kontrolkę downloadButton
, downloadAsync
program obsługi zdarzeń tworzy WebClient
obiekt i Uri
obiekt, aby pobrać obraz ze określonego adresu URL. Następnie wywołuje metodę WebClient
obiektu DownloadDataTaskAsync
za pomocą tego adresu URL, aby pobrać obraz.
Zwróć uwagę, że deklaracja downloadAsync
metody klasy jest poprzedzona async
słowem kluczowym, aby wskazać, że zostanie uruchomiona asynchronicznie i zwróci zadanie. Należy również zauważyć, że wywołanie metody jest DownloadDataTaskAsync
poprzedzone await
słowem kluczowym . Aplikacja przenosi wykonywanie programu obsługi zdarzeń (począwszy od punktu, w którym await
występuje) do wątku w tle do momentu DownloadDataTaskAsync
zakończenia i powrotu.
W międzyczasie wątek interfejsu użytkownika aplikacji może nadal reagować na dane wejściowe użytkownika i uruchamiać programy obsługi zdarzeń dla innych kontrolek. Po DownloadDataTaskAsync
zakończeniu (co może potrwać kilka sekund), wykonywanie wznawia działanie, w którym bytes
zmienna jest ustawiona na wynik wywołania DownloadDataTaskAsync
metody , a pozostała część kodu procedury obsługi zdarzeń wyświetla pobrany obraz w wątku obiektu wywołującego.
Aby zapoznać się z wprowadzeniem do async
/await
języka C#, zobacz temat Programowanie asynchroniczne z funkcją Async i Await.
Aby uzyskać więcej informacji na temat obsługi platformy Xamarin funkcji programowania asynchronicznego, zobacz Async Support Overview (Omówienie asynchronicznej pomocy technicznej).
Różnice słów kluczowych
Wiele słów kluczowych języka używanych w języku Java jest również używanych w języku C#. Istnieje również wiele słów kluczowych języka Java, które mają równoważny, ale inaczej nazwany odpowiednik w języku C#, jak wymieniono w tej tabeli:
Java | C# | opis |
---|---|---|
boolean |
bool | Służy do deklarowania wartości logicznych true i false. |
extends |
: |
Poprzedza klasę i interfejsy dziedziczone z. |
implements |
: |
Poprzedza klasę i interfejsy dziedziczone z. |
import |
using | Importuje typy z przestrzeni nazw, używane również do tworzenia aliasu przestrzeni nazw. |
final |
sealed | Zapobiega wyprowadzaniu klas; zapobiega zastępowaniu metod i właściwości w klasach pochodnych. |
instanceof |
is | Ocenia, czy obiekt jest zgodny z danym typem. |
native |
extern | Deklaruje metodę zaimplementowaną zewnętrznie. |
package |
namespace | Deklaruje zakres powiązanych zestawów obiektów. |
T... |
params T | Określa parametr metody, który przyjmuje zmienną liczbę argumentów. |
super |
base | Służy do uzyskiwania dostępu do składowych klasy nadrzędnej z poziomu klasy pochodnej. |
synchronized |
lock | Opakowuje krytyczną sekcję kodu przy użyciu uzyskiwania blokady i wydawania. |
Istnieje również wiele słów kluczowych, które są unikatowe dla języka C# i nie mają odpowiednika w języku Java używanym w systemie Android. Kod platformy Xamarin.Android często używa następujących słów kluczowych języka C# (ta tabela jest przydatna do odwoływania się podczas odczytywania przykładowego kodu platformy Xamarin.Android.
C# | opis |
---|---|
as | Wykonuje konwersje między zgodnymi typami referencyjnymi lub typami dopuszczanymi do wartości null. |
async | Określa, że metoda lub wyrażenie lambda jest asynchroniczne. |
await | Zawiesza wykonywanie metody do momentu zakończenia zadania. |
byte | Niepodpisany typ liczby całkowitej 8-bitowej. |
delegate | Służy do hermetyzacji metody lub metody anonimowej. |
enum | Deklaruje wyliczenie , zestaw nazwanych stałych. |
event | Deklaruje zdarzenie w klasie wydawcy. |
Stałe | Zapobiega przeniesieniu zmiennej. |
get |
Definiuje metodę dostępu, która pobiera wartość właściwości. |
w | Umożliwia akceptowanie mniej pochodnego typu w interfejsie ogólnym parametru. |
object | Alias typu obiekt w programie .NET Framework. |
out | Modyfikator parametrów lub deklaracja parametru typu ogólnego. |
override | Rozszerza lub modyfikuje implementację dziedziczonego elementu członkowskiego. |
partial | Deklaruje definicję, która ma zostać podzielona na wiele plików, lub dzieli definicję metody z jej implementacji. |
readonly | Deklaruje, że składowa klasy może być przypisana tylko w czasie deklaracji lub przez konstruktor klasy. |
ref | Powoduje przekazanie argumentu przez odwołanie, a nie przez wartość. |
set | Definiuje metodę dostępu, która ustawia wartość właściwości. |
string | Alias typu Ciąg w programie .NET Framework. |
struct | Typ wartości, który hermetyzuje grupę powiązanych zmiennych. |
typeof | Uzyskuje typ obiektu. |
var | Deklaruje niejawnie typizowanej zmiennej lokalnej. |
wartość | Odwołuje się do wartości, którą kod klienta chce przypisać do właściwości. |
virtual | Umożliwia zastąpienie metody w klasie pochodnej. |
Współdziałanie z istniejącym kodem java
Jeśli masz istniejące funkcje języka Java, których nie chcesz konwertować na język C#, możesz ponownie użyć istniejących bibliotek Java w aplikacjach platformy Xamarin.Android za pomocą dwóch technik:
Utwórz bibliotekę powiązań Języka Java — za pomocą tego podejścia użyjesz narzędzi platformy Xamarin do generowania otoek języka C# wokół typów języka Java. Te otoki są nazywane powiązaniami. W związku z tym aplikacja Xamarin.Android może używać pliku .jar , wywołując te otoki.
Java Native Interface — interfejs natywny Języka Java (JNI) to struktura, która umożliwia wywoływanie aplikacji języka C# lub wywoływanie ich przez kod Java.
Aby uzyskać więcej informacji na temat tych technik, zobacz Omówienie integracji języka Java.
Dalsze informacje
Przewodnik programowania w języku C# w witrynie MSDN to doskonały sposób na rozpoczęcie nauki języka programowania w języku C#. W celu wyszukania określonych funkcji języka C# możesz użyć odwołania w języku C#.
W ten sam sposób, że wiedza na temat języka Java jest co najmniej tak samo znana z bibliotek klas Języka Java, jak znajomość języka Java, praktyczna wiedza na temat języka C# wymaga znajomości platformy .NET. Przejście firmy Microsoft do języka C# i programu .NET Framework dla deweloperów języka Java to dobry sposób, aby dowiedzieć się więcej na temat platformy .NET z perspektywy języka Java (przy jednoczesnym uzyskaniu głębszego zrozumienia języka C#).
Gdy wszystko będzie gotowe do rozwiązania swojego pierwszego projektu platformy Xamarin.Android w języku C#, nasza seria Hello, Android może pomóc w utworzeniu pierwszej aplikacji platformy Xamarin.Android i dokładniej zrozumieć podstawy tworzenia aplikacji dla systemu Android za pomocą platformy Xamarin.
Podsumowanie
W tym artykule przedstawiono wprowadzenie do środowiska programowania języka C# platformy Xamarin.Android z perspektywy dewelopera języka Java. Zwrócił on uwagę na podobieństwa między językami C# i Java, wyjaśniając ich praktyczne różnice. Wprowadzono zestawy i przestrzenie nazw, wyjaśniono, jak importować typy zewnętrzne, oraz przedstawiono omówienie różnic w modyfikatorach dostępu, rodzajach, wyprowadzeniu klas, wywoływaniu metod klasy bazowej, zastępowaniu metod i obsłudze zdarzeń. Wprowadzono funkcje języka C#, które nie są dostępne w języku Java, takie jak właściwości, async
/await
programowanie asynchroniczne, lambdy, delegaty języka C# i system obsługi zdarzeń języka C#. Zawierała ona tabele ważnych słów kluczowych języka C#, wyjaśniono, jak współdziałać z istniejącymi bibliotekami Języka Java i dostarczała linki do powiązanej dokumentacji w celu dalszej analizy.