Singleton สำหรับเก็บ Array และ Global Context
บทความนี้ขยายจาก Singleton Pattern เพื่อเก็บ Array (int[]) และให้เข้าถึง Global Context ได้จากทุกที่ในแอปพลิเคชัน ผ่าน method static getContext()
ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่
Android Studio → File → New Project → Empty Activity
ขั้นตอนที่ 2: Layout - activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Singleton Array + Global Context"
android:textSize="20sp"
android:textStyle="bold"
android:layout_marginBottom="16dp" />
<Button
android:id="@+id/btnSaveArray"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="บันทึก Array ลง Singleton"
android:layout_marginBottom="12dp" />
<Button
android:id="@+id/btnShowArray"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="แสดง Array จาก Singleton (ใช้ Global Context)" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
ขั้นตอนที่ 3: Singleton Class - ArrayRepository.java
package com.example.singletonarraydemo;
import android.content.Context;
import android.util.Log;
import java.util.Arrays;
public class ArrayRepository {
private static volatile ArrayRepository instance;
private Context appContext;
private int[] storedArray;
private ArrayRepository() {}
public static ArrayRepository getInstance() {
if (instance == null) {
synchronized (ArrayRepository.class) {
if (instance == null) {
instance = new ArrayRepository();
}
}
}
return instance;
}
// Global Context Accessor - เรียกได้จากที่ไหนก็ได้: ArrayRepository.getInstance().getContext()
public static Context getGlobalContext() {
return getInstance().appContext;
}
public void init(Context context) {
if (appContext == null) {
this.appContext = context.getApplicationContext();
Log.d("ArrayRepository", "Context initialized");
}
}
public void storeArray(int[] array) {
this.storedArray = array != null ? array.clone() : new int[0];
}
public int[] getArray() {
return storedArray != null ? storedArray.clone() : new int[0];
}
public String getArrayString() {
return Arrays.toString(storedArray);
}
public void clear() {
storedArray = new int[0];
}
}
ขั้นตอนที่ 4: MainActivity.java
package com.example.singletonarraydemo;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private ArrayRepository repository;
private Button btnSave, btnShow;
private final int[] sampleArray = {33, 12, 98, 45, 67, 23};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
repository = ArrayRepository.getInstance();
repository.init(getApplicationContext());
btnSave = findViewById(R.id.btnSaveArray);
btnShow = findViewById(R.id.btnShowArray);
btnSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
repository.storeArray(sampleArray);
Toast.makeText(MainActivity.this, "บันทึก Array แล้ว: " + Arrays.toString(sampleArray), Toast.LENGTH_SHORT).show();
}
});
btnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ใช้ Global Context จาก Singleton โดยตรง
Context globalContext = ArrayRepository.getGlobalContext();
String arrayString = repository.getArrayString();
Toast.makeText(globalContext, "ข้อมูลจาก Singleton: " + arrayString, Toast.LENGTH_LONG).show();
}
});
}
}
การใช้งาน Global Context ในคลาสอื่น
// ในคลาสอื่นๆ ใดๆ ที่ไม่ใช่ Activity/Service
public class SomeHelperClass {
public void doSomething() {
Context context = ArrayRepository.getGlobalContext();
if (context != null) {
// ใช้ context ได้เลย เช่น
// SharedPreferences prefs = context.getSharedPreferences(...);
// Resources res = context.getResources();
// context.startActivity(intent); // ต้องเพิ่ม FLAG_ACTIVITY_NEW_TASK
}
}
}
⚠️ ข้อควรระวังในการใช้ Global Context
| ปัญหา | คำอธิบาย | แก้ไข |
|---|---|---|
| Memory Leak | ถ้าเก็บ Activity Context แทน Application Context | ใช้ context.getApplicationContext() เสมอ |
| Null Context | เรียกก่อน init() หรือหลัง Process ถูก Kill | Check null ก่อนใช้, เริ่มต้นใน Application class |
| Start Activity | Application Context ไม่สามารถ startActivity() ได้โดยตรง | เพิ่ม intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) |
| Dialog/Toast | ทำงานได้แต่ควรใช้ Activity Context สำหรับ Dialog | ส่ง Activity context เข้า method แทน |
Best Practice: เริ่มต้นใน Application Class
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); // Initialize Singleton ทุกตัวที่ต้องการ Context ที่นี่ ArrayRepository.getInstance().init(this); DataRepository.getInstance().init(this); } }AndroidManifest.xml:
<application android:name=".MyApp" ...>ขยายเป็น Generic Array Repository
public class GenericArrayRepository<T> { private static volatile GenericArrayRepository instance; private T[] array; private GenericArrayRepository() {} public static GenericArrayRepository getInstance() { ... } public void setArray(T[] array) { this.array = array != null ? array.clone() : null; } public T[] getArray() { return array != null ? array.clone() : null; } }สรุป
Singleton ที่ให้ Global Context และเก็บ Array ได้ ช่วยลดการส่ง Context ผ่าน Constructor หลายชั้น แต่ต้องระวัง Memory Leak และ Null Context ควร Initialize ใน Application Class และใช้ Application Context เท่านั้น