Flutter Tutorial in Bangla দ্বিতীয় পর্ব: একদম Beginner থেকে বেসিক লেভেল পর্যন্ত সম্পূর্ণ গাইড (২০২৬)

Flutter Tutorial in Bangla দ্বিতীয় পর্ব: একদম Beginner থেকে বেসিক লেভেল পর্যন্ত সম্পূর্ণ গাইড (২০২৬)
গতপর্বে আমরা Flutter শেখার শুরুর ধাপ নিয়ে আলোচনা করেছিলাম। আজ থেকে শুরু হচ্ছে আমাদের Dart Programming শেখার আসল যাত্রা। Day 2-এ আমরা একদম গভীরভাবে বুঝব Dart-এর ছয়টা সবচেয়ে গুরুত্বপূর্ণ বেসিক কনসেপ্ট — কেন এগুলো লাগে, কীভাবে কাজ করে, কোথায় ভুল হয়, আর বাস্তব প্রজেক্টে কীভাবে ব্যবহার হয়। শেষে সবকিছু একসাথে করে বানাবো একটা সম্পূর্ণ Simple Calculator।
এই আর্টিকেলটা একটু লম্বা, কিন্তু ইচ্ছা করেই — কারণ Dart-এর এই বেসিক জিনিসগুলোই সামনে পুরো Flutter জার্নির ভিত্তি হয়ে থাকবে। তাড়াহুড়া না করে প্রতিটা অংশ নিজে হাতে টাইপ করে প্র্যাকটিস করুন।
১. Variables (ভ্যারিয়েবল) — গভীরভাবে
### ভ্যারিয়েবল আসলে কী, এবং কেন লাগে?
প্রোগ্রামিং-এ আমরা সবসময় ডেটা নিয়ে কাজ করি — কারো নাম, বয়স, দাম, স্কোর, ইত্যাদি। এই ডেটাগুলো কম্পিউটারের মেমোরিতে (RAM-এ) সংরক্ষণ করে রাখার জন্য একটা নাম দরকার হয়, যাতে পরে সেই নাম ধরে ডেটাটা আবার ব্যবহার করা যায়। এই নামটাই হলো ভ্যারিয়েবল।
ধরা যাক, আপনি একটা দোকানে গিয়ে ৫টা আপেল কিনলেন, প্রতিটার দাম ১০ টাকা। মোট দাম হিসাব করতে আপনাকে সংখ্যাগুলো কোথাও রাখতে হবে:
void main() {
int totalApples = 5;
int pricePerApple = 10;
int totalPrice = totalApples * pricePerApple;print("Total Price: $totalPrice টাকা"); } ```
এখানে `totalApples`, `pricePerApple`, `totalPrice` — এই তিনটাই ভ্যারিয়েবল। এগুলো ছাড়া আমাদের প্রতিবার সরাসরি সংখ্যা লিখতে হতো, যা কোড পড়া ও মেইনটেইন করা কঠিন করে ফেলত।
### var, final, const — পার্থক্য বিস্তারিতভাবে
Dart-এ ভ্যারিয়েবল ডিক্লেয়ার করার তিনটা মূল উপায় আছে, আর এই তিনটার মধ্যে পার্থক্য বোঝাটা খুব গুরুত্বপূর্ণ।
`var` — পরিবর্তনযোগ্য, টাইপ অটো-ডিটেক্ট
void main() {
var name = "Tarikul";
print(name); // Tarikulname = "Rahim"; // পরিবর্তন করা যাচ্ছে, সমস্যা নেই print(name); // Rahim
// name = 25; // এটা এরর দেবে! কারণ Dart প্রথমেই বুঝে নিয়েছে name একটা String } ```
`var` দিয়ে ডিক্লেয়ার করলে Dart প্রথম মান দেখে টাইপ ঠিক করে নেয় (এটাকে Type Inference বলে), কিন্তু একবার টাইপ ঠিক হয়ে গেলে সেই টাইপ পরিবর্তন করা যায় fix করা যায় না — শুধু মান পরিবর্তন করা যায়।
`final` — একবার সেট, আর পরিবর্তন নয়
void main() {
final String city = "Dhaka";
print(city);// city = "Chittagong"; // এরর! final ভ্যারিয়েবল পরিবর্তন করা যায় না } ```
`final` সাধারণত তখন ব্যবহার করা হয়, যখন কোনো মান রানটাইমে (প্রোগ্রাম চলার সময়) নির্ধারিত হয়, কিন্তু একবার সেট হয়ে গেলে সেটা আর বদলাবে না। যেমন — কোনো ইউজারের আইডি, যা লগইনের সময় সার্ভার থেকে আসে।
`const` — কম্পাইল-টাইম কনস্ট্যান্ট
void main() {
const double pi = 3.1416;
const int maxUsers = 100;print(pi); print(maxUsers); } ```
`const` অনেকটা `final`-এর মতোই, কিন্তু আরও কড়া — এর মান প্রোগ্রাম কম্পাইল হওয়ার সময়েই জানা থাকতে হবে। এটা runtime-এ নির্ধারিত কোনো মান (যেমন API থেকে আসা ডেটা) দিয়ে সেট করা যায় না। সাধারণত ফিক্সড মান — যেমন pi-এর মান, অ্যাপের ভার্সন নাম্বার, ইত্যাদির জন্য `const` ব্যবহার হয়।
### Variable Naming Rules
Dart-এ ভ্যারিয়েবলের নাম দেওয়ার কিছু নিয়ম আছে:
- নাম অক্ষর বা `_` দিয়ে শুরু হতে হবে, সংখ্যা দিয়ে শুরু করা যাবে না (`1name` ভুল, `name1` ঠিক)
- Dart-এর কনভেনশন হলো camelCase ব্যবহার করা — যেমন `firstName`, `totalPrice`
- Dart-এর রিজার্ভড কিওয়ার্ড (যেমন `class`, `void`, `return`) ভ্যারিয়েবল নাম হিসেবে ব্যবহার করা যাবে না
২. Data Types (ডেটা টাইপ) — গভীরভাবে
Dart একটা strongly-typed ল্যাঙ্গুয়েজ, মানে প্রতিটা ভ্যারিয়েবলের একটা নির্দিষ্ট টাইপ থাকে, আর সেই টাইপ অনুযায়ীই তার আচরণ নির্ধারিত হয়।
### Numeric Types: int ও double
void main() {
int quantity = 10; // দশমিক ছাড়া পূর্ণ সংখ্যা
double weight = 65.5; // দশমিকযুক্ত সংখ্যাprint(quantity.runtimeType); // int print(weight.runtimeType); // double
// int আর double নিয়ে ক্যালকুলেশন করলে ফলাফল double হয়ে যায় double result = quantity / 3; print(result); // 3.333... } ```
একটা কমন ভুল যা নতুনরা করে: `int` দিয়ে ভাগ করলে ফলাফল সবসময় পূর্ণ সংখ্যা হবে ভেবে নেয়। কিন্তু Dart-এ `/` অপারেটর সবসময় `double` রিটার্ন করে, যদি আসল পূর্ণ সংখ্যা ভাগফল চান তাহলে `~/` (integer division) ব্যবহার করতে হবে:
void main() {
print(10 / 3); // 3.3333333333333335 (double)
print(10 ~/ 3); // 3 (int, দশমিক অংশ বাদ)
}
### String
void main() {
String firstName = "Tarikul";
String lastName = "Islam";// String Concatenation (জোড়া লাগানো) String fullName = firstName + " " + lastName; print(fullName);
// String Interpolation — এটাই বেশি ব্যবহার হয় print("Full Name: ${firstName} ${lastName}"); print("Name length: ${firstName.length}");
// কমন String মেথড print(firstName.toUpperCase()); // TARIKUL print(firstName.toLowerCase()); // tarikul print(firstName.contains("rik")); // true } ```
### bool
void main() {
bool isLoggedIn = false;
bool hasPermission = true;print(isLoggedIn); print(hasPermission);
// সাধারণত কন্ডিশনের সাথে ব্যবহার হয় if (hasPermission) { print("অ্যাক্সেস দেওয়া হলো"); } } ```
### List — একাধিক মান রাখার অ্যারে
void main() {
List<String> fruits = ["Apple", "Mango", "Banana"];print(fruits[0]); // Apple (index শুরু হয় 0 থেকে) print(fruits.length); // 3
fruits.add("Orange"); // যুক্ত করা fruits.remove("Mango"); // বাদ দেওয়া print(fruits); // [Apple, Banana, Orange]
// Loop দিয়ে সব এলিমেন্ট দেখা for (var fruit in fruits) { print(fruit); } } ```
### Map — key-value জোড়া
void main() {
Map<String, dynamic> student = {
"name": "Tarikul",
"age": 22,
"isActive": true,
};print(student["name"]); // Tarikul print(student["age"]); // 22
student["age"] = 23; // মান পরিবর্তন student["city"] = "Dhaka"; // নতুন key যুক্ত করা
print(student); } ```
### dynamic ও var-এর পার্থক্য
অনেকেই `dynamic` আর `var`-কে গুলিয়ে ফেলেন। `var` একবার টাইপ ফিক্স হয়ে গেলে বদলানো যায় না, কিন্তু `dynamic` দিয়ে ডিক্লেয়ার করা ভ্যারিয়েবলের টাইপ পুরো প্রোগ্রামে যতবার ইচ্ছা বদলানো যায়:
void main() {
dynamic value = "Hello";
print(value); // Hellovalue = 100; // সমস্যা নেই, টাইপ বদলে গেল print(value); // 100 } ```
সাধারণত `dynamic` এড়িয়ে যাওয়া ভালো, কারণ এতে টাইপ-সেফটি নষ্ট হয় এবং রানটাইমে ভুল হওয়ার সম্ভাবনা বাড়ে।
৩. Operators (অপারেটর) — গভীরভাবে
### Arithmetic Operators
void main() {
int a = 10, b = 3;print("Addition: ${a + b}"); // 13 print("Subtraction: ${a - b}"); // 7 print("Multiplication: ${a * b}"); // 30 print("Division: ${a / b}"); // 3.333... print("Integer Division: ${a ~/ b}"); // 3 print("Modulus: ${a % b}"); // 1 (ভাগশেষ) } ```
Modulus (%) অপারেটরটা নতুনদের কাছে একটু কনফিউজিং লাগে, কিন্তু এটা অত্যন্ত কাজের — যেমন কোনো সংখ্যা জোড় (even) নাকি বিজোড় (odd) সেটা চেক করার জন্য এটাই সবচেয়ে বেশি ব্যবহার হয়:
void main() {
int number = 7;
if (number % 2 == 0) {
print("Even");
} else {
print("Odd");
}
}
### Assignment Operators
void main() {
int x = 10;x += 5; // x = x + 5 → 15 x -= 3; // x = x - 3 → 12 x *= 2; // x = x * 2 → 24 x ~/= 4; // x = x ~/ 4 → 6
print(x); } ```
### Comparison Operators
void main() {
int a = 5, b = 8;print(a == b); // false — সমান কিনা print(a != b); // true — অসমান কিনা print(a > b); // false print(a < b); // true print(a >= 5); // true print(a <= 4); // false } ```
### Logical Operators
void main() {
bool hasTicket = true;
bool hasID = false;print(hasTicket && hasID); // AND — দুটোই true হলে true → false print(hasTicket || hasID); // OR — যেকোনো একটা true হলে true → true print(!hasTicket); // NOT — উল্টো করে দেয় → false } ```
### Null-aware Operators (Dart-এর স্পেশাল ফিচার)
Dart-এ Null Safety একটা বড় বিষয়, আর কিছু স্পেশাল অপারেটর null হ্যান্ডলিং সহজ করে দেয়:
void main() {
String? name; // ? মানে এই ভ্যারিয়েবল null হতে পারেprint(name ?? "Guest"); // name null হলে "Guest" দেখাবে
name = "Tarikul"; print(name ?? "Guest"); // Tarikul দেখাবে, কারণ null নয়
int? age; age ??= 18; // age null হলে তখনই মান সেট হবে print(age); // 18 } ```
৪. Conditions (কন্ডিশনাল স্টেটমেন্ট) — গভীরভাবে
### if, else if, else
void main() {
int marks = 75;if (marks >= 80) { print("Grade: A+"); } else if (marks >= 70) { print("Grade: A"); } else if (marks >= 60) { print("Grade: A-"); } else if (marks >= 40) { print("Grade: C"); } else { print("Grade: Fail"); } } ```
এখানে গুরুত্বপূর্ণ ব্যাপার হলো, Dart উপর থেকে নিচে কন্ডিশন চেক করে এবং যেই কন্ডিশনটা প্রথম true হয়, সেটার ব্লক রান করেই বাকি সব চেক করা বন্ধ করে দেয়। তাই কন্ডিশনগুলোর ক্রম (order) গুরুত্বপূর্ণ।
### Nested if (একটার ভিতরে আরেকটা কন্ডিশন)
void main() {
bool isLoggedIn = true;
String role = "admin";if (isLoggedIn) { if (role == "admin") { print("অ্যাডমিন প্যানেলে স্বাগতম"); } else { print("সাধারণ ইউজার ডাশবোর্ড"); } } else { print("প্রথমে লগইন করুন"); } } ```
### switch-case
`switch` তখন বেশি কাজে লাগে, যখন একটা ভ্যারিয়েবলের একাধিক নির্দিষ্ট মানের ওপর ভিত্তি করে সিদ্ধান্ত নিতে হয়:
void main() {
String day = "Saturday";switch (day) { case "Friday": print("সাপ্তাহিক ছুটির দিন"); break; case "Saturday": print("অফিস ডে শুরু"); break; case "Sunday": print("সাপ্তাহিক ছুটির দিন"); break; default: print("সাধারণ কর্মদিবস"); } } ```
`break` না দিলে Dart পরের case-গুলোতেও চলে যাবে (fall-through), তাই প্রতিটা case-এর শেষে `break` দেওয়া জরুরি।
### Ternary Operator (শর্টকাট if-else)
void main() {
int age = 20;
String status = age >= 18 ? "Adult" : "Minor";
print(status); // Adult
}
এটা ছোট ছোট কন্ডিশনের জন্য কোড আরও সংক্ষিপ্ত করে ফেলে।
৫. Loops (লুপ) — গভীরভাবে
### for loop
void main() {
for (int i = 1; i <= 5; i++) {
print("Number: ${i}");
}
}
`for` লুপের তিনটা অংশ: শুরুর মান (`int i = 1`), শর্ত (`i <= 5`), এবং প্রতিবার কী পরিবর্তন হবে (`i++`)। যতক্ষণ শর্ত true থাকবে, লুপ চলতে থাকবে।
### while loop
void main() {
int count = 1;
while (count <= 5) {
print("Count: ${count}");
count++;
}
}
`while` তখন বেশি উপযোগী, যখন লুপ কতবার চলবে তা আগে থেকে জানা থাকে ঘন — বরং একটা শর্তের ওপর নির্ভর করে।
### do-while loop
void main() {
int number = 1;
do {
print("Number: ${number}");
number++;
} while (number <= 3);
}
`do-while`-এর বিশেষত্ব হলো এটা কন্ডিশন চেক করার আগেই একবার কোড ব্লক রান করে ফেলে — অর্থাৎ, কমপক্ষে একবার তো চলবেই, শর্ত যাই হোক না কেন।
### for-in loop
void main() {
List<String> cities = ["Dhaka", "Chittagong", "Sylhet"];for (var city in cities) { print(city); } } ```
### break ও continue
void main() {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break; // লুপ সম্পূর্ণ বন্ধ হয়ে যাবে
}
print(i);
}print("---");
for (int i = 1; i <= 5; i++) { if (i == 3) { continue; // এই ধাপ স্কিপ করে পরের ধাপে যাবে } print(i); } } ```
### Nested Loop (লুপের ভিতরে লুপ)
void main() {
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
print("i=${i}, j=${j}");
}
}
}
এটা প্রায়ই ব্যবহার হয় টেবিল, গ্রিড বা প্যাটার্ন তৈরির ক্ষেত্রে।
৬. Functions (ফাংশন) — গভীরভাবে
### কেন ফাংশন লাগে?
ফাংশন ছাড়া একই কোড বারবার লিখতে হয়, যা কোড বড় করে ফেলে ও ভুল হওয়ার সম্ভাবনা বাড়ায়। ফাংশন দিয়ে একটা কাজ একবার লিখে বারবার ব্যবহার করা যায় — এটাকে বলে DRY (Don't Repeat Yourself) প্রিন্সিপল।
### সাধারণ ফাংশন
void greet(String name) {
print("Hello, ${name}!");
}void main() { greet("Tarikul"); greet("Rahim"); } ```
### রিটার্ন ভ্যালু সহ ফাংশন
int add(int a, int b) {
return a + b;
}void main() { int result = add(5, 7); print("Sum: ${result}"); } ```
### Optional ও Default Parameter
int multiply(int a, [int b = 2]) {
return a * b;
}void main() { print(multiply(5)); // 10 (ডিফল্ট b=2 ব্যবহার হবে) print(multiply(5, 3)); // 15 } ```
### Named Parameter (নাম উল্লেখ করে ভ্যালু পাস করা)
Flutter-এ Widget তৈরির সময় এই স্টাইল খুব বেশি দেখা যায়, তাই এখনই এর সাথে পরিচিত হওয়া ভালো:
void showProfile({required String name, int age = 18}) {
print("Name: ${name}, Age: ${age}");
}void main() { showProfile(name: "Tarikul", age: 22); showProfile(name: "Rahim"); // age ডিফল্ট 18 হবে } ```
### Arrow Function (একলাইনের শর্টকাট)
int square(int x) => x * x;void main() { print(square(5)); // 25 } ```
যেসব ফাংশনের বডি একটামাত্র লাইনের এক্সপ্রেশন, সেগুলো `=>` দিয়ে সংক্ষেপে লেখা যায়।
Project: Simple Calculator (সম্পূর্ণ ব্যাখ্যা সহ)
এখন উপরের সব কনসেপ্ট একসাথে ব্যবহার করে বানানো যাক একটা কনসোল-বেসড Simple Calculator। এটা এখনো Flutter UI ছাড়া, শুধু Dart লজিক প্র্যাকটিসের জন্য — তবে এই লজিকটাই পরে আমরা Flutter UI-এর সাথে জুড়ে দেব।
import 'dart:io';// ক্যালকুলেশনের মূল লজিক আলাদা ফাংশনে রাখা হলো, যাতে কোড পরিষ্কার থাকে double calculate(double num1, double num2, String operator) { double result = 0;
switch (operator) { case '+': result = num1 + num2; break; case '-': result = num1 - num2; break; case '*': result = num1 * num2; break; case '/': if (num2 != 0) { result = num1 / num2; } else { print("ভুল: শূন্য দিয়ে ভাগ করা যায় না!"); return 0; } break; case '%': result = num1 % num2; break; default: print("ভুল অপারেটর দেওয়া হয়েছে।"); }
return result; }
void main() { bool continueCalculation = true;
print("=== Simple Calculator ===");
// while loop দিয়ে ইউজারকে বারবার ক্যালকুলেশনের সুযোগ দেওয়া হচ্ছে while (continueCalculation) { stdout.write("প্রথম সংখ্যা দিন: "); double num1 = double.parse(stdin.readLineSync()!);
stdout.write("অপারেটর দিন (+, -, *, /, %): "); String operator = stdin.readLineSync()!;
stdout.write("দ্বিতীয় সংখ্যা দিন: "); double num2 = double.parse(stdin.readLineSync()!);
double result = calculate(num1, num2, operator); print("ফলাফল: ${result}");
stdout.write("আরেকবার হিসাব করতে চান? (yes/no): "); String choice = stdin.readLineSync()!.toLowerCase();
// ternary + condition একসাথে ব্যবহার continueCalculation = choice == "yes" ? true : false; }
print("ক্যালকুলেটর বন্ধ করা হলো। ধন্যবাদ!"); } ```
### এই প্রজেক্টে কোন কনসেপ্ট কোথায় ব্যবহার হলো — লাইন ধরে ধরে
- Variables: `num1`, `num2`, `operator`, `result`, `choice` — সবই ভ্যারিয়েবল
- Data Types: `double` (সংখ্যা), `String` (অপারেটর ও ইউজারের ইনপুট), `bool` (`continueCalculation`)
- Operators: `+`, `-`, `*`, `/`, `%` — Arithmetic; `!=`, `==` — Comparison
- Conditions: `switch-case` দিয়ে কোন অপারেশন হবে সেটা ঠিক করা হচ্ছে; `if-else` দিয়ে শূন্য ভাগ চেক করা হচ্ছে
- Loops: `while` লুপ দিয়ে ইউজারকে বারবার হিসাব করার সুযোগ দেওয়া হচ্ছে
- Functions: `calculate()` ফাংশনে পুরো লজিক আলাদা করে রাখা হয়েছে, যাতে `main()` পরিষ্কার থাকে এবং লজিক পুনঃব্যবহার করা যায়
অনুশীলনের জন্য চ্যালেঞ্জ
নিজে হাতে-কলমে চেষ্টা করলেই আসল শেখা হবে। নিচের চ্যালেঞ্জগুলো নিজে সমাধান করার চেষ্টা করুন:
1. ক্যালকুলেটরে power (^) অপারেশন যুক্ত করুন (একটা সংখ্যাকে অন্যটার পাওয়ারে তোলা) 2. ইউজার যদি ভুল অপারেটর দেয় (যেমন `&`), তাহলে সেটা সুন্দরভাবে হ্যান্ডল করুন 3. একটা নতুন ফাংশন লিখুন যা একটা লিস্টের সব সংখ্যার গড় (average) বের করে দেয় 4. `for` লুপ দিয়ে ১ থেকে ১০০ পর্যন্ত সব জোড় সংখ্যার যোগফল বের করুন 5. একটা ফাংশন লিখুন যা চেক করে একটা সংখ্যা প্রাইম (prime) নাকি না
পরের পর্বে
তৃতীয় পর্বে আমরা Dart-এর সবচেয়ে গুরুত্বপূর্ণ বিষয় Object-Oriented Programming (OOP) সম্পূর্ণ বিস্তারিতভাবে শিখব। একদম বেসিক থেকে প্রতিটি কনসেপ্ট বাস্তব উদাহরণসহ ব্যাখ্যা করা হবে, যাতে ভবিষ্যতে Flutter-এর যেকোনো বড় প্রজেক্ট সহজেই বুঝতে ও তৈরি করতে পারেন।
### এই পর্বে যা যা শিখবেন
- Dart Object-Oriented Programming (OOP)
- Class
- Object
- Constructor
- Getter
- Setter
- Inheritance
- Polymorphism
- Abstract Class
- Interface
- Mixins
### বাস্তব প্রজেক্ট
সব কনসেপ্ট শেখার পর আমরা এগুলো ব্যবহার করে একটি Student Management System তৈরি করব, যেখানে OOP-এর প্রতিটি বিষয় বাস্তবে কীভাবে ব্যবহার হয় তা ধাপে ধাপে দেখানো হবে।
ততক্ষণ পর্যন্ত আজকের Variables, Data Types, Operators, Conditions, Loops এবং Functions-এর প্রতিটি উদাহরণ নিজে হাতে লিখে প্র্যাকটিস করুন। কারণ এই বেসিক কনসেপ্টগুলোর ওপরই Dart ও Flutter-এর পরবর্তী সব বিষয় দাঁড়িয়ে আছে। যত বেশি প্র্যাকটিস করবেন, পরবর্তী পর্বগুলো তত সহজ ও উপভোগ্য হবে।