سورس اندروید اسلایدر پیشرفته با کاتلین
سورس اندروید اسلایدر پیشرفته با کاتلین
۱۳۹۷-۱۱-۱۰
کتابخانه timber برای گرفتن لاگ بهتر در اندروید
کتابخانه Timber برای گرفتن لاگ بهتر در اندروید
۱۳۹۷-۱۱-۱۷

کتابخانه RxJava را کاربردی بیاموزیم

آموزش RxJava با مثال های کاربردی

آموزش RxJava با مثال های کاربردی

آموزش RxJava با مثال های کاربردی ، ما در کدنویسی پلتفرم اندروید کتابخانه های بسیاری داریم که استفاده از آنها از واجبات است ! یکی از پرکاربردترین آنها کتابخانه RxJava ست که در این پست تجاری اپ بیشتر به آن میپردازیم پس با ما همراه باشید 😉

آموزش کتابخانه RxJava با مثال های کاربردی

در دنیای Rxjava ما به تعداد ستاره های آسمان 😀 اپراتور بدردبخور داریم که به معنای واقعی جادو میکنند !!
البته ما یک آموزش پروژه محور کامل الگوی طراحی MVVM با Rxjava در تجاری اپ داریم که میتونید مطالعه کنید 🙂
در این پست ما تعدادی مثال کاملا کاربردی از استفاده هایی که میشه از کتابخانه RxJava در اندروی کرد آوردیم که امید است برای شما نیز بکار آید 🙂

نکته قابل توجه این ست که ما از زبان کاتلین kotlin استفاده میکنیم

استفاده از کتابخانه RxJava برای حالت TextWatcher

مشخصا همه میدونیم که زمانی از TextWatcher استفاده میکنیم که میخوایم اطلاعات ورودی یک EditText رو در ۳ حالت به دست بیاریم !

  • قبل از وارد کردن داده در ادیت تکست
  • هنگام وارد کردن داده در ادیت تکست
  • پس از وارد کردن داده در ادیت تکست

در حالت عادی ما بدین صورت TextWatcher خواهیم داشت

et1.addTextChangedListener(new TextWatcher() {
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

        // TODO Auto-generated method stub
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        // TODO Auto-generated method stub
    }

    @Override
    public void afterTextChanged(Editable s) {

        // TODO Auto-generated method stub
    }
});

اما با استفاده از کتابخانه RxJava میتونیم کد رو بصورت زیر بنویسیم و کدهای Boilerplate رو حذف کنیم

RxTextView.afterTextChangeEvents(your_edittext_name)
                .filter { t -> t.toString().length > 3 //some filter }
                .subscribe { //do sth if filter has pass }
                
RxTextView.beforeTextChangeEvents(edt_new_pass)
                .filter { t -> t.toString().length > 3 }
                .subscribe { checkLayoutAccept() }


ایجاد یک سری داده بر اساس شرایط خاصی از view ها

در بعضی مواقع ما نیاز داریم تا یک سری عملیات را بروی تعدادی view اعمال کنیم و بر این اساس یک سری داده ایجاد کنیم.
برای مثال فرض کنید یک سری CheckBox داریم که نمایانگر روزهای هفته هستند و براساس اینکه فعال هستند یا غیر فعال یک ارایه از اعداد بسته به روز انتخابی ایجاد کنیم.

در حالت عادی ما یک سری if else… تودرتو خواهیم داشت درحالی که در کتابخانه RxJava ما یک بلاک بصورت زیر خواهیم داشت

var days = ""
        Observable.just(activity.check_sat_day, activity.check_sun_day, activity.check_mon_day, activity.check_tue_day, activity.check_wed_day, activity.check_thu_day, activity.check_fri_day)
                .filter({
                    it.isChecked
                }).flatMap {
                    if (it == activity.check_sat_day)
                        days += "0"
                    if (it == activity.check_sun_day)
                        days += "1"
                    if (it == activity.check_mon_day)
                        days += "2"
                    if (it == activity.check_tue_day)
                        days += "3"
                    if (it == activity.check_wed_day)
                        days += "4"
                    if (it == activity.check_thu_day)
                        days += "5"
                    if (it == activity.check_fri_day)
                        days += "6"

                    return@flatMap Observable.just(days)
                }.subscribe()


انجام عملیاتی برروی view ها براساس یک سری داده

این مثال دقیقا برعکس مثال قبل است بدین صورت که در اینجا ما یک آرایه از اعداد داریم و براساس آنها چک باکس هایی که مشخص کننده روز های هفته است را فعال یا غیر فعال میکنیم

بصورت زیر

val ary: List<String> = days.split("".toRegex())//"12345" -> "1" , "2" , "3"
        Observable.fromIterable(ary)
                .flatMap {
                    if (it == "0")
                        check_sat_day.isChecked = true
                    if (it == "1")
                        check_sun_day.isChecked = true
                    if (it == "2")
                        check_mon_day.isChecked = true
                    if (it == "3")
                        check_tue_day.isChecked = true
                    if (it == "4")
                        check_wed_day.isChecked = true
                    if (it == "5")
                        check_thu_day.isChecked = true
                    if (it == "6")
                        check_fri_day.isChecked = true

                    return@flatMap Observable.just(it)
                }.subscribe()


اعمال debounce برروی مقادیر ورودی

در بعضی مواقع ما لازم داریم که برروی مقادیر ورودی یک ادیت تکست بصورت آنی با هر تغییر عملیاتی انجام دهیم اما نمیخواهیم عملیات با وارد شدن هر دونه کاراکتر اعمال شود.
بلکه برروی تکست ورودی نهایی که مورد نظر کاربر است !
با مثالی واضح تر این مسئله را بیان میکنیم . شما ادیت تکستی که کار search را میخواهد انجام دهد درنظر بگیرید
ما میخواهیم با وارد کردن داده در این ادیت تکست مقادیر خروجی سرچ تغییر کند بصورت آنی
خب طبیعتا باید یک listener برای حالت تغییر ورودی ادیت تکست قرار دهیم برای مثال میتونیم از رویداد onTextChange مربوط به TextWatcher استفاده کنیم اما مشکلی که هست در این روش این ست که با وارد کردن هر کاراکتر عملیات ما انجام خواهد شد حال فرض کنید که این عملیات درخواست یک api سرور است.

خب طبیعتا با وارد شدن هرکاراکتر اگر این api صدا زده شود برنامه ما خیلی رم مصرف میکنه و برای سیستم موبایل بشدت مضر خواهد بوداما با debounce ما مشخص میکنیم که روی حالت TextChange باش اما پس از گذشت مدت زمان کوتاهی (مثلا چند میلی ثانیه) عملیات را نجام بده
این روش خیلی بهینه تر خواهد بود چرا که ما درهنگام تایپ کاربر و با ورود هرکاراکتر سرور را مشغول نمیکنیم بلکه دقیقا پس از تایپ کاربر کل تکست ورودی را میگیریم و api را صدا میزنیم

Observable<String> obs;

        obs = RxTextView.textChanges(activity.getBinding().edtUsername).
                filter(charSequence ->
                {
                        Log.e("filter run  ", charSequence.toString());
                        return charSequence.length() > 3 &amp;&amp; !baseUsername.equals(charSequence);
                })
                .debounce(2000, TimeUnit.MILLISECONDS)
                .map(charSequence -> {
                        Log.e("map run  ", charSequence.toString());
                        return charSequence.toString();
                });
        obs.subscribe(s -> {
                Log.e("obs.subscribe run  ", s);
                if (!s.equals(baseUsername))
                    checkUsername(s);
        });


تغییر حلقه ()for به fromIterable

حلقه ()for یکی از پرکاربرد ترین دستور دربرنامه نویسی ست که با کتابخانه RxJava در اندروید میتونیم اون رو بدین صورت تغییر بدیم و کنترل بیشتری روی اون داشته باشیم بدون کدهای اضافه

این کدی ست که در حالت عادی میزنیم

 for (i in 0 until offList.size) {
            if (offList[i].foodId == 2)
                doSomeFunc(offList[i])
        }


و این حالت کتابخانه RxJava آن است که اپراتور firstElement مشخص میکنه که با گرفتن اولین آیتم موفق از حلقه خارج شو که میتونیم اون رو هم حذف کنیم و حلقه رو برروی تمامی آیتم های لیست اعمال کنیم

Observable.fromIterable(offList)
                .filter{
                    it.foodId == 2
                }.firstElement()
                .subscribe{
                    doSomeFunc(it)
                }

همچنین بدین صورت میتونیم حلقه های تودتو بنویسیم

 Observable.fromIterable(mList)
                .filter{it ->
                    baseFoods.contains(it)
                }
                .map{it ->
                    Observable.fromIterable(baseFoods)
                            .filter{bf->
                                it.foodId == bf.foodId
                            }
                            .firstElement()
                            .subscribe{bf ->
                                doSomeFunc(bf)
                            }
                }.subscribe()


مثالی از زنجیر شرایط login

خب شرایطی که برای حالت ورود برنامه میذاریم معمولا این دوشرط رو دارن که شماره موبایل معتبر باشه و رمزعبور هم بیش از ۴ کاراکتر باشه.
در حالت عادی ما بلاک های if تودرتو رو داریم اما در حالت کتابخانه RxJava ما بلاک زیر رو خواهیم داشت که پله پله مشخص کردیم که باید چیکار کنی

Observable.just(edt_mobile.text.toString())
            .filter {
                if (checkMobile(it))
                    return@filter true
                else {
                    edt_mobile.error = getString(R.string.login01_error)
                    return@filter false
                }
            }.map {
                edt_password.text.toString()
            }.filter {
                if (it.isNotBlank() &amp;&amp; it.length >= 4)
                    return@filter true
                else {
                    edt_password.error = getString(R.string.login02_error)
                    return@filter false
                }
            }.subscribe {
                goLogin(edt_mobile.text.toString(), edt_password.text.toString())
            }

امیدوارم این پست براتون مفید بوده باشه و ازش استفاده کنید. از طریق راه های ارتباطی زیر میتونید با ما برای درخواست آموزش های اختصاصی و انواع پروژه ها در ارتباط باشید.


دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *