Singleton Pattern và Synchronized
Singleton là mẫu thiết kế giới hạn việc khởi tạo một lớp chỉ có một thể hiện duy nhất. Từ khóa synchronized đảm bảo chỉ một luồng (thread) có thể truy cập phương thức tại một thời điểm, quan trọng cho tính an toàn luồng (thread-safety) trong môi trường đa luồng.
Ví dụ: Singleton Dialog với synchronized
Ví dụ này demo cách quản lý ProgressDialog thông qua Singleton với phương thức getInstance() được đồng bộ hóa.
Bước 1: Tạo dự án mới
Trong Android Studio: File → New Project → điền thông tin → Finish.
Bước 2: Giao diện chính (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<Button
android:id="@+id/start"
android:text="Bắt đầu Dialog Singleton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/end"
android:text="Kết thúc Dialog Singleton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Hai nút bấm: Start hiển thị ProgressDialog, End đóng Dialog.
Bước 3: MainActivity.java
package com.example.singletondialog;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button btnStart;
SingleTonExample singletonExample;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = findViewById(R.id.start);
singletonExample = SingleTonExample.getInstance();
findViewById(R.id.end).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
singletonExample.dismiss();
}
});
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
singletonExample.show(MainActivity.this);
}
});
}
}
Bước 4: Lớp Singleton Dialog (SingleTonExample.java)
package com.example.singletondialog;
import android.app.Dialog;
import android.content.Context;
import android.view.Window;
public class SingleTonExample {
private Dialog dialog;
private static final SingleTonExample ourInstance = new SingleTonExample();
public static synchronized SingleTonExample getInstance() {
return ourInstance;
}
private SingleTonExample() { }
public void show(Context context) {
if (dialog != null && dialog.isShowing()) {
return; // Dialog đã hiển thị, không tạo mới
}
dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.layout_progress_dialog);
dialog.setCancelable(true);
dialog.show();
}
public void dismiss() {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
}
Bước 5: Layout cho Dialog (res/layout/layout_progress_dialog.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="https://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progress" />
</LinearLayout>
Chạy ứng dụng
Triển khai lên thiết bị thật. Nhấn nút "Bắt đầu Dialog Singleton" để hiển thị ProgressDialog từ lớp Singleton. Nhấn "Kết thúc" để đóng.
Ưu điểm của cách tiếp cận này
- Thread-safe:
synchronized getInstance()ngăn chặn race condition khi nhiều luồng cùng yêu cầu instance. - Quản lý vòng đời Dialog: Kiểm tra
dialog != null && dialog.isShowing()trước khi show/dismiss tránh crash. - Tái sử dụng: Chỉ tạo một Dialog instance, tiết kiệm tài nguyên.