Soru CursorLoaders'ın avantajları nelerdir?


kullanırım Cursors Uygulamamda kapsamlı bir şekilde yükleme yapmak ve zaman zaman bir veritabanına bilgi yüklemek. Honeycomb ve Uyumluluk Paketinin yeni olduğunu gördüm Loader Verileri "iyi" bir şekilde yüklemeye yardımcı olmak için tasarlanmış sınıflar.

Esasen, bu yeni sınıflar (özellikle CursorLoader) önceki veri yönetimi yöntemlerinden önemli ölçüde daha iyi? Bir yararı nedir CursorLoader üzerinde yönetilen Cursors Örneğin?

Ve ben bir ContentProvider Açıkça görüldüğü verilerle uğraşmak Uris ama bu nasıl ağlıyor initLoader() yöntem? Her birini ayarlamalıyım Fragments Yükleyicileri ayrı ayrı kullanmak için? Her bir yükleyici için kimliğin ne kadar benzersiz olması gerekir? Uygulamamın kapsamı mı yoksa sadece bir parça mı? Sadece geçmenin basit bir yolu var mı Uri Verilerimi sorgulamak için bir CursorLoader'a mı?

Şu anda görebildiğim tek şey Loaders'ın verilerimi benim uygulamamda kullanmak için gereksiz bir adım atmasıdır, bu yüzden birisi bunları bana daha iyi anlatabilir mi?


25
2017-08-24 22:09


Menşei




Cevaplar:


Kullanmanın iki temel yararı vardır. CursorLoader uygulamanızda Activity.managedQuery():

  1. Sorgu sizin için bir arka plan iş parçacığı üzerinde ele alınır. AsyncTaskLoader) Çok büyük veri sorguları UI'yi engellemez. Bu, bir belgeyi kullanırken dokümanlar kendiniz için önerdiğiniz bir şeydir Cursorama şimdi başlığın altında yapıldı.
  2. CursorLoader otomatik güncelleniyor. İlk sorguyu gerçekleştirmenin yanı sıra, CursorLoader kaydeder bir ContentObserver İstediğiniz veri kümesine forceLoad() veri seti değiştiğinde kendi başına. Bu, görünümü güncelleştirmek için verileriniz her an değiştikçe geri aramaları geri almanıza neden olur.

Her Loader örnek ayrıca tekil aracılığıyla ele alınır LoaderManagerBu nedenle, imleci doğrudan yönetmek zorunda değilsiniz, ve şimdi bağlantı, bir tekin ötesinde bile devam edebilir Activity. LoaderManager.initLoader() ve LoaderManager.restartLoader() var olanla yeniden bağlantı kurmanıza izin ver Loader Sorgunuz için zaten ayarlanmış ve bazı durumlarda mevcutsa en son verileri anında al.

Sizin Activity veya Fragment büyük olasılıkla şimdi uygulayacak LoaderManager.Callback arayüz. çağrı initLoader() sonuçlanacak onCreateLoader() sorguyu ve yeni oluşturulacak yöntem CursorLoader örneğin, gerekirse. onLoadFinished() Her yeni veri mevcut olduğunda yöntem ateşlenecek ve en yeni Cursor görünümüne eklemek ya da başka bir şekilde yinelemek için.

Buna ek olarak, tüm bu uydurma üzerinde birlikte iyi bir örnek var. LoaderManager sınıf dokümantasyon sayfası: http://developer.android.com/reference/android/app/LoaderManager.html

Umarım yardımcı olur!


44
2017-08-24 22:48



Cool, bu açıklama için teşekkürler! Sadece bir kaç soru: initLoader() sorgulamak istediğiniz benzersiz veya her bir veri kümesi anlamına mı geliyor? Ve her biri veritabanımın farklı tablolarını kullanan birden fazla faaliyetim olduğu için, her birini idare eden bir sınıf oluşturabileceğim herhangi bir yol var mı? CursorLoaderçok gibi ContentProvider çoklu işlem yapabilir Cursors ile query? - Alex Curran
Kimlik değeri benzersiz bir şey tanımlar Loader örneğin yönetici ile sorarsanız yine aynı olana erişebilirsiniz LoaderManager zaten oluşturulduktan bir süre sonra. Her biri CursorLoader Temel olarak belirli bir sorguyu yürütmek için yaratılır, bir kimliğin bir veri kümesine eşlendiğini söyleyebilirdiniz. Üzerinde yöntemler olmasına rağmen CursorLoader sorgu parametrelerini de dinamik olarak değiştirmek için, bu durumda olması gerekmez. - Devunwired
LoaderManager gerçekten her birini idare eden tek sınıf Loader Senin için, ama eğer yönetmek için tek bir sınıf oluşturabilirsin LoaderManager.Callback çoklu için Loader örnekler, cevap evet. Tek bir çağrı için birden fazla geri arama eklenebilir Loader Kimlik değeri ve çoklu kimlikleri aynı geri çağrı uygulamasına işaret edebilir. - Devunwired
Cool, bunu denemeliyim, yardımın için teşekkürler! - Alex Curran


Eğer benzer bir durumda kendilerini bulursa, işte yaptığım şey:

  • Uygulayan bir sınıf oluşturuldu LoaderCallbacks ve kolları herşey ihtiyacınız olacak sorgular.
  • Bunu bir Context ve Adapter söz konusu.
  • Kullanacağınız her sorgu için benzersiz kimlikler oluşturun. UriMatcher, aynı olanları da kullanabilir)
  • Sorguları için gereken paketin içine aktaran bir kolaylık yöntemi yapın. LoaderCallbacks
  • Bu oldukça fazla :) Yaptığım şeyi tam olarak göstermek için kodumun bazılarını koydum

Benim .. De GlobalCallbacks sınıf:

public static final String PROJECTION = "projection";
public static final String SELECTION = "select";
public static final String SELECTARGS = "sargs";
public static final String SORT = "sort";

Context mContext;
SimpleCursorAdapter mAdapter;

public GlobalCallbacks(Context context, SimpleCursorAdapter adapter) {
    mContext = context;
    mAdapter = adapter;
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {

    Uri contentUri = AbsProvider.customIntMatch(id);
    if (contentUri != null) {
        return new CursorLoader(mContext, contentUri, args.getStringArray(PROJECTION), args.getString(SELECTION), 
                args.getStringArray(SELECTARGS), args.getString(SORT));
    } else return null;

}

@Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {
    mAdapter.swapCursor(arg1);      
}

@Override
public void onLoaderReset(Loader<Cursor> arg0) {
    mAdapter.swapCursor(null);
}

Ve ne zaman kullanmak istediğimde CursorLoader (Helper.bundleArgs() uygunluk paketleme yöntemidir):

scAdapt = new Adapters.NewIndexedAdapter(mHost, getMenuType(), 
                null, new String[] { "name" }, new int[] { android.R.id.text1 });
        getLoaderManager().initLoader(
                GlobalCallbacks.GROUP,
                Helper.bundleArgs(new String[] { "_id", "name" }),
                new GlobalCallbacks(mHost, scAdapt));
        setListAdapter(scAdapt);

Ve yardımcısı:

public static Bundle bundleArgs(String[] projection, String selection, String[] selectionArgs) {
    Bundle b = new Bundle();
    b.putStringArray(GlobalCallbacks.PROJECTION, projection);
    b.putString(GlobalCallbacks.SELECTION, selection);
    b.putStringArray(GlobalCallbacks.SELECTARGS, selectionArgs);
    return b;
}

Umarım bu başka birine yardımcı olur :)

DÜZENLE

Daha ayrıntılı bir şekilde açıklamak gerekirse:

  • İlk olarak, null olan bir bağdaştırıcı Cursor başlatıldı. Onu bir tedarik etmeyiz Cursor Çünkü GlobalCallbacks adaptöre doğru verecek Cursor içinde onLoadFinished(..)
  • Sonra anlatırız LoaderManager yeni bir başlangıç ​​yapmak istiyoruz CursorLoader. Yeni bir tedarik GlobalCallbacks Örnek (uygulayan Loader.Callbacks) daha sonra imlecin yüklenmesini izleyecektir. Adaptörü de tedarik etmeliyiz, böylece yeni takas edebilir Cursor bir kere bitti. Bir noktada, LoaderManager (OS içinde yerleşik) arayacak onCreateLoader(..) arasında GlobalCallbacks ve eşzamansız olarak veri yükleme
  • Helper.bundleArgs(..) sadece sorgu için argümanlar koyar Bundle (örn. sütun projeksiyonu, sıralama düzeni, WHERE maddesi)
  • Sonra biz Fragment'ler ListAdapter. İmleç hala bu noktada boş olacak, bu yüzden bir yükleme işareti veya boş bir mesaj gösterecektir onLoadFinished() denir

10
2017-09-20 16:27



Hey, hızlı bir sorum var. İlk olarak, bunu sağladığınız için teşekkür etmek istiyorum. Yapmam gerekeni ve nereye bakmam gerektiğini gerçekten anlamama yardımcı oldunuz. Bu yüzden sorum, kolaylık yönteminiz hakkında. Nasıl çalıştığından emin değilim. Zamanınız varsa, kodun sonunu açıklar mısınız lütfen. Tekrar teşekkürler! - Andy
Güncellenmiş cevabımı görün, daha fazla bir şeye ihtiyacınız varsa bildirin - Alex Curran
Ohhhhhh, anladım. Sonunda anladım! Ben anlıyorum. Ama bu nasıl? Bundlegönderildi onCreateLoader? Gördüğüm öğretici, onCreateLoader'da bunu hiç kullanmıyor. Kullanmam gerekmediği varsayımı altındaydım. - Andy
Sorgunuzu dinamik olarak değiştirmek istiyorsanız Bundle'ın daha kullanışlı olduğunu düşünüyorum. Örneğin, bir öğelerin bir listesi olsaydı ve hepsini istediyseniz, Bundle'a ihtiyacınız olmazdı, ancak daha sonra iki farklı CursorLoader'a ihtiyacınız olmayacağından, bunları filtrelemek istiyorsanız kullanışlı olabilirdi (siz d Sadece Bundle'da bir filtre sorgusu olup olmadığını kontrol edin). - Alex Curran
Ahh, zamanını gerçekten takdir ediyorum. Bir şey daha var, bu kolaylık yöntemini tam olarak nasıl aldığınızı ve hangi sınıfta olduğunu yeniden yazabilir misiniz? Ama bunun yanı sıra, her şey hazır. Bana çok yardımcı oldun. Sana yeterince teşekkür edemem! - Andy