Loader در اندروید

API Loader در Android 3.0 (سطح API 11) معرفی شده است و به شما امکان می دهد داده ها را از یک ارائه دهنده محتوا یا سایر منابعa داده برای نمایش در فعالیت یا قطعه بارگذاری کنید. اگر شما نمی دانید که چرا به API Loader نیاز دارید و چرا از آن استفاده می کنید، ابتدا به موارد زیر می پردازیم:

1 - اگر شما داده ها را مستقیما در اکتیویتی یا فرگمنت بیاورید، به علت کارایی پایین و اهسته بودن فعالیت ها ممکن است برای کاربر خوب نباشد یا کاربر از کار کردن با برنامه رنج بکشد.

 

2 - اگر داده ها را از یک thread دیگر ببرید، شاید با AsyncTask، شما مسئولیت manage کردن UI و thread را از طریق اکتیویتی ها و فرگمنت ها را بر عهده دارید.

Loader ها این مشکلات را حل می کنند و شامل مزایای دیگر می شوند. مثلا:

1 - Loader ها در موضوعات مختلف مانند عدم پاسخگویی اجرا می شوند.

2 - Loader ها با ارائه روش های فراخوانی هنگام وقوع رویدادها، مدیریت برنامه را را ساده می کنند.

3 - Loader ها نتایج و تغییرات پیکربندی را برای جلوگیری از نمایشهای تکراری حفظ کرده و ذخیره می کنند.

4 - Loader ها می توانند یک ناظر را برای نظارت بر تغییرات در منبع داده پایه اجرا کنند. به عنوان مثال، CursorLoader به طور خودکار یک ContentObserver را ثبت می کند تا وقتی که داده ها تغییر می کند، مجدد بارگیری شود.

Loader API

کلاس ها و رابط های چندگانه وجود دارد که ممکن است هنگام استفاده از Loader ها در یک برنامه شوند. آنها در این جدول خلاصه شده اند:

توضیحات Class/Interface

یک کلاس انتزاعی مرتبط با یک Activity یا Fragment برای مدیریت یک یا چند مورد Loader. تنها یک LoaderManager در هر اکتیویتی یا فرگمنت وجود دارد، اما LoaderManager میتواند چندین مورد را اداره کند.

برای دریافت LoaderManager، call () getLoaderManager از داخل اکتیویتی یا فرگمنت صدا بزنید.

برای شروع بارگیری داده ها از Loader ، یا ()initLoader یا ()restartLoader صدا بزنید. سیستم به طور خودکار تعیین می کند که آیا یک Loader با همان عدد صحیح موجود در حال حاضر وجود دارد و یا یک Loader جدید ایجاد می کند یا یک Loader موجود را مجددا استفاده می کند.

LoaderManager

این رابط شامل روش های فراخوانی است که هنگام رویداد Loader رخ می دهد. رابط کاربری سه روش callback را تعریف می کند:

1 – (onCreateLoader(int, Bundle - زمانی که سیستم نیاز به یک Loader جدید داشته باشد استفاده می شود. کد شما باید یک شی Loader ایجاد کرده و آن را به سیستم بازگرداند.

2 – (onLoadFinished(Loader<D>, D - هنگامی که یک Loader اطلاعات بارگیری را به پایان رسانده است، این متد صدا زده می شود. به طور معمول، کد شما باید داده ها را به کاربر نمایش دهد.

3 – (<onLoaderReset(Loader<D - زمانی که (call destroyLoader (int را فراخوانی می کنید یا زمانی که فعالیت یا فعالیت از بین می رود ، صدا زده می شود، بنابراین داده های آن در دسترس نیستند.

این رابط معمولا توسط اجزای موجود در اکتیویتی یا فرگمنت شما اجرا می شود و هنگامی که شما ()initLoader یا ()restartLoader صدا می زنید ثبت می شود.

LoaderManager.LoaderCallbacks

Loader ها بارگیری داده ها را انجام می دهند. این کلاس انتزاعی است و به عنوان کلاس پایه برای همه Loader ها عمل می کند.

شما می توانید به طور مستقیم از Subclass Loader یا از یک زیر کلاس ساخته شده شبیه زیر برای ساده سازی استفاده کنید:

1 – AsyncTaskLoader - یک Loader انتزاعی است که AsyncTask را برای انجام عملیات لود در یک thread جداگانه فراهم می کند.

2 – CursorLoader - یک زیرمجموعه از AsyncTaskLoader برای بارگیری داده ها از یک ContentProvider به صورت یکپارچه را فراهم می کند.

Loader

استفاده از Loaders در یک برنامه

این بخش نحوه استفاده از Loaders در یک برنامه Android را توضیح می دهد. برنامه ای که با استفاده از Loaders ها شامل موارد زیر است:

1 - یک اکتیویتی یا فرگمنت

2 - یک نمونه از LoaderManager.

3 - CursorLoader برای بارگیری داده هایی که توسط ContentProvider پشتیبانی می شود. به علاوه، شما می توانید زیر کلاس خود Loader یا AsyncTaskLoader را برای بارگیری داده ها از برخی منابع دیگر اجرا کنید.

4 - پیاده سازی برای LoaderManager.LoaderCallbacks. این جایی است که شما Loader جدیدی را ایجاد می کنید و منابع خود را که در Loader های موجود وجود داری مدیریت می کنید.

5 - راهی برای نمایش داده های Loader مانند SimpleCursorAdapter.

6 - منبع داده، مانند ContentProvider، هنگام استفاده از CursorLoader.

شروع Loader

LoaderManager یک یا چند مورد Loader را در یک اکتیویتی یا Fragment مدیریت می کند. تنها یک LoaderManager در هر اکتیویتی یا فرگمنت وجود دارد.

شما به طور معمول Loader را در متد ()onCreate یا در متد ()onActivityCreated می توانید قرار دهید. شما این کار را به صورت زیر انجام می دهید:

 

 

// Prepare the loader.  Either re-connect with an existing one,
// or start a new one.
getLoaderManager
().initLoader(0, null, this);

متد () initLoader پارامترهای زیر را می گیرد:

1 - یک شناسه منحصر به فرد که Loader را شناسایی می کند. در این مثال، شناسه 0 است.

2 - استدلال های اختیاری برای ارائه به Loader در هنگام ایجاد شدن آن (در این مثال خالی می باشد).

3 - اجرای LoaderManager.LoaderCallbacks که LoaderManager را برای گزارش وقایع بارگذاری می کند. در این مثال، کلاس محلی لایه رابط LoaderManager.LoaderCallbacks را اجرا می کند.

متد () initLoader تضمین می کند که Loader اولیه initialized شده و فعال است. و شمال موارد زیر است:

1 - اگر Loader مشخص شده توسط شناسه در حال حاضر وجود داشته باشد، Loader جدید ایجاد شده مجددا استفاده می شود.

2 - اگر Loader مشخص شده توسط ID وجود ندارد، () initLoader روش LoaderManager.LoaderCallbacks را بر روی () onCreateLoader راه اندازی می کند. این جایی است که شما کد را برای نمونه سازی و بازگرداندن یک Loader جدید پیاده سازی می کنید.

در هر دو مورد، اجرای LoaderManager.LoaderCallbacks با Loader همراه است و زمانی که وضعیت Loader تغییر داده می شود، صدا زده می شود.

توجه داشته باشید که روش () initLoader Loader, ایجاد شده را باز می کند، اما نیاز نیست شما آنرا مدیریت کنید. LoaderManager به طور خودکار Loader را مدیریت می کند.

LoaderManager در صورت لزوم بارگیری را متوقف می کند و وضعیت Loader و محتوای مرتبط آن را حفظ می کند.

این بدان معنی است، شما به ندرت با Loader به طور مستقیم ارتباط برقرار می کنید . شما اغلب از روش LoaderManager.LoaderCallbacks برای مداخله در فرآیند بارگیری هنگام وقوع رویداد خاص استفاده می کنید.

بارگذاری مجدد Loader

هنگامی که شما از () initLoader استفاده می کنید، همانطور که در بالا گفته شده است، از یک Loader موجود با شناسه مشخص شده استفاده می شود. اگر وجود نداشته باشد، آن را ایجاد می کند. اما گاهی اوقات می خواهید یک Loader را بارگذاری مجدد کنید و داده های قبلی را از بین ببرید.

برای از بین بردن داده های قدیمی خود، از () restartLoader استفاده می کنید.

به عنوان مثال، این پیاده سازی SearchView.OnQueryTextListener باعث بارگذاری مجدد هنگامی که پرس و جو کاربر تغییر می کند می شود. Loader باید دوباره راه اندازی شود تا بتواند از فیلتر جستجوی اصلاح شده برای انجام یک پرس و جو جدید استفاده کند:

public boolean onQueryTextChanged(String newText) {
   
// Called when the action bar search text has changed.  Update
   
// the search filter, and restart the loader to do a new query
   
// with this filter.
    mCurFilter
= !TextUtils.isEmpty(newText) ? newText : null;
    getLoaderManager
().restartLoader(0, null, this);
   
return true;
}

استفاده از Callback LoaderManager

LoaderManager.LoaderCallbacks یک رابط فراخوانی است که به کاربر اجازه می دهد با LoaderManager ارتباط برقرار کند.

از Loader ها، به ویژه CursorLoader، انتظار می رود که اطلاعات خود را پس از متوقف نگه دارند.

این فرایند اجازه می دهد تا برنامه ها اطلاعات خود را در مورد در متدهای () onStop و () onStart نگهداری کنند، به طوری که هنگامی که کاربران به یک برنامه باز می گردند، لازم نیست منتظر بارگذاری اطلاعات باشند.

LoaderManager.LoaderCallbacks شامل این روشها است:

1 - () onCreateLoader

2 - () onLoadFinished

3 - () onLoaderReset

onCreateLoader

هنگام تلاش برای دسترسی به Loader (به عنوان مثال، از طریق () initLoader)، آن را بررسی می کند که آیا Loader مشخص شده توسط شناسه وجود دارد. اگر این کار را نکند، روش () LoaderManager.LoaderCallbacks onCreateLoader را اجرا می کند. این جایی است که شما یک Loader جدید ایجاد می کنید. به طور معمول این CursorLoader خواهد بود، اما شما می توانید زیر کلاس خود Loader خود را اجرا کنید.

در این مثال، روش () callback onCreateLoader یک CursorLoader ایجاد می کند. شما باید CursorLoader را با استفاده از روش سازنده خود بسازید، که نیاز به مجموعه کامل اطلاعات مورد نیاز برای انجام پرس و جو به ContentProvider دارد. به طور خاص، آن موارد را نیاز دارد:

1 - uri

2 - projection

3 – selection

4 – selectionArgs

5 – sortOrder

برای مثال :

// If non-null, this is the current filter the user has provided.
String mCurFilter;
...
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
   
// This is called when a new Loader needs to be created.  This
   
// sample only has one Loader, so we don't care about the ID.
   
// First, pick the base URI to use depending on whether we are
   
// currently filtering.
   
Uri baseUri;
   
if (mCurFilter != null) {
        baseUri
= Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                 
Uri.encode(mCurFilter));
   
} else {
        baseUri
= Contacts.CONTENT_URI;
   
}

   
// Now create and return a CursorLoader that will take care of
   
// creating a Cursor for the data being displayed.
   
String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
           
+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
           
+ Contacts.DISPLAY_NAME + " != '' ))";
   
return new CursorLoader(getActivity(), baseUri,
            CONTACTS_SUMMARY_PROJECTION
, select, null,
           
Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}

onLoadFinished

این متد زمانی خوانده می شود که Loader قبلا ساخته شده و load خود را به پایان رسانده است. این متد قبل از انتشار آخرین اطلاعاتی که برای این Loader عرضه شده، تضمین شده است.

Loader داده ها را پس از اطلاع از اینکه برنامه دیگر از آن استفاده نمی کند، منتشر می کند. برای مثال، اگر داده هایی که به آن اشاره می شود از CursorLoader باشد،شما نباید متد () close را صدا بزنید. اگر مکان نما در CursorAdapter قرار می گیرد، شما باید از روش () swapCursor استفاده کنید تا Cursor قدیمی بسته شود. مثلا:

// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
...

public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
   
// Swap the new cursor in.  (The framework will take care of closing the
   
// old cursor once we return.)
    mAdapter
.swapCursor(data);

onLoaderReset

این روش هنگامی که یک Loader قبلا ایجاد شده و reset می شود، صدا زده می شود، بنابراین داده های آن در دسترس نیستند. این فراخوانی به شما امکان می دهد زمانی که داده ها در اختیار شما قرار می گیرند پیدا کنید تا بتوانید مرجع خود را به آن حذف کنید.

این پیاده سازی () swapCursor را با مقدار null تعریف می کند:

// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
...

public void onLoaderReset(Loader<Cursor> loader) {
   
// This is called when the last Cursor provided to onLoadFinished()
   
// above is about to be closed.  We need to make sure we are no
   
// longer using it.
    mAdapter
.swapCursor(null);
}

مثال:

به عنوان مثال، در اینجا Fragment پیاده سازی شده است که برای نمایش ListView حاوی نتایج پرس و جو برای کاربران است. برای مدیریت پرس و جو در ارائه دهنده از CursorLoader استفاده می کند.

در برنامه کاربردی برای دسترسی به مخاطبین کاربر باید مجوز ان تعریف گردد (permission READ_CONTACTS)

public static class CursorLoaderListFragment extends ListFragment
       
implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {

   
// This is the Adapter being used to display the list's data.
   
SimpleCursorAdapter mAdapter;

   
// If non-null, this is the current filter the user has provided.
   
String mCurFilter;

   
@Override public void onActivityCreated(Bundle savedInstanceState) {
       
super.onActivityCreated(savedInstanceState);

       
// Give some text to display if there is no data.  In a real
       
// application this would come from a resource.
        setEmptyText
("No phone numbers");

       
// We have a menu item to show in action bar.
        setHasOptionsMenu
(true);

       
// Create an empty adapter we will use to display the loaded data.
        mAdapter
= new SimpleCursorAdapter(getActivity(),
                android
.R.layout.simple_list_item_2, null,
               
new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
               
new int[] { android.R.id.text1, android.R.id.text2 }, 0);
        setListAdapter
(mAdapter);

       
// Prepare the loader.  Either re-connect with an existing one,
       
// or start a new one.
        getLoaderManager
().initLoader(0, null, this);
   
}

   
@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
       
// Place an action bar item for searching.
       
MenuItem item = menu.add("Search");
        item
.setIcon(android.R.drawable.ic_menu_search);
        item
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
       
SearchView sv = new SearchView(getActivity());
        sv
.setOnQueryTextListener(this);
        item
.setActionView(sv);
   
}

   
public boolean onQueryTextChange(String newText) {
       
// Called when the action bar search text has changed.  Update
       
// the search filter, and restart the loader to do a new query
       
// with this filter.
        mCurFilter
= !TextUtils.isEmpty(newText) ? newText : null;
        getLoaderManager
().restartLoader(0, null, this);
       
return true;
   
}

   
@Override public boolean onQueryTextSubmit(String query) {
       
// Don't care about this.
       
return true;
   
}

   
@Override public void onListItemClick(ListView l, View v, int position, long id) {
       
// Insert desired behavior here.
       
Log.i("FragmentComplexList", "Item clicked: " + id);
   
}

   
// These are the Contacts rows that we will retrieve.
   
static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
       
Contacts._ID,
       
Contacts.DISPLAY_NAME,
       
Contacts.CONTACT_STATUS,
       
Contacts.CONTACT_PRESENCE,
       
Contacts.PHOTO_ID,
       
Contacts.LOOKUP_KEY,
   
};
   
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
       
// This is called when a new Loader needs to be created.  This
       
// sample only has one Loader, so we don't care about the ID.
       
// First, pick the base URI to use depending on whether we are
       
// currently filtering.
       
Uri baseUri;
       
if (mCurFilter != null) {
            baseUri
= Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                   
Uri.encode(mCurFilter));
       
} else {
            baseUri
= Contacts.CONTENT_URI;
       
}

       
// Now create and return a CursorLoader that will take care of
       
// creating a Cursor for the data being displayed.
       
String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
               
+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
               
+ Contacts.DISPLAY_NAME + " != '' ))";
       
return new CursorLoader(getActivity(), baseUri,
                CONTACTS_SUMMARY_PROJECTION
, select, null,
               
Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
   
}

   
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
       
// Swap the new cursor in.  (The framework will take care of closing the
       
// old cursor once we return.)
        mAdapter
.swapCursor(data);
   
}

   
public void onLoaderReset(Loader<Cursor> loader) {
       
// This is called when the last Cursor provided to onLoadFinished()
       
// above is about to be closed.  We need to make sure we are no
       
// longer using it.
        mAdapter
.swapCursor(null);
   
}
}

منبع : https://developer.android.com/guide/components/loaders.html#summary

نوشتن دیدگاه


تصویر امنیتی
تصویر امنیتی جدید

تماس با آموزشگاه

جوملا فارسی