Sorunuz " RecyclerView
Bir veritabanı ile nasıl kullanılır" dediğinden ve SQLite veya herhangi başka bir şey isteyip istemediğiniz konusunda net olmadığınız için RecyclerView
, size oldukça uygun bir çözüm sunacağım. Realm'i veritabanı olarak kullanacağım ve içindeki tüm verileri görüntülemenize izin vereceğim RecyclerView
. Loaders
Veya kullanmadan asenkron sorgu desteğine sahiptir AsyncTask
.
Neden realm?
Aşama 1
Realm için gradle bağımlılığını ekleyin, en son sürüm için bağımlılık burada bulunur
Adım 2
Model sınıfınızı oluşturun, örneğin, Data
2 alan, RecyclerView
satırın içinde görüntülenecek bir dize ve RecyclerView
öğelerin canlandırılmasına izin vermek için itemId olarak kullanılacak bir zaman damgası gibi basit bir şey söyleyelim . RealmObject
Aşağıda, Data
sınıfınızın bir tablo olarak depolanacağı ve tüm özelliklerinizin bu tablonun sütunları olarak depolanacağı için genişlettiğime dikkat edin Data
. Bir dizenin birden çok kez eklenmesini istemediğim için, benim durumumda veri metnini birincil anahtar olarak işaretledim. Ancak yinelemeleri tercih ediyorsanız, zaman damgasını @PrimaryKey olarak yapın. Birincil anahtarsız bir tablonuz olabilir, ancak oluşturduktan sonra satırı güncellemeyi denerseniz sorunlara neden olur. Bu cevabı yazarken bir bileşik birincil anahtar Realm tarafından desteklenmemektedir.
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;
}
}
Aşama 3
İçinde tek bir satırın nasıl görünmesi gerektiğine ilişkin mizanpajınızı oluşturun RecyclerView
. İçimizdeki tek bir satır öğesinin düzeni Adapter
aşağıdaki gibidir
<?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>
Bir FrameLayout
içim olmasına rağmen bir kök olarak tuttuğuma dikkat edin TextView
. Bu düzene daha fazla öğe eklemeyi planlıyorum ve bu nedenle şimdilik esnek hale getirdim :)
Dışarıdaki meraklı insanlar için, şu anda tek bir öğe böyle görünüyor.
4. adım
Uygulamanızı oluşturun RecyclerView.Adapter
. Bu durumda, veri kaynağı nesnesi, RealmResults
temelde LIVE olarak adlandırılan özel bir nesnedir ArrayList
, başka bir deyişle, öğeler tablonuza eklendiğinde veya kaldırıldığında bu RealmResults
nesne otomatik olarak güncellenir.
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
Kaldırma işleminin gerçekleştiği konumla aradığıma dikkat edin, ancak ARAMIYORUM notifyItemInserted
veya notifyItemRangeChanged
Realm girişleri sıralı bir şekilde saklanmadığından öğenin veritabanına hangi konuma eklendiğini bilmenin doğrudan bir yolu olmadığından. RealmResults
Nesne oto yeni madde eklendi dediğimiz böylece veritabanından değiştirilmiş veya çıkarıldığında günceller notifyDataSetChanged
ekleme ve eklerken toplu girişlerini. Bu noktada, muhtemelen yöntemlerin notifyDataSetChanged
yerine çağırdığınız için tetiklenmeyecek olan animasyonlar hakkında endişelisiniz notifyXXX
. İşte tam da bu yüzden getItemId
metodun sonuç nesnesinden her satır için zaman damgasını döndürmesine sahibim . animasyon 2 adımda elde edilirnotifyDataSetChanged
ararsanız setHasStableIds(true)
ve ardından geçersiz kılarsanızgetItemId
sadece konumdan başka bir şey sağlamak için.
Adım 5
Veya ' RecyclerView
ye ekleyelim . Benim durumumda, bir . İçeren düzen dosyası oldukça önemsizdir ve buna benzer bir şeye benzeyecektir.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" />
Kısaca bu cevaba göndermediğim bir içeri girdiğimden app:layout_behavior
beri bir ekledim .RecyclerView
CoordinatorLayout
6. Adım
Giriş RecyclerView
kodunu oluşturun ve ihtiyaç duyduğu verileri sağlayın. İçinde bir Realm nesnesi oluşturun ve başlatın onCreate
ve onDestroy
hemen hemen bir SQLiteOpenHelper
örneği kapatır gibi içeride kapatın . En basit sizin de onCreate
içine Activity
aşağıdaki gibi görünecektir. initUi
Tüm Sihirin yöntemidir. İçinde bir Realm örneği açıyorum 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);
}
İlk adımda, Realm'i Data
veri denen değişken adlarına göre eşzamansız bir şekilde sıralanmış sınıftaki tüm nesneleri bana vermesi için sorguladığıma dikkat edin . Bu bana RealmResults
ana iş parçacığındaki 0 öğeli bir nesne veriyor Adapter
. Bir ilave RealmChangeListener
veri ararım arkaplan iplikle yüklenmeden haberdar olmak için notifyDataSetChanged
sahip oldugumla Adapter
. Ayrıca setHasStableIds
, RecyclerView.Adapter
uygulamanın eklenen, kaldırılan veya değiştirilen öğeleri izlemesine izin vermek için true çağrısı yaptım . onDestroy
Benim için Activity
kapanmadan Diyar örneği
@Override
protected void onDestroy() {
super.onDestroy();
mRealm.close();
}
Bu yöntem initUi
içine çağrılabilir onCreate
senin içinde Activity
ya onCreateView
ya onViewCreated
, aramalarınızdan Fragment
. Aşağıdaki şeylere dikkat edin.
7. Adım
BAM! Senin içine veritabanından veri yok RecyclerView
asynchonously olmadan yüklenen CursorLoader
, CursorAdapter
, SQLiteOpenHelper
animasyonlarla. Burada gösterilen GIF resmi biraz gecikmeli, ancak öğeler eklediğinizde veya kaldırdığınızda animasyonlar oluyor.