चूँकि आपका प्रश्न " RecyclerView
डेटाबेस के साथ कैसे उपयोग किया जाए " कहता है और आप विशिष्ट नहीं हैं कि आप SQLite चाहते हैं या इसके साथ कुछ और RecyclerView
, मैं आपको एक समाधान दूंगा जो अत्यधिक इष्टतम है। मैं Realm डेटाबेस के रूप में उपयोग कर रहा हूँ और आपको अपने अंदर के सभी डेटा को प्रदर्शित करने देता हूँ RecyclerView
। इसमें अतुल्यकालिक क्वेरी समर्थन के साथ-साथ उपयोग किए बिना Loaders
या है AsyncTask
।
दायरे क्यों?
चरण 1
दायरे के लिए श्रेणी निर्भरता जोड़ें, नवीनतम संस्करण के लिए निर्भरता यहां पाई गई है
चरण 2
उदाहरण के लिए, अपना मॉडल वर्ग बनाएं, जो कुछ सरल कहे, जैसे Data
कि 2 फ़ील्ड, RecyclerView
पंक्ति के अंदर प्रदर्शित होने के लिए एक स्ट्रिंग और एक टाइमस्टैम्प जिसका उपयोग RecyclerView
आइटम के रूप में किया जाएगा जो चेतन वस्तुओं की अनुमति देता है । ध्यान दें कि मैं RealmObject
नीचे का विस्तार करता हूं , जिसके कारण आपकी Data
कक्षा एक तालिका के रूप में संग्रहीत की जाएगी और आपके सभी गुण उस तालिका के कॉलम के रूप में संग्रहीत किए जाएंगे Data
। मैंने अपने मामले में डेटा टेक्स्ट को प्राथमिक कुंजी के रूप में चिह्नित किया है क्योंकि मैं नहीं चाहता कि एक स्ट्रिंग को एक से अधिक बार जोड़ा जाए। लेकिन अगर आप डुप्लिकेट होना पसंद करते हैं, तो टाइमस्टैम्प को @PrimaryKey के रूप में बनाएं। आपके पास एक प्राथमिक कुंजी के बिना एक तालिका हो सकती है लेकिन यह समस्या पैदा करेगा यदि आप इसे बनाने के बाद पंक्ति को अपडेट करने का प्रयास करते हैं। इस उत्तर को लिखने के समय एक प्राथमिक प्राथमिक कुंजी Realm द्वारा समर्थित नहीं है।
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class Data extends RealmObject {
@PrimaryKey
private String data;
//The time when this item was added to the database
private long timestamp;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}
चरण 3
कैसे एक पंक्ति के अंदर दिखाई देना चाहिए के लिए अपना लेआउट बनाएँ RecyclerView
। हमारे अंदर एक एकल पंक्ति आइटम के लिए लेआउट Adapter
इस प्रकार है
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@android:color/white"
android:padding="16dp"
android:text="Data"
android:visibility="visible" />
</FrameLayout>
ध्यान दें कि मैं एक FrameLayout
जड़ है, भले ही मेरे TextView
अंदर है। मेरी योजना इस लेआउट में और आइटम जोड़ने की है और इसलिए इसे अभी के लिए लचीला बना दिया है :)
जिज्ञासु लोगों के लिए, यह एक एकल आइटम वर्तमान में कैसा दिखता है।
चरण 4
अपना RecyclerView.Adapter
कार्यान्वयन बनाएं । इस मामले में, डेटा स्रोत ऑब्जेक्ट एक विशेष ऑब्जेक्ट है जिसे RealmResults
मूल रूप से एक LIVE कहा जाता है ArrayList
, दूसरे शब्दों में, जैसा कि आइटम आपकी तालिका से जोड़े या हटाए जाते हैं, यह RealmResults
ऑब्जेक्ट ऑटो अपडेट करता है।
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import io.realm.Realm;
import io.realm.RealmResults;
import slidenerd.vivz.realmrecycler.R;
import slidenerd.vivz.realmrecycler.model.Data;
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.DataHolder> {
private LayoutInflater mInflater;
private Realm mRealm;
private RealmResults<Data> mResults;
public DataAdapter(Context context, Realm realm, RealmResults<Data> results) {
mRealm = realm;
mInflater = LayoutInflater.from(context);
setResults(results);
}
public Data getItem(int position) {
return mResults.get(position);
}
@Override
public DataHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.row_data, parent, false);
DataHolder dataHolder = new DataHolder(view);
return dataHolder;
}
@Override
public void onBindViewHolder(DataHolder holder, int position) {
Data data = mResults.get(position);
holder.setData(data.getData());
}
public void setResults(RealmResults<Data> results) {
mResults = results;
notifyDataSetChanged();
}
@Override
public long getItemId(int position) {
return mResults.get(position).getTimestamp();
}
@Override
public int getItemCount() {
return mResults.size();
}
public void add(String text) {
//Create a new object that contains the data we want to add
Data data = new Data();
data.setData(text);
//Set the timestamp of creation of this object as the current time
data.setTimestamp(System.currentTimeMillis());
//Start a transaction
mRealm.beginTransaction();
//Copy or update the object if it already exists, update is possible only if your table has a primary key
mRealm.copyToRealmOrUpdate(data);
//Commit the transaction
mRealm.commitTransaction();
//Tell the Adapter to update what it shows.
notifyDataSetChanged();
}
public void remove(int position) {
//Start a transaction
mRealm.beginTransaction();
//Remove the item from the desired position
mResults.remove(position);
//Commit the transaction
mRealm.commitTransaction();
//Tell the Adapter to update what it shows
notifyItemRemoved(position);
}
public static class DataHolder extends RecyclerView.ViewHolder {
TextView area;
public DataHolder(View itemView) {
super(itemView);
area = (TextView) itemView.findViewById(R.id.area);
}
public void setData(String text) {
area.setText(text);
}
}
}
ध्यान दें कि मैं notifyItemRemoved
उस स्थिति के साथ कॉल कर रहा हूं जिस पर निष्कासन हुआ था, लेकिन मैं कॉल नहीं करता हूं notifyItemInserted
या notifyItemRangeChanged
इसलिए यह जानने का कोई सीधा तरीका नहीं है कि डेटाबेस में कौन सा स्थान डाला गया है क्योंकि Realm प्रविष्टियां एक क्रमबद्ध फैशन में संग्रहीत नहीं हैं। RealmResults
वस्तु ऑटो जब भी कोई नया आइटम, जोड़ा जाता है संशोधित या डेटाबेस से निकाल तो हम फोन अद्यतन करता है notifyDataSetChanged
, जबकि जोड़ने और डालने थोक प्रविष्टियों। इस बिंदु पर, आप शायद उन एनिमेशन के बारे में चिंतित हैं जो ट्रिगर नहीं होंगे क्योंकि आप विधियों के notifyDataSetChanged
स्थान पर कॉल कर रहे हैं notifyXXX
। यही कारण है कि मेरे पास getItemId
विधि ऑब्जेक्ट से प्रत्येक पंक्ति के लिए टाइमस्टैम्प वापस करने की विधि है। एनिमेशन केवल 2 चरणों में प्राप्त किया जाता है, कियाnotifyDataSetChanged
यदि आप कॉल करते हैं setHasStableIds(true)
और फिर ओवरराइड करते हैं, तोgetItemId
केवल स्थिति के अलावा कुछ और प्रदान करने के लिए।
चरण 5
RecyclerView
हमारे Activity
या जोड़ने के लिए देता है Fragment
। मेरे मामले में, मैं एक का उपयोग कर रहा हूँ Activity
। लेआउट फ़ाइल युक्त RecyclerView
बहुत तुच्छ है और ऐसा कुछ दिखाई देगा।
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/text_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
मैंने जोड़ा है app:layout_behavior
जब से मेरे RecyclerView
अंदर जाता है CoordinatorLayout
जो मैंने इस जवाब में संक्षिप्तता के लिए पोस्ट नहीं किया है।
चरण 6
RecyclerView
कोड में निर्माण और इसके लिए आवश्यक डेटा की आपूर्ति। बनाएँ और एक दायरे वस्तु अंदर इनिशियलाइज़ करें और onCreate
इसे onDestroy
एक SQLiteOpenHelper
इंस्टेंस को बंद करने की तरह बहुत अंदर बंद करें । आपकी इच्छा के onCreate
अंदर सबसे सरल Activity
इस तरह दिखेगा। initUi
विधि जहां सभी जादू होता है। मैं अंदर दायरे का एक उदाहरण खोलता हूं onCreate
।
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRealm = Realm.getInstance(this);
initUi();
}
private void initUi() {
//Asynchronous query
RealmResults<Data> mResults = mRealm.where(Data.class).findAllSortedAsync("data");
//Tell me when the results are loaded so that I can tell my Adapter to update what it shows
mResults.addChangeListener(new RealmChangeListener() {
@Override
public void onChange() {
mAdapter.notifyDataSetChanged();
Toast.makeText(ActivityMain.this, "onChange triggered", Toast.LENGTH_SHORT).show();
}
});
mRecycler = (RecyclerView) findViewById(R.id.recycler);
mRecycler.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new DataAdapter(this, mRealm, mResults);
//Set the Adapter to use timestamp as the item id for each row from our database
mAdapter.setHasStableIds(true);
mRecycler.setAdapter(mAdapter);
}
ध्यान दें कि पहले चरण में, मैं दायरे को सभी वस्तुओं को Data
उनके चर नाम से क्रमबद्ध कक्षा से डेटा देने के लिए कहता हूं, जिन्हें एसिंक्रोनस तरीके से डेटा कहा जाता है। यह मुझे RealmResults
मुख्य थ्रेड पर 0 आइटम के साथ एक ऑब्जेक्ट देता है जिसे मैं सेट कर रहा हूं Adapter
। मुझे RealmChangeListener
सूचित किया जाना चाहिए जब डेटा पृष्ठभूमि थ्रेड से लोड करना समाप्त कर देता है जहां मैं notifyDataSetChanged
अपने साथ कॉल करता हूं Adapter
। मैंने इसे लागू करने, हटाए या संशोधित किए गए आइटम का ट्रैक रखने के setHasStableIds
लिए भी सच RecyclerView.Adapter
कहा है। onDestroy
मेरे लिए Activity
बंद क्षेत्र उदाहरण
@Override
protected void onDestroy() {
super.onDestroy();
mRealm.close();
}
इस विधि initUi
के अंदर बुलाया जा सकता है onCreate
अपने की Activity
या onCreateView
या onViewCreated
अपने की Fragment
। निम्नलिखित बातों पर ध्यान दें।
चरण 7
BAM! अंदर अपने डेटाबेस से डेटा नहीं है RecyclerView
asynchonously के बिना लोड CursorLoader
, CursorAdapter
, SQLiteOpenHelper
एनिमेशन के साथ। यहां दिखाई गई GIF छवि थोड़े अंतराल वाली है लेकिन आइटम जोड़ते या हटाते समय एनिमेशन हो रहे हैं।