Android में SQLite डेटाबेस के साथ RecyclerView इम्प्लीमेंटेशन
यह ट्यूटोरियल दिखाता है कि कैसे Room Database (आधुनिक) या SQLiteOpenHelper (लीगेसी) के साथ RecyclerView को जोड़ा जाता है, CRUD ऑपरेशन्स (बनाएं, पढ़ें, अपडेट करें, हटाएं) के साथ।
आधुनिक दृष्टिकोण: Room Database (अनुशंसित)
चरण 1: निर्भरताएं
dependencies {
def room_version = "2.6.1"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
implementation "androidx.recyclerview:recyclerview:1.3.2"
implementation "androidx.cardview:cardview:1.0.0"
implementation "com.google.android.material:material:1.11.0"
// Kotlin के लिए
implementation "androidx.room:room-ktx:$room_version"
}
चरण 2: Entity (टेबल परिभाषा)
@Entity(tableName = "contacts")
public class Contact {
@PrimaryKey(autoGenerate = true)
public int id;
@ColumnInfo(name = "name")
public String name;
@ColumnInfo(name = "phone_number")
public String phoneNumber;
@ColumnInfo(name = "created_at")
public long createdAt = System.currentTimeMillis();
}
चरण 3: DAO (डेटा एक्सेस ऑब्जेक्ट)
@Dao
public interface ContactDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insert(Contact contact);
@Update
int update(Contact contact);
@Delete
int delete(Contact contact);
@Query("DELETE FROM contacts WHERE id = :id")
int deleteById(int id);
@Query("SELECT * FROM contacts ORDER BY name ASC")
LiveData<List<Contact>> getAllContacts();
@Query("SELECT * FROM contacts WHERE name LIKE :query ORDER BY name ASC")
LiveData<List<Contact>> searchContacts(String query);
@Query("SELECT * FROM contacts WHERE id = :id")
Contact getContactById(int id);
}
चरण 4: Database क्लास
@Database(entities = {Contact.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public abstract ContactDao contactDao();
private static volatile AppDatabase INSTANCE;
public static AppDatabase getInstance(Context context) {
if (INSTANCE == null) {
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, "contacts_db")
.fallbackToDestructiveMigration()
.build();
}
}
}
return INSTANCE;
}
}
चरण 5: Repository (वैकल्पिक लेकिन अनुशंसित)
public class ContactRepository {
private ContactDao contactDao;
private LiveData<List<Contact>> allContacts;
public ContactRepository(Application application) {
AppDatabase db = AppDatabase.getInstance(application);
contactDao = db.contactDao();
allContacts = contactDao.getAllContacts();
}
public LiveData<List<Contact>> getAllContacts() { return allContacts; }
public LiveData<List<Contact>> searchContacts(String query) {
return contactDao.searchContacts("%" + query + "%");
}
public void insert(Contact contact) {
new InsertAsyncTask(contactDao).execute(contact);
}
private static class InsertAsyncTask extends AsyncTask<Contact, Void, Void> {
private ContactDao dao;
InsertAsyncTask(ContactDao dao) { this.dao = dao; }
@Override protected Void doInBackground(Contact... contacts) {
dao.insert(contacts[0]); return null;
}
}
}
चरण 6: ViewModel
public class ContactViewModel extends AndroidViewModel {
private ContactRepository repository;
private LiveData<List<Contact>> allContacts;
public ContactViewModel(@NonNull Application application) {
super(application);
repository = new ContactRepository(application);
allContacts = repository.getAllContacts();
}
public LiveData<List<Contact>> getAllContacts() { return allContacts; }
public LiveData<List<Contact>> searchContacts(String query) {
return repository.searchContacts(query);
}
public void insert(Contact contact) { repository.insert(contact); }
public void update(Contact contact) { /* समान पैटर्न */ }
public void delete(Contact contact) { /* समान पैटर्न */ }
}
चरण 7: एडाप्टर (DiffUtil के साथ)
public class ContactAdapter extends ListAdapter<Contact, ContactAdapter.ContactViewHolder> {
private OnItemClickListener clickListener;
private OnItemLongClickListener longClickListener;
public ContactAdapter() {
super(new DiffUtil.ItemCallback<Contact>() {
@Override public boolean areItemsTheSame(Contact old, Contact newItem) {
return old.id == newItem.id;
}
@Override public boolean areContentsTheSame(Contact old, Contact newItem) {
return old.name.equals(newItem.name) && old.phoneNumber.equals(newItem.phoneNumber);
}
});
}
@NonNull @Override
public ContactViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.contact_list_layout, parent, false);
return new ContactViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ContactViewHolder holder, int position) {
Contact contact = getItem(position);
holder.bind(contact);
}
class ContactViewHolder extends RecyclerView.ViewHolder {
TextView tvName, tvPhone;
ImageView ivEdit, ivDelete;
View container;
ContactViewHolder(View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.contactName);
tvPhone = itemView.findViewById(R.id.phoneNum);
ivEdit = itemView.findViewById(R.id.editContact);
ivDelete = itemView.findViewById(R.id.deleteContact);
container = itemView.findViewById(R.id.container); // रूट व्यू
}
void bind(Contact contact) {
tvName.setText(contact.name);
tvPhone.setText(contact.phoneNumber);
container.setOnClickListener(v -> {
if (clickListener != null) clickListener.onItemClick(contact);
});
container.setOnLongClickListener(v -> {
if (longClickListener != null) longClickListener.onItemLongClick(contact);
return true;
});
ivEdit.setOnClickListener(v -> {
if (clickListener != null) clickListener.onEditClick(contact);
});
ivDelete.setOnClickListener(v -> {
if (clickListener != null) clickListener.onDeleteClick(contact);
});
}
}
public interface OnItemClickListener {
void onItemClick(Contact contact);
void onEditClick(Contact contact);
void onDeleteClick(Contact contact);
}
public interface OnItemLongClickListener {
void onItemLongClick(Contact contact);
}
public void setOnItemClickListener(OnItemClickListener listener) { this.clickListener = listener; }
public void setOnItemLongClickListener(OnItemLongClickListener listener) { this.longClickListener = listener; }
}
चरण 8: MainActivity (LiveData ऑब्जर्वर)
public class MainActivity extends AppCompatActivity {
private ContactViewModel viewModel;
private ContactAdapter adapter;
private EditText etSearch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.myContactList);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
adapter = new ContactAdapter();
recyclerView.setAdapter(adapter);
viewModel = new ViewModelProvider(this).get(ContactViewModel.class);
// LiveData ऑब्जर्व करें
viewModel.getAllContacts().observe(this, contacts -> {
adapter.submitList(contacts);
});
// सर्च
etSearch = findViewById(R.id.etSearch);
etSearch.addTextChangedListener(new TextWatcher() {
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
viewModel.searchContacts(s.toString()).observe(MainActivity.this, contacts -> {
adapter.submitList(contacts);
});
}
@Override public void afterTextChanged(Editable s) {}
});
// FAB/बटन से जोड़ें
findViewById(R.id.btnAdd).setOnClickListener(v -> showAddDialog());
adapter.setOnItemClickListener(new ContactAdapter.OnItemClickListener() {
@Override public void onItemClick(Contact contact) { /* डिटेल देखें */ }
@Override public void onEditClick(Contact contact) { showEditDialog(contact); }
@Override public void onDeleteClick(Contact contact) {
viewModel.delete(contact);
}
});
}
private void showAddDialog() { /* डायलॉग दिखाएं, viewModel.insert() कॉल करें */ }
private void showEditDialog(Contact contact) { /* डायलॉग दिखाएं, viewModel.update() कॉल करें */ }
}
लीगेसी SQLiteOpenHelper दृष्टिकोण (संदर्भ के लिए)
अगर Room उपयोग नहीं कर सकते:
public class SqliteDatabase extends SQLiteOpenHelper {
// ... onCreate, onUpgrade में टेबल बनाएं
// listContacts(), addContacts(), updateContacts(), deleteContact() मेथड्स
// Cursor से ArrayList<Contact> में कन्वर्ट करें
// एडाप्टर में Filterable इम्प्लीमेंट करें क्लाइंट-साइड सर्च के लिए
}
लेआउट फाइल्स
res/layout/activity_main.xml - RecyclerView + FAB
res/layout/contact_list_layout.xml - CardView में नाम, नंबर, एडिट/डिलीट आइकन्स
res/layout/add_contacts.xml - डायलॉग के लिए दो EditText
मैनिफेस्ट
स्टैंडर्ड कॉन्फ़िगरेशन।
Room vs SQLiteOpenHelper
| विशेषता | Room | SQLiteOpenHelper |
|---|---|---|
| कंपाइल-टाइम SQL चेक | हां | नहीं |
| LiveData/RxJava सपोर्ट | बिल्ट-इन | मैन्युअल |
| माइग्रेशन | आसान | मैन्युअल |
| टाइप सेफ्टी | हां | नहीं |
| बॉयलरप्लेट | कम | अधिक |
बेस्ट प्रैक्टिसेज
- मुख्य थ्रेड पर DB ऑपरेशन्स न करें - AsyncTask, Coroutines, या Executors उपयोग करें
- LiveData/Flow के साथ ऑब्जर्वर पैटर्न उपयोग करें ऑटो-UI अपडेट के लिए
- DiffUtil/ListAdapter उपयोग करें एनिमेटेड अपडेट्स के लिए
- पेजिनेशन के लिए PagingSource उपयोग करें बड़े डेटासेट के लिए
- डेटाबेस इंस्टेंस सिंगलटन रखें