1. Giriş
Dart 3, dile desenler ekliyor. Bu, yeni bir dilbilgisi kategorisidir. Dart kodu yazmanın bu yeni yolunun yanı sıra, aşağıdakiler de dahil olmak üzere çeşitli dil geliştirmeleri yapıldı:
- Farklı türlerdeki verileri paketlemek için kayıtlar,
- Erişimi kontrol etmek için sınıf değiştiriciler ve
- Yeni switch ifadeleri ve if-case ifadeleri.
Bu özellikler, Dart kodu yazarken sahip olduğunuz seçenekleri genişletir. Bu codelab'de, kodunuzu daha kompakt, akıcı ve esnek hale getirmek için bu işlevleri nasıl kullanacağınızı öğreneceksiniz.
Bu codelab'de Flutter ve Dart hakkında bilgi sahibi olduğunuz varsayılır. Bilgilerinizin biraz paslandığını düşünüyorsanız aşağıdaki kaynaklarla temel bilgilerinizi tazeleyebilirsiniz:
Ne oluşturacaksınız?
Bu codelab'de, Flutter'da bir JSON belgesini görüntüleyen bir uygulama oluşturulur. Uygulama, harici bir kaynaktan gelen JSON'u simüle eder. JSON dosyasında değişiklik tarihi, başlık, başlıklar ve paragraflar gibi doküman verileri bulunur. Verileri, Flutter widget'larınızın ihtiyaç duyduğu her yerde aktarılıp açılabilmesi için kayıtlara düzgün bir şekilde yerleştirmek üzere kod yazarsınız.
Ardından, değer bu kalıpla eşleştiğinde uygun widget'ı oluşturmak için kalıpları kullanırsınız. Ayrıca, verileri yerel değişkenlere ayırmak için kalıpların nasıl kullanılacağını da göreceksiniz.

Neler öğreneceksiniz?
- Farklı türlerde birden fazla değer depolayan bir kayıt oluşturma
- Kayıt kullanarak bir işlevden birden fazla değer döndürme
- Kayıtlardaki ve diğer nesnelerdeki verileri eşleştirmek, doğrulamak ve yapılarını bozmak için desenleri kullanma.
- Desene göre eşleşen değerleri yeni veya mevcut değişkenlere nasıl bağlayacağınız açıklanmaktadır.
- Yeni anahtar ifadesi özelliklerini, anahtar ifadelerini ve if-case ifadelerini kullanma
- Her durumun bir switch ifadesinde veya switch ifadesinde ele alınmasını sağlamak için kapsamlılık kontrolünden yararlanma
2. Ortamınızı ayarlama
- Flutter SDK'sını yükleyin.
- Visual Studio Code (VS Code) gibi bir düzenleyici ayarlayın.
- En az bir hedef platform (iOS, Android, masaüstü veya web tarayıcısı) için Platform kurulumu adımlarını uygulayın.
3. Projeyi oluşturma
Desenler, kayıtlar ve diğer yeni özelliklere geçmeden önce tüm kodunuzu yazacağınız bir Flutter projesi oluşturun.
Flutter projesi oluşturma
flutter createkomutunu kullanarakpatterns_codelabadlı yeni bir proje oluşturun.--emptyişareti,lib/main.dartdosyasında standart sayaç uygulamasının oluşturulmasını engeller. Bu uygulamayı yine de kaldırmanız gerekir.
flutter create --empty patterns_codelab
- Ardından, VS Code'u kullanarak
patterns_codelabdizinini açın.
code patterns_codelab

Minimum SDK sürümünü ayarlama
- Projenizin SDK sürümü kısıtlamasını Dart 3 veya sonraki sürümlere bağlı olacak şekilde ayarlayın.
pubspec.yaml
environment:
sdk: ^3.0.0
4. Projeyi oluşturma
Bu adımda iki Dart dosyası oluşturur veya güncellersiniz:
- Uygulamanın widget'larını içeren
main.dartdosyası ve - Uygulamanın verilerini sağlayan
data.dartdosyası.
Sonraki adımlarda bu iki dosyayı da değiştirmeye devam edeceksiniz.
Uygulamanın verilerini tanımlama
- Yeni bir dosya oluşturun
lib/data.dartve aşağıdaki kodu ekleyin:
lib/data.dart
import 'dart:convert';
class Document {
final Map<String, Object?> _json;
Document() : _json = jsonDecode(documentJson);
}
const documentJson = '''
{
"metadata": {
"title": "My Document",
"modified": "2023-05-10"
},
"blocks": [
{
"type": "h1",
"text": "Chapter 1"
},
{
"type": "p",
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
},
{
"type": "checkbox",
"checked": false,
"text": "Learn Dart 3"
}
]
}
''';
Giriş/çıkış akışı veya HTTP isteği gibi harici bir kaynaktan veri alan bir program düşünün. Bu codelab'de, gelen JSON verilerini documentJson değişkeninde çok satırlı bir dizeyle taklit ederek bu daha gerçekçi kullanım alanını basitleştireceksiniz.
JSON verileri, Document sınıfında tanımlanır. Bu codelab'in ilerleyen bölümlerinde, ayrıştırılmış JSON'dan veri döndüren işlevler ekleyeceksiniz. Bu sınıf, oluşturucusunda _json alanını tanımlar ve başlatır.
Uygulamayı çalıştırma
flutter create komutu, varsayılan Flutter dosya yapısının bir parçası olarak lib/main.dart dosyasını oluşturur.
- Uygulama için bir başlangıç noktası oluşturmak üzere
main.dartiçeriğini aşağıdaki kodla değiştirin:
lib/main.dart
import 'package:flutter/material.dart';
import 'data.dart';
void main() {
runApp(const DocumentApp());
}
class DocumentApp extends StatelessWidget {
const DocumentApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(),
home: DocumentScreen(document: Document()),
);
}
}
class DocumentScreen extends StatelessWidget {
final Document document;
const DocumentScreen({required this.document, super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Title goes here')),
body: const Column(children: [Center(child: Text('Body goes here'))]),
);
}
}
Uygulamaya aşağıdaki iki widget'ı eklediniz:
DocumentApp, kullanıcı arayüzünü temalandırmak için Materyal Tasarım'ın en son sürümünü kurar.DocumentScreen,Scaffoldwidget'ını kullanarak sayfanın görsel düzenini sağlar.
- Her şeyin sorunsuz çalıştığından emin olmak için Çalıştır ve Hata Ayıkla'yı tıklayarak uygulamayı ana makinenizde çalıştırın:

- Varsayılan olarak Flutter, kullanılabilir hedef platformu seçer. Hedef platformu değiştirmek için durum çubuğunda geçerli platformu seçin:

title ve body öğelerinin DocumentScreen widget'ında tanımlandığı boş bir çerçeve görürsünüz:

5. Kayıt oluşturma ve döndürme
Bu adımda, bir işlev çağrısından birden fazla değer döndürmek için kayıtları kullanırsınız. Ardından, değerlere erişmek ve bunları kullanıcı arayüzüne yansıtmak için DocumentScreen widget'ında bu işlevi çağırırsınız.
Kayıt oluşturma ve döndürme
data.dartiçinde,metadataadlı ve kayıt döndüren yeni bir getter yöntemi ekleyin:
lib/data.dart
import 'dart:convert';
class Document {
final Map<String, Object?> _json;
Document() : _json = jsonDecode(documentJson);
(String, {DateTime modified}) get metadata { // Add from here...
const title = 'My Document';
final now = DateTime.now();
return (title, modified: now);
} // to here.
}
Bu işlevin dönüş türü, biri String türünde, diğeri DateTime türünde olmak üzere iki alan içeren bir kayıttır.
Döndürme ifadesi, iki değeri parantez içine alarak (title, modified: now) yeni bir kayıt oluşturur.
İlk alan konumsal ve adsız, ikinci alan ise modified olarak adlandırılmıştır.
Kayıt alanlarına erişme
DocumentScreenwidget'ında, kaydınızı alıp değerlerine erişebilmek içinbuildyöntemindemetadatagetter yöntemini çağırın:
lib/main.dart
class DocumentScreen extends StatelessWidget {
final Document document;
const DocumentScreen({required this.document, super.key});
@override
Widget build(BuildContext context) {
final metadataRecord = document.metadata; // Add this line.
return Scaffold(
appBar: AppBar(title: Text(metadataRecord.$1)), // Modify this line,
body: Column(
children: [ // And the following line.
Center(child: Text('Last modified ${metadataRecord.modified}')),
],
),
);
}
}
metadata getter yöntemi, metadataRecord yerel değişkenine atanan bir kayıt döndürür. Kayıtlar, tek bir işlev çağrısından birden çok değer döndürmenin ve bunları bir değişkene atamanın kolay bir yoludur.
Bu kayıtta oluşturulan alanlara erişmek için kayıtların yerleşik getter söz dizimini kullanabilirsiniz.
- Konum alanını (
titlegibi adı olmayan bir alan) almak için kayıttaki alıcı'ı kullanın. Bu işlev yalnızca adlandırılmamış alanları döndürür. modifiedgibi adlandırılmış alanların konuma dayalı alıcısı yoktur. Bu nedenle, adını doğrudan (ör.metadataRecord.modified) kullanabilirsiniz.
Konumsal bir alanın alıcı yönteminin adını belirlemek için $1 ile başlayın ve adlandırılmış alanları atlayın. Örneğin:
var record = (named: 'v', 'y', named2: 'x', 'z');
print(record.$1); // prints y
print(record.$2); // prints z
- Uygulamada gösterilen JSON değerlerini görmek için hızlı yeniden yükleme yapın. VS Code Dart eklentisi, bir dosyayı her kaydettiğinizde hızlı yeniden yükleme yapar.

Her alanın türünü koruduğunu görebilirsiniz.
Text()yöntemi, ilk bağımsız değişken olarak bir dize alır.modifiedalanı bir DateTime'dır ve dize enterpolasyonu kullanılarakStringbiçimine dönüştürülür.
Farklı veri türlerini döndürmenin diğer tür güvenli yolu, daha ayrıntılı olan bir sınıf tanımlamaktır.
6. Desenlerle eşleştirme ve yapı bozma
Kayıtlar, farklı veri türlerini verimli bir şekilde toplayabilir ve kolayca paylaşabilir. Artık desenleri kullanarak kodunuzu iyileştirebilirsiniz.
Bir kalıp, bir veya daha fazla değerin alabileceği bir yapıyı (ör. plan) temsil eder. Kalıpların eşleşip eşleşmediğini belirlemek için gerçek değerlerle karşılaştırma yapılır.
Bazı kalıplar eşleştiğinde, içindeki verileri çekerek eşleşen değeri yapılandırılmış hale getirir. Yapı bozma, bir nesnedeki değerleri yerel değişkenlere atamak veya bunlar üzerinde daha fazla eşleştirme yapmak için açmanıza olanak tanır.
Bir kaydı yerel değişkenlere ayırma
buildyönteminiDocumentScreenolarak yeniden düzenleyerekmetadatayöntemini çağırın ve desen değişkeni bildirimi başlatmak için kullanın:
lib/main.dart
class DocumentScreen extends StatelessWidget {
final Document document;
const DocumentScreen({required this.document, super.key});
@override
Widget build(BuildContext context) {
final (title, modified: modified) = document.metadata; // Modify
return Scaffold(
appBar: AppBar(title: Text(title)), // Modify from here...
body: Column(children: [Center(child: Text('Last modified $modified'))]),
); // To here.
}
}
Kayıt kalıbı (title, modified: modified), metadata tarafından döndürülen kaydın alanlarıyla eşleşen iki değişken kalıbı içerir.
- Sonuç, iki alanlı bir kayıt olduğu ve bu alanlardan birinin adı
modifiedolduğu için ifade alt kalıpla eşleşir. - Eşleşme nedeniyle değişken bildirimi kalıbı, ifadeyi yapılandırarak değerlerine erişir ve bunları aynı tür ve adlara sahip yeni yerel değişkenlere (
String titleveDateTime modified) bağlar.
Bir alanın adı ile onu dolduran değişken aynı olduğunda kullanılan bir kısaltma vardır. DocumentScreen öğesinin build yöntemini aşağıdaki gibi yeniden düzenleyin.
lib/main.dart
class DocumentScreen extends StatelessWidget {
final Document document;
const DocumentScreen({required this.document, super.key});
@override
Widget build(BuildContext context) {
final (title, :modified) = document.metadata; // Modify
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Column(children: [Center(child: Text('Last modified $modified'))]),
);
}
}
Değişken kalıbının :modified söz dizimi, modified: modified için kısa yazım şeklidir. Farklı bir ada sahip yeni bir yerel değişken istiyorsanız bunun yerine modified: localModified yazabilirsiniz.
- Önceki adımdaki sonucu görmek için sıcak yeniden yükleme yapın. Davranış tam olarak aynıdır. Yalnızca kodunuzu daha kısa hale getirdiniz.
7. Verileri çıkarmak için kalıpları kullanma
Belirli bağlamlarda kalıplar yalnızca eşleşip yapıyı bozmakla kalmaz, aynı zamanda kalıbın eşleşip eşleşmemesine bağlı olarak kodun ne yaptığı hakkında bir karar da verebilir. Bunlara çürütülebilir kalıplar denir.
Son adımda kullandığınız değişken bildirimi kalıbı kesin bir kalıptır: Değer, kalıpla eşleşmelidir. Aksi takdirde hata oluşur ve yapı bozma işlemi gerçekleşmez. Herhangi bir değişken bildirimi veya ataması yapıldığını düşünün. Aynı türde değillerse bir değişkene değer atayamazsınız.
Öte yandan, çürütülebilir kalıplar kontrol akışı bağlamlarında kullanılır:
- Karşılaştırdıkları bazı değerlerin eşleşmeyeceğini beklerler.
- Değerin eşleşip eşleşmemesine bağlı olarak kontrol akışını etkilemek için tasarlanmıştır.
- Eşleşmiyorlarsa yürütmeyi hatayla kesmezler, yalnızca bir sonraki ifadeye geçerler.
- Yalnızca eşleştiğinde kullanılabilen değişkenleri yapılandırabilir ve bağlayabilir.
JSON değerlerini kalıpsız okuma
Bu bölümde, kalıpların JSON verileriyle çalışmanıza nasıl yardımcı olabileceğini görmek için kalıp eşleştirme olmadan verileri okuyacaksınız.
metadata'nın önceki sürümünü, değerleri_jsonharitasından okuyan bir sürümle değiştirin.metadatasürümünü kopyalayıpDocumentsınıfına yapıştırın:
lib/data.dart
class Document {
final Map<String, Object?> _json;
Document() : _json = jsonDecode(documentJson);
(String, {DateTime modified}) get metadata {
if (_json.containsKey('metadata')) { // Modify from here...
final metadataJson = _json['metadata'];
if (metadataJson is Map) {
final title = metadataJson['title'] as String;
final localModified = DateTime.parse(
metadataJson['modified'] as String,
);
return (title, modified: localModified);
}
}
throw const FormatException('Unexpected JSON'); // to here.
}
}
Bu kod, verilerin kalıplar kullanılmadan doğru şekilde yapılandırıldığını doğrular. Daha sonraki bir adımda, daha az kod kullanarak aynı doğrulamayı yapmak için kalıp eşleştirme özelliğini kullanırsınız. Başka bir işlem yapmadan önce üç kontrol gerçekleştirir:
- JSON, beklediğiniz yapı verilerini içeriyor:
if (_json.containsKey('metadata')) - Veriler, beklediğiniz türde olmalıdır:
if (metadataJson is Map) - Verilerin boş olmadığını (bu, önceki kontrolde örtülü olarak onaylanır).
Harita kalıbı kullanarak JSON değerlerini okuma
Çürütülebilir bir kalıpla, harita kalıbı kullanarak JSON'un beklenen yapıya sahip olduğunu doğrulayabilirsiniz.
metadata'nın önceki sürümünü şu kodla değiştirin:
lib/data.dart
class Document {
final Map<String, Object?> _json;
Document() : _json = jsonDecode(documentJson);
(String, {DateTime modified}) get metadata {
if (_json case { // Modify from here...
'metadata': {'title': String title, 'modified': String localModified},
}) {
return (title, modified: DateTime.parse(localModified));
} else {
throw const FormatException('Unexpected JSON');
} // to here.
}
}
Burada, Dart 3'te kullanıma sunulan yeni bir if-statement türü olan if-case'i görüyorsunuz. Case gövdesi yalnızca case kalıbı _json içindeki verilerle eşleşirse yürütülür. Bu eşleşme, gelen JSON'ı doğrulamak için metadata'nın ilk sürümünde yazdığınız kontrollerin aynısını gerçekleştirir. Bu kod aşağıdakileri doğrular:
_json, bir Harita türüdür._json,metadataanahtarı içeriyor._jsonboş değil._json['metadata']da bir harita türüdür._json['metadata'],titlevemodifiedanahtarlarını içerir.titlevelocalModifieddizelerdir ve boş değildir.
Değer eşleşmezse desen çürütülür (yürütme devam etmez) ve else ifadesine geçilir. Eşleşme başarılı olursa desen, haritadaki title ve modified değerlerini yapılandırır ve yeni yerel değişkenlere bağlar.
Desenlerin tam listesi için özellik spesifikasyonunun Desenler bölümündeki tabloya bakın.
8. Uygulamayı daha fazla desene hazırlama
Şimdiye kadar JSON verilerinin metadata bölümünü ele aldınız. Bu adımda, blocks listesindeki verileri işlemek ve uygulamanızda oluşturmak için işletme mantığınızı biraz daha ayrıntılı hale getirirsiniz.
{
"metadata": {
// ...
},
"blocks": [
{
"type": "h1",
"text": "Chapter 1"
},
// ...
]
}
Veri depolayan bir sınıf oluşturma
- JSON verilerindeki bloklardan birinin verilerini okumak ve depolamak için kullanılan
data.dart'ye yeni bir sınıf (Block) ekleyin.
lib/data.dart
class Block {
final String type;
final String text;
Block(this.type, this.text);
factory Block.fromJson(Map<String, dynamic> json) {
if (json case {'type': final type, 'text': final text}) {
return Block(type, text);
} else {
throw const FormatException('Unexpected JSON format');
}
}
}
Fabrika oluşturucu fromJson(), daha önce gördüğünüz harita deseniyle aynı if-case'i kullanır.
JSON verilerinin, kalıpta bulunmayan checked adlı ek bir bilgiye sahip olmasına rağmen beklenen kalıba benzediğini görürsünüz. Bunun nedeni, bu tür kalıpları ("harita kalıpları" olarak adlandırılır) kullandığınızda yalnızca kalıpta tanımladığınız belirli şeyleri dikkate almaları ve verilerdeki diğer her şeyi yoksaymalarıdır.
Block nesnelerinin listesini döndürme
- Ardından,
DocumentsınıfınagetBlocks()adlı yeni bir işlev ekleyin.getBlocks(), JSON'ıBlocksınıfının örneklerine ayrıştırır ve kullanıcı arayüzünüzde oluşturulacak blokların listesini döndürür:
lib/data.dart
class Document {
final Map<String, Object?> _json;
Document() : _json = jsonDecode(documentJson);
(String, {DateTime modified}) get metadata {
if (_json case {
'metadata': {'title': String title, 'modified': String localModified},
}) {
return (title, modified: DateTime.parse(localModified));
} else {
throw const FormatException('Unexpected JSON');
}
}
List<Block> getBlocks() { // Add from here...
if (_json case {'blocks': List blocksJson}) {
return [for (final blockJson in blocksJson) Block.fromJson(blockJson)];
} else {
throw const FormatException('Unexpected JSON format');
}
} // to here.
}
getBlocks() işlevi, daha sonra kullanıcı arayüzünü oluşturmak için kullandığınız Block nesnelerinin listesini döndürür. Tanıdık bir if-case ifadesi doğrulama gerçekleştirir ve blocks meta verilerinin değerini blocksJson adlı yeni bir List'ye dönüştürür (desenler olmadan dönüştürmek için toList() yöntemini kullanmanız gerekir).
Liste değişmezi, yeni listeyi Block nesneleriyle doldurmak için bir collection for içerir.
Bu bölümde, bu codelab'de daha önce denemediğiniz desenle ilgili özellikler tanıtılmamaktadır. Sonraki adımda, kullanıcı arayüzünüzdeki liste öğelerini oluşturmaya hazırlanır.
9. Dokümanı görüntülemek için desenleri kullanma
Artık bir if-case ifadesi ve çürütülebilir kalıplar kullanarak JSON verilerinizi başarılı bir şekilde yapılandırabilir ve yeniden oluşturabilirsiniz. Ancak if-case, kalıplarla birlikte gelen kontrol akışı yapılarındaki geliştirmelerden yalnızca biridir. Şimdi, çürütülebilir kalıplarla ilgili bilginizi switch ifadelerine uygulayın.
Anahtar ifadeleriyle desenleri kullanarak neyin oluşturulacağını kontrol etme
main.dartiçinde, her bloğun stilinitypealanına göre belirleyen yeni bir widget (BlockWidget) oluşturun.
lib/main.dart
class BlockWidget extends StatelessWidget {
final Block block;
const BlockWidget({required this.block, super.key});
@override
Widget build(BuildContext context) {
TextStyle? textStyle;
switch (block.type) {
case 'h1':
textStyle = Theme.of(context).textTheme.displayMedium;
case 'p' || 'checkbox':
textStyle = Theme.of(context).textTheme.bodyMedium;
case _:
textStyle = Theme.of(context).textTheme.bodySmall;
}
return Container(
margin: const EdgeInsets.all(8),
child: Text(block.text, style: textStyle),
);
}
}
build yöntemindeki switch ifadesi, block nesnesinin type alanını açar.
- İlk case ifadesinde sabit dize kalıbı kullanılır.
block.type, sabit değerh1'ye eşitse kalıp eşleşir. - İkinci case ifadesi, alt kalıpları olarak iki sabit dize kalıbı içeren bir mantıksal VEYA kalıbı kullanır.
block.type,pveyacheckboxalt kalıplarından biriyle eşleşirse kalıp eşleşir.
- Son durum,
_joker karakter kalıbıdır. Switch ifadelerindeki joker karakterler diğer her şeyle eşleşir. Bunlar, switch ifadelerinde hâlâ izin verilendefaultifadeleriyle aynı şekilde davranır (yalnızca biraz daha ayrıntılıdır).
Joker karakter kalıpları, kalıba izin verilen her yerde kullanılabilir. Örneğin, değişken bildirimi kalıbında: var (title, _) = document.metadata;
Bu bağlamda, joker karakter herhangi bir değişkeni bağlamaz. İkinci alanı siler.
Sonraki bölümde, Block nesneleri görüntülendikten sonra daha fazla anahtar özelliği hakkında bilgi edineceksiniz.
Doküman içeriğini görüntüleme
Block nesnelerinin listesini içeren bir yerel değişken oluşturmak için DocumentScreen widget'ının build yönteminde getBlocks() işlevini çağırın.
DocumentationScreeniçindeki mevcutbuildyöntemini bu sürümle değiştirin:
lib/main.dart
class DocumentScreen extends StatelessWidget {
final Document document;
const DocumentScreen({required this.document, super.key});
@override
Widget build(BuildContext context) {
final (title, :modified) = document.metadata;
final blocks = document.getBlocks(); // Add this line
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Column(
children: [
Text('Last modified: $modified'), // Modify from here
Expanded(
child: ListView.builder(
itemCount: blocks.length,
itemBuilder: (context, index) {
return BlockWidget(block: blocks[index]);
},
),
), // to here.
],
),
);
}
}
BlockWidget(block: blocks[index]) satırı, getBlocks() yönteminden döndürülen blok listesindeki her öğe için bir BlockWidget widget'ı oluşturur.
- Uygulamayı çalıştırın. Ardından ekranda blokların göründüğünü görmelisiniz:

10. Anahtar ifadeleri kullanma
Kalıplar, switch ve case'ye birçok özellik ekler. Dart, switch ifadeleri sayesinde bu ifadelerin daha fazla yerde kullanılabilmesini sağlar. Bir dizi durum, doğrudan bir değişken atamasına veya döndürme ifadesine değer sağlayabilir.
Anahtar ifadesini anahtar ifadesine dönüştürme
Dart analiz aracı, kodunuzda değişiklik yapmanıza yardımcı olacak yardımlar sunar.
- İmlecinizi önceki bölümdeki switch ifadesine taşıyın.
- Mevcut destekleri görüntülemek için ampulü tıklayın.
- Convert to switch expression (Anahtar ifadesine dönüştür) yardımını seçin.

Bu kodun yeni sürümü şu şekilde görünür:
lib/main.dart
class BlockWidget extends StatelessWidget {
final Block block;
const BlockWidget({required this.block, super.key});
@override
Widget build(BuildContext context) {
TextStyle? textStyle; // Modify from here
textStyle = switch (block.type) {
'h1' => Theme.of(context).textTheme.displayMedium,
'p' || 'checkbox' => Theme.of(context).textTheme.bodyMedium,
_ => Theme.of(context).textTheme.bodySmall,
}; // to here.
return Container(
margin: const EdgeInsets.all(8),
child: Text(block.text, style: textStyle),
);
}
}
Bir switch ifadesi, switch ifadesine benzer ancak case anahtar kelimesini ortadan kaldırır ve kalıbı case gövdesinden ayırmak için => kullanır. Switch ifadelerinden farklı olarak, switch ifadeleri bir değer döndürür ve bir ifadenin kullanılabildiği her yerde kullanılabilir.
11. Nesne kalıplarını kullanma
Dart, nesne yönelimli bir dil olduğundan desenler tüm nesneler için geçerlidir. Bu adımda, kullanıcı arayüzünüzün tarih oluşturma mantığını geliştirmek için bir nesne kalıbı etkinleştirir ve nesne özelliklerini yapılandırılmış hale getirirsiniz.
Özellikleri nesne desenlerinden çıkarma
Bu bölümde, son değiştirilme tarihinin nasıl görüntülendiğini kalıpları kullanarak iyileştirirsiniz.
main.dartöğesineformatDateyöntemini ekleyin:
lib/main.dart
String formatDate(DateTime dateTime) {
final today = DateTime.now();
final difference = dateTime.difference(today);
return switch (difference) {
Duration(inDays: 0) => 'today',
Duration(inDays: 1) => 'tomorrow',
Duration(inDays: -1) => 'yesterday',
Duration(inDays: final days, isNegative: true) => '${days.abs()} days ago',
Duration(inDays: final days) => '$days days from now',
};
}
Bu yöntem, difference değerine (Duration nesnesi) göre seçim yapan bir switch ifadesi döndürür. today ile JSON verilerindeki modified değeri arasındaki zaman aralığını gösterir.
Anahtar ifadesinin her durumu, nesnenin inDays ve isNegative özelliklerinde alıcılar çağrılarak eşleşen bir nesne kalıbı kullanıyor. Söz dizimi, bir süre nesnesi oluşturuyormuş gibi görünüyor ancak aslında difference nesnesindeki alanlara erişiyor.
İlk üç örnekte, inDays nesne özelliğiyle eşleşmek ve ilgili dizeyi döndürmek için sabit alt desenler 0, 1 ve -1 kullanılır.
Son iki örnekte, bugün, dün ve yarının dışındaki süreler ele alınır:
isNegativeözelliği, boolean sabit kalıbıylatrueeşleşiyorsa (yani değişiklik tarihi geçmişteyse) gün önce gösterilir.- Bu durum farkı yakalamazsa sürenin pozitif bir gün sayısı olması gerekir (
isNegative: falseile açıkça doğrulamaya gerek yoktur). Bu nedenle, değiştirme tarihi gelecektedir ve günden itibaren gösterilir.
Haftalar için biçimlendirme mantığı ekleme
- 7 günden uzun süreleri belirlemek için biçimlendirme işlevinize iki yeni durum ekleyin. Böylece kullanıcı arayüzü bu süreleri hafta olarak gösterebilir:
lib/main.dart
String formatDate(DateTime dateTime) {
final today = DateTime.now();
final difference = dateTime.difference(today);
return switch (difference) {
Duration(inDays: 0) => 'today',
Duration(inDays: 1) => 'tomorrow',
Duration(inDays: -1) => 'yesterday',
Duration(inDays: final days) when days > 7 => '${days ~/ 7} weeks from now', // Add from here
Duration(inDays: final days) when days < -7 =>
'${days.abs() ~/ 7} weeks ago', // to here.
Duration(inDays: final days, isNegative: true) => '${days.abs()} days ago',
Duration(inDays: final days) => '$days days from now',
};
}
Bu kod, koruma ifadelerini tanıtır:
- Koruma ifadesi, bir durum kalıbından sonra
whenanahtar kelimesini kullanır. - Bunlar if-case'lerde, switch ifadelerinde ve switch ifadelerinde kullanılabilir.
- Yalnızca eşleştirildikten sonra bir desene koşul eklerler.
- Koruma koşulu yanlış olarak değerlendirilirse tüm kalıp çürütülür ve yürütme bir sonraki duruma geçer.
Yeni biçimlendirilmiş tarihi kullanıcı arayüzüne ekleme
- Son olarak,
formatDateişlevini kullanmak içinDocumentScreeniçindekibuildyöntemini güncelleyin:
lib/main.dart
class DocumentScreen extends StatelessWidget {
final Document document;
const DocumentScreen({required this.document, super.key});
@override
Widget build(BuildContext context) {
final (title, :modified) = document.metadata;
final formattedModifiedDate = formatDate(modified); // Add this line
final blocks = document.getBlocks();
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Column(
children: [
Text('Last modified: $formattedModifiedDate'), // Modify this line
Expanded(
child: ListView.builder(
itemCount: blocks.length,
itemBuilder: (context, index) {
return BlockWidget(block: blocks[index]);
},
),
),
],
),
);
}
}
- Uygulamanızdaki değişiklikleri görmek için anında yeniden yükleme yapın:

12. Kapsamlı anahtarlama için bir sınıfı kapatma
Son anahtarın sonunda joker karakter veya varsayılan durum kullanmadığınıza dikkat edin. Değerlerin başarısız olabileceği durumlar için her zaman bir durum eklemek iyi bir uygulama olsa da, tanımladığınız durumların tüm olası değerleri kapsadığını bildiğiniz için bu gibi basit örneklerde sorun yoktur.inDays
Bir switch ifadesindeki her durum işlendiğinde buna kapsamlı switch denir. Örneğin, bool türünde bir anahtarın true ve false durumları varsa bu anahtarın açılması kapsamlıdır. Numaralandırmalar, sabit sayıda sabit değeri temsil ettiğinden, numaralandırmanın her bir değeri için durumlar olduğunda enum türünü etkinleştirmek kapsamlıdır.
Dart 3, yeni sınıf değiştiricisi sealed ile kapsamlılık kontrolünü nesnelere ve sınıf hiyerarşilerine genişletti. Block sınıfınızı kapalı bir üst sınıf olarak yeniden düzenleyin.
Alt sınıfları oluşturma
data.dartiçinde,Block'i genişleten üç yeni sınıf oluşturun:HeaderBlock,ParagraphBlockveCheckboxBlock:
lib/data.dart
class HeaderBlock extends Block {
final String text;
HeaderBlock(this.text);
}
class ParagraphBlock extends Block {
final String text;
ParagraphBlock(this.text);
}
class CheckboxBlock extends Block {
final String text;
final bool isChecked;
CheckboxBlock(this.text, this.isChecked);
}
Bu sınıfların her biri, orijinal JSON'daki farklı type değerlerine karşılık gelir: 'h1', 'p' ve 'checkbox'.
Üst sınıfı kapatma
Blocksınıfınısealedolarak işaretleyin. Ardından, if-case ifadesini, JSON'da belirtilentypedeğerine karşılık gelen alt sınıfı döndüren bir switch ifadesi olarak yeniden düzenleyin:
lib/data.dart
sealed class Block {
Block();
factory Block.fromJson(Map<String, Object?> json) {
return switch (json) {
{'type': 'h1', 'text': String text} => HeaderBlock(text),
{'type': 'p', 'text': String text} => ParagraphBlock(text),
{'type': 'checkbox', 'text': String text, 'checked': bool checked} =>
CheckboxBlock(text, checked),
_ => throw const FormatException('Unexpected JSON format'),
};
}
}
sealed anahtar kelimesi, yalnızca aynı kitaplıkta bu sınıfı genişletebileceğiniz veya uygulayabileceğiniz anlamına gelen bir sınıf değiştiricisidir. Analiz aracı bu sınıfın alt türlerini bildiğinden, bir anahtar bunlardan birini kapsamadığında ve kapsamlı olmadığında hata bildirir.
Widget'ları görüntülemek için bir anahtar ifadesi kullanın
main.dartiçindekiBlockWidgetsınıfını, her durum için nesne kalıplarını kullanan bir anahtar ifadesiyle güncelleyin:
lib/main.dart
class BlockWidget extends StatelessWidget {
final Block block;
const BlockWidget({required this.block, super.key});
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(8),
child: switch (block) {
HeaderBlock(:final text) => Text(
text,
style: Theme.of(context).textTheme.displayMedium,
),
ParagraphBlock(:final text) => Text(text),
CheckboxBlock(:final text, :final isChecked) => Row(
children: [
Checkbox(value: isChecked, onChanged: (_) {}),
Text(text),
],
),
},
);
}
}
BlockWidget'nın ilk sürümünde, TextStyle döndürmek için Block nesnesinin bir alanını etkinleştirdiniz. Artık Block nesnesinin bir örneğini değiştirip alt sınıflarını temsil eden nesne kalıplarıyla eşleştirerek nesnenin özelliklerini çıkarabilirsiniz.
Dart analiz aracı, Block sınıfını kapalı sınıf yaptığınız için her alt sınıfın switch ifadesinde işlendiğini kontrol edebilir.
Ayrıca, burada bir switch ifadesi kullanmanın, sonucu daha önce gereken ayrı bir dönüş ifadesi yerine doğrudan child öğesine iletmenize olanak tanıdığını da unutmayın.
- Onay kutusu JSON verilerinin ilk kez oluşturulduğunu görmek için hızlı yeniden yükleme yapın:

13. Tebrikler
Desenler, kayıtlar, gelişmiş switch ve case ile sealed sınıflarını başarıyla denediniz. Çok fazla bilgi verdin ancak bu özelliklerin sadece yüzeyini çizdin. Kalıplar hakkında daha fazla bilgi için özellik spesifikasyonuna bakın.
Farklı kalıp türleri, görünebilecekleri farklı bağlamlar ve alt kalıpların olası iç içe yerleşimi, davranışlardaki olasılıkları sınırsız hale getirir. Ancak bu tür reklamlar kolayca görülebilir.
Desenleri kullanarak Flutter'da içerikleri görüntülemenin her türlü yolunu düşünebilirsiniz. Kalıpları kullanarak kullanıcı arayüzünüzü birkaç satır kodla oluşturmak için verileri güvenli bir şekilde ayıklayabilirsiniz.
Yapabilecekleriniz
- Dart dokümanlarının Dil bölümünde desenler, kayıtlar, gelişmiş switch ve case'ler ile sınıf değiştiricilerle ilgili dokümanlara göz atın.
Referans belgeler
Adım adım tam örnek kodu flutter/codelabs deposunda inceleyin.
Her yeni özelliğin ayrıntılı spesifikasyonları için orijinal tasarım belgelerine göz atın: