tejariapp-new-logotejariapp-new-logotejariapp-new-logotejariapp-new-logo
  • صفحه اصلی
  • پروژه ها
    • پروژه طراحی سایت
    • پروژه های اندروید
    • پروژه های تحت ویندوز
    • UI & UX
    • ربات تلگرام
  • سفارش پروژه
    • انجام پروژه اندروید (Android)
    • طراحی و ساخت اپلیکیشن موبایل
    • انجام پروژه طراحی سایت با php
    • انجام پروژه طراحی سایت با Asp.net
    • انجام پروژه سی شارپ
    • فرم سفارش پروژه
  • مدرسه ی تجاری اپ
    • طراحی سایت
    • اندروید
    • سی شارپ
    • آموزش پایگاه داده
    • برنامه های کاربردی
  • لینک های مفید
    • پرداخت آنلاین
    • درباره تجاری اپ
    • تماس با ما
استخدام برنامه نویس متلب
سفارش پروژه
✕
            هیچ نتیجه ای یافت نشدمشاهده همه نتایج

            آموزش الگوی MVVM و RxJava به صورت پروژه محور + سورس کد

            • صفحه نخست
            • مدرسه ی تجاری اپ آموزش اندروید
            • آموزش الگوی MVVM و RxJava به صورت پروژه محور + سورس کد
            android framework logo
            برترین فریم ورک های اندروید
            12 آبان 1396
            سورس کد فریم ورک های دیتابیس اندروید
            21 آبان 1396
            منتشر شده توسط مهندس داودی
            mvvmlogo

            mvvmlogo

            آموزش الگوی MVVM و RxJava به صورت پروژه محور ، توی این آموزش ما قصد داریم که با انجام یک پروژه تا حدودی با دو مفهوم الگوی طراحی MVVM و RxJava آشنا بشیم.
            دلیل استفاده از این دو مفهوم نیز این است که پروژه ای که ایجاد میکنیم رو طبق استاندارد های جهانی برنامه نویسی پیش ببریم تا معتبرتر و البته منعطف تر بشوند.

            آموزش الگوی طراحی MVVM و برنامه نویسی واکنش گرا با RxJava

            قبل از شروع به کار پروژه بهتره تا کمی با تئوری این دو مفهوم آشنا بشیم.
            چرا از الگوی طراحی یا design pattern استفاده کنیم؟!
            سوال جالبیه خب چه کاریه وقتی میتونیم کدهامون رو هرطور ی با هرساختاری ایجاد کنیم بیایم از این الگو ها استفاده کنیم!؟
            خب البته اجباری هم برای این کار نیست! درواقع دلیل استفاده از الگوهای طراحی یا design patternها به عبارتی تمیز کردن کدهای ما هستن
            چون در نهایت خروجی با هر الگویی بوجود میاد اما این پشت پرده ماجرا است که برنامه نویس باهاش سروکار داره و قطعا نیاز به آپدیت کدهاش هست و البته تا آخر عمر که خودش رو پروژه نیست ! به احتمال زیاد یک نفر دیگه ممکنه بخواد با کدها کار کنه و اون موقع است که برنامه نویس بعدی باید متوجه بشه که برنامه نویس قبلی چیکار کرده !!
            دلیل مهم دیگر استفاده از design pattern ها امکان testable یا تست پذیر بودن هر بخش بدون نیاز به بخش دیگر است(که این خود موضوع قابل بحثی است برای اطلاعات بیشتر در ارتباط با تست پذیر کردن پروژه به این مقاله مراجعه کنید)
            همین دلایل و بسیاری دلایل دیگه هست که باعث میشه ما از design pattern ها استفاده کنیم

            اما نکته قابل توجه این است که هنوز هم اجباری در استفاده از الگوهای پیشنهادی خود اندروید (MVC, MVP, MVVM) نیست.

            شما اگر خودتون یک ساختار استاندارد سفارشی شده برای خودتون دارید که از مشکلات گفته شده جلوگیری میکنه میتونید از همون استفاده کنید.

            خب بریم سراغ design pattern هایی که اندروید زحمتشو کشیده که تا به حال ۳ تا ارئه داده به شرح زیر (میتونید آموزش کامل هر ۳ الگو رو در این مقاله مطالعه کنید )

            MVC(Model View Controller)

            دارای سه بخش Model View Controller است که به صورت زیر عمل میکنند

            *Model

            در واقع همان POJO ها یا کلاس هاس معمولی است که از هیچ کلاسی ارث بری نمیکنند و وظیفه تعریف ساختار و ویژگی های یک شی را دارند.

            *View

            نماینده Modelها هستند. وظیفه viewها نمایش UI مناسب به کاربر است و ارتباط مستقیم با Controller جهت اعمال دستورات user میباشد.

            *Controller

            درواقع هسته مرکزی این الگوست چون تمامی عملیات اصلی درون این بخش انجام میشود و رابطی بین View و Model میباشد برای مثال زمانی که کاربر در view یک کلید را فشرد conteroller عملیات لازم را در model اعمال میکند

            MVC(Model View Controller)
            MVC(Model View Controller)

            MVP (Model View Presenter)

            دارای سه بخش Model View Presenter است که به صورت زیر عمل میکنند.

            *Model

            در واقع همان نقش سابق را دارد (کلاس هاس ساده POJO )

            *View

            ها در این الگو کمی متفاوت هستند.در این design pattern اکتیویتی ها و فرگمنت ها به عنوان بخشی از view معرفی شدند و دیگر لازم نیست تمامی عملیات را مثل الگوی قبل انجام دهند و تنها کافی است از یک interface ساخته شده با عنوان view استفاده کنند تا نتیجه عملیاتی که در presenter انجام میشود را به کاربر نمایش دهد.

            *Presenter

            ها در این الگو دقیقا وظیفه Controller هارا درالگوی mvc به عهده دارند با این تفاوت که آنها اصلا با view هادر ارتباط نیستند و درصورت نیاز از interface ها استفاده میکنند.

            MVP (Model View Presenter)
            MVP (Model View Presenter)

            الگوی طراحی MVVM (Model View View-Model)

            این الگو نیز دارای ۳ بخش Model View ViewModel میباشد که یک تفاوت عمده با دو الگوی قبلی دارد و آن استفاده از Data Binding on Adnroid است که علاوه بر بالابردن امکان ماژولاری و تست پذیر کردن پروژه باعث کاهش کدنویسی جهت اتصال view و model نیز شده و عملکرد هر بخش نیز به شرح زیر است

            *Model

            عملکرد سابق را دنبال میکند(کلاس های ساده POJO به همراه getter ها و setter ها)

            *View

            در واقع باز به اکتیویتی وفرگمنت هایی اشاره میکند که عناصرشان bind شده به viewModel با استفاده از همان ویژگی جالب DataBinding علاوه بر فیلد ها همچنین اکشن ها نیز برای مثال اجرای یک متد هنگام فشردن یک کلید نیز bind شده به viewModel

            *ViewModel

            وظیفه دارد که اطلاعات مورد نیاز را به هرشکل وشمایلی که نیاز view است از model دریافت و برای نمایش در view ارائه دهد همچنین ViewModel به طور مستقیم با view در ارتباط نیست بلکه از یک interface جهت اعمال عملیات خاص خود در view (اکتیویتی یا فرگمنت) استفاده میکند.

            الگوی MVVM
            الگوی MVVM

            ما در این پروژه از آخرین الگوی ارائه شده یعنی الگوی MVVM استفاده میکنیم.

            حالا مفهوم RxJava رو تا حدودی آشنا بشیم
            کلا RxJava و reactive programming یا برنامه نویسی واکنشی یعنی چی؟!
            برنامه نویسی واکنشی یا reactive programming همونطور که از اسمش مشخصه یعنی واکنش در لحظه !

            به نقل از wikipedia

            Reactive programming is a programming paradigm oriented around data flows and the propagation of change. This means that it should be possible to express static or dynamic data flows with ease in the programming languages used, and that the underlying execution model will automatically propagate changes through the data flow.


            به عبارت ساده تر برنامه نویسی واکنشی حول محور جریان داده ها حرکت میکند و در مواقع معین تغییرات را منتشر میکند و این دلیلی است برای اینکه برنامه نویسی asynchronous یا ناهمگام رو برنامه نویسی reactieve هم میگن. در این نوع برنامه نویسی ما از observerها یا مشاهده گر ها استفاده میکنیم برای انتشار تغییر حالت یا رویداد.

            و حال RxJava هم یک پیاده سازی براساس جاوا با مفهوم reactive programming هست که Api های جاوا رو جهت برنامه نویسی ناهمگام یا asynchronous با Observabel stream رو برای ما فراهم میکنه!
            reactive programming مختص جاوا و برنامه نویسی اندروید نیست بلکه reactivex یا Reactive Extensions افزونه هایی هستند برای زبان های برنامه نویسی مختلف که امکان برنامه نویسی reactive رو در پروژه فراهم میکنند.

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

            -OBSERVABLE

            مشاهده گرها یا observableها چیزی جز جریان داد ها نیستند.
            observableها داده هایی که میتوانند (ویا باید) از یک thread به thread دیگر منتقل شوند به صورت بسته ای از داده ها ارسال میکنند.
            اونها اساسا داده هارا منتشر یا emit میکنند که این emitکردن ممکن است براساس نوع تنظیمات تعیین شده به صورت دوره ای ویا یکجا و یکبار باشد. به عبارت دیگر هم میتوان گفت Observableها تامین کننده های ما هستند.
            تعداد بسیار زیادی operator در Rxjava وجود دارد(همین عامل باعث محبوبیت بیش از حد Rxjava نیز میباشد ) که به Observable جهت به دست آوردن خروجی ویژه تر متناسب با خواست ما کمک میکند.
            همه operatorها رو میتونید از اینجا ببینید.

            -OBSERVER

            observerها جریان داده های تولیدی observable رو مصرف میکنند. observer ها با متد subscribeOn() دستورات observable رو اجرا میکنند تا به داده های منتشر شده توسط observable رو دریافت کنند.
            هرزمان که observable داده هارو منتشر میکنه تمامی observer هایی که به این observable اشاره کردند داده هارو در متد onNext() خودشون دریافت میکنند. و اگر هم با خطایی مواجه شد اون خطارو داخل متد onError میتونیم شناسایی کنیم.

            -SCHEDULERS

            همونطور که بالاتر گفتیم Rx به معنای برنامه نویسی asynchronous یا ناهمگام هستش پس ما باید threadها رو جهت تقسیم بندی کارها کنترل کنیم.
            اینجاست که Schedularها میان توی کدهای ما! درواقع Schedularها جزئی از Rx هستند که به Observable و Observer میگن که داخل کدوم thread باید اجرا بشن.
            با استفاده از متد observeOn() مشخص میکنیم که Observeها داخل کدوم thread و با استفاده از subscribeOn() به Observable میگیم که داخل کدوم thread اجرا بشن.
            برای مثال پارامتر Schedulers.io() مشخص میکنه که برای مثال observer یا observable در thread مربوط به io یا ورودی خروجی (برای مثال ارتباط با سرور) اجرا بشه.

            ما توی برنامه نویسی اندروید علاوه بر Rxjava از RxAndroid هم استفاه میکنیم درواقع RxAndroid یک فرمت برای RxJava است چون ما در برنامه نویسی اندروید از جاوا استفاده میکنیم پس RxJava رو داریم اما برخی مباحث اندروید هستند که در RxJava موجود نیست و برای خود اندروید هستند مثل multi threading که بالا با عنوان Schedulers باهاش آشنا شدیم به همین جهت ما از RxAndroid برای برخی ویژگی های خاص اندروید هم استفاده میکنیم..

            خب حالا که تا حدودی با این دو مفهوم آشنا شدیم بریم سراغ کدزدن.
            ما در این آموزش میخوایم یه پروژه اندروید متصل به سرور asp.net ایجاد کنیم که اگر آموزش قبل مارو دیده باشید مبحث اتصال اندروید به سرور asp.net با retrofit رو آموزش دادیم
            و داخل این آموزش تنها میخوایم دستورات داخل اندروید استودیو رو به الگوی MVVM و دستورات سرور رو به RxJava تبدیل کنیم پس پیشنهاد میکنم اگر آموزش قبل مارو ندیدید حتما مطالعه ای داشته باشید.

            قبل از هرکار کتابخانه های مربوط به RxJava رو اضافه میکنیم

            compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
            compile 'io.reactivex.rxjava2:rxjava:2.1.5'
            compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
            

            و همچنین کتابخانه هایی که از آموزش قبل در gradle بود

            compile 'com.google.code.gson:gson:2.6.2'
            compile 'com.squareup.retrofit2:retrofit:2.0.2'
            compile 'com.squareup.retrofit2:converter-gson:2.0.2'
            compile 'com.android.support:cardview-v7:25.3.1'
            

            و مهم تر از همه فعال کردن ویژگی DataBinding پروژه هستش چون داخل الگوی MVVM ما از DataBinding استفاده میکنیم پس

            android {
            ....
            dataBinding{
            enabled = true
            }
            }
            

            خب بریم سراغ کلاس مدل که ما Person رو داریم که بدین صورته

            package com.tejariapp.mvvmrxjava.data.model;
            
            import com.google.gson.annotations.SerializedName;
            
            /**
            * Created by Marjan on 23/10/2017.
            */
            
            public class Person {
            @SerializedName("Id")
            private int pID;
            
            @SerializedName("Name")
            private String pName;
            
            @SerializedName("Family")
            private String pFamily;
            
            public Person(){}
            
            public Person(int id,String pName,String pFamily){
            this.pID=id;
            this.pName=pName;
            this.pFamily=pFamily;
            }
            
            public Person(String pName,String pFamily){
            this.pName=pName;
            this.pFamily=pFamily;
            }
            public int getpID() {
            return pID;
            }
            
            public String getpFamily() {
            return pFamily;
            }
            
            public String getpName() {
            return pName;
            }
            
            public void setpID(int pID) {
            this.pID = pID;
            }
            
            public void setpName(String pName) {
            this.pName = pName;
            }
            
            public void setpFamily(String pFamily) {
            this.pFamily = pFamily;
            }
            }
            

            مشخصه که تغییر آنچنانی با آموزش قبل نکرده چون طبق گفته هادر بخش design pattern ها قسمت model در تمامی الگوهای طراحی یکسان بود
            حالا میریم سراغ اینترفیس (interface) taskService که وظیفه ارتباط با سرور رو داشت
            این قسمت تغییر های اساسی کرده

            package com.tejariapp.mvvmrxjava.data.api;
            
            import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
            import com.tejariapp.mvvmrxjava.data.model.Person;
            
            import java.util.List;
            
            import io.reactivex.Observable;
            
            import okhttp3.ResponseBody;
            import retrofit2.Call;
            import retrofit2.Retrofit;
            import retrofit2.converter.gson.GsonConverterFactory;
            import retrofit2.http.Body;
            import retrofit2.http.Field;
            import retrofit2.http.FormUrlEncoded;
            import retrofit2.http.GET;
            import retrofit2.http.POST;
            
            /**
            * Created by Marjan on 26/09/2017.
            */
            
            public interface TaskService {
            @GET("StudentApi/getAll")
            Observable<List<Person>> getPersons();
            
            @POST("StudentApi/insertObjStu")
            Observable<Person> addNewPerson(@Body Person person);
            
            @FormUrlEncoded
            @POST("StudentApi/insertObjStu")
            Call<Person> addNewPerson(@Field("name") String name
            , @Field("family") String family);
            
            @POST("StudentApi/updateStudent")
            Observable<String> updatePersonInfo(@Body Person person);
            
            @FormUrlEncoded
            @POST("StudentApi/deleteStudent")
            Observable<String> deletePeronInfo(@Field("id") int id);
            

            همونطور که میبینید به جای Call<> از Observable<> استفاده شده چون میخوایم از RxJava استفاده کنیم و این قسمت طبق گفته ها وظیفه تولید و emit داده ها به سمت Observer رو به عهده داره.
            حالا کلاس ServiceGenerator رو مبینیم که وظیفش ایجاد بیس درخواست یا request به سرور بود

            package com.tejariapp.mvvmrxjava.data.api;
            
            import com.google.gson.Gson;
            import com.google.gson.GsonBuilder;
            import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
            
            import java.io.IOException;
            
            import okhttp3.Interceptor;
            import okhttp3.OkHttpClient;
            import okhttp3.Request;
            import okhttp3.Response;
            import retrofit2.converter.gson.GsonConverterFactory;
            
            /**
            * Created by Marjan on 26/09/2017.
            */
            
            public class ServiceGenerator {
            
            private static final String URL = "http://10.0.2.2:62813/";
            private TaskService apiService;
            
            public ServiceGenerator()
            {
            OkHttpClient okClient = new OkHttpClient.Builder()
            .addInterceptor(
            new Interceptor() {
            @Override
            public Response intercept(Interceptor.Chain chain) throws IOException {
            Request original = chain.request();
            // Request customization: add request headers
            Request.Builder requestBuilder = original.newBuilder()
            //cues it want to run as local in local server
            .header("Host", "localhost")
            .method(original.method(), original.body());
            
            Request request = requestBuilder.build();
            return chain.proceed(request);
            }
            })
            .build();
            
            Gson gson = new GsonBuilder()
            .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
            .setLenient()
            .create();
            
            retrofit2.Retrofit restAdapter = new retrofit2.Retrofit.Builder()
            .baseUrl(URL)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create(gson))
            .client(okClient)
            .build();
            
            apiService = restAdapter.create(TaskService.class);
            }
            
            public TaskService getService()
            {
            return apiService;
            }
            
            }
            
            

            توی این کلاس تغییرات زیادی نیاز نداریم به جز موارد زیر
            .setLenient() که در تعریف gson بکار رفته و درواقع برای صحیح دریافت کردن مقدار ریسپانسی هست که به صورت string از سرور دریافت میشه(که ربطی به RxJava و الگوی MVVM نداره فقط برای بهبود کار اضافه شده)
            و.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) که به restAdapter اضافه شده.
            خب حالا باید یک interface جدید تحت عنوان PersonRepository ایجاد کنیم با کدهای زیر

            package com.tejariapp.mvvmrxjava.data.repository;
            
            import com.tejariapp.mvvmrxjava.data.model.Person;
            
            import java.util.ArrayList;
            import java.util.List;
            
            import io.reactivex.Observable;
            
            public interface PersonsRepository {
            
            /*
            * Get list of popular persons
            */
            Observable&amp;amp;lt;List&amp;amp;lt;Person&amp;amp;gt;&amp;amp;gt; getAllPersons();
            
            /**
            * Insert new person in server
            */
            Observable&amp;amp;lt;Person&amp;amp;gt; insertNewPerson(Person person);
            
            /**
            * Update person in server
            */
            Observable&amp;amp;lt;String&amp;amp;gt; updatePerson(Person person);
            
            /**
            * Delete person in server
            */
            Observable&amp;amp;lt;String&amp;amp;gt; deletePerson(int id);
            } 

            و یک کلاس جدید تحت عنوان PersonRemoteRepository برای کدنویسی متدهای اینترفیس ایجاد میکنیم با کدنویسی زیر

            package com.tejariapp.mvvmrxjava.data.repository;
            
            import android.util.Log;
            
            import com.tejariapp.mvvmrxjava.data.model.Person;
            import com.tejariapp.mvvmrxjava.data.api.ServiceGenerator;
            import com.tejariapp.mvvmrxjava.data.api.TaskService;
            
            import java.util.List;
            
            import io.reactivex.Observable;
            import io.reactivex.annotations.NonNull;
            import io.reactivex.functions.Function;
            
            public class PersonsRemoteRepository implements PersonsRepository {
            
            private TaskService apiService;
            
            ServiceGenerator serviceGenerator;
            
            public PersonsRemoteRepository(ServiceGenerator serviceGenerator) {
            this.serviceGenerator = serviceGenerator;
            }
            @Override
            public Observable&amp;amp;lt;List&amp;amp;lt;Person&amp;amp;gt;&amp;amp;gt; getAllPersons() {
            Observable&amp;amp;lt;List&amp;amp;lt;Person&amp;amp;gt;&amp;amp;gt; observable=
            serviceGenerator.getService().getPersons();
            return observable
            .flatMap(new Function&amp;amp;lt;List&amp;amp;lt;Person&amp;amp;gt;, Observable&amp;amp;lt;List&amp;amp;lt;Person&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;() {
            @Override
            public Observable&amp;amp;lt;List&amp;amp;lt;Person&amp;amp;gt;&amp;amp;gt;
            apply(@NonNull List&amp;amp;lt;Person&amp;amp;gt; persons) throws Exception {
            return Observable.fromArray(persons);
            }
            });
            
            }
            
            @Override
            public Observable&amp;amp;lt;Person&amp;amp;gt; insertNewPerson(Person person) {
            Observable&amp;amp;lt;Person&amp;amp;gt; observable =
            serviceGenerator.getService().addNewPerson(person);
            return observable
            .flatMap(new Function&amp;amp;lt;Person, Observable&amp;amp;lt;Person&amp;amp;gt;&amp;amp;gt;() {
            @Override
            public Observable&amp;amp;lt;Person&amp;amp;gt; apply(@NonNull Person person) throws Exception {
            return Observable.just(person);
            }
            });
            }
            
            @Override
            public Observable&amp;amp;lt;String&amp;amp;gt; updatePerson(Person person) {
            Observable&amp;amp;lt;String&amp;amp;gt; observable=
            serviceGenerator.getService().updatePersonInfo(person);
            return observable
            .map(new Function&amp;amp;lt;String, String&amp;amp;gt;() {
            @Override
            public String apply(@NonNull String s) throws Exception {
            Log.e("map",s);
            return s;
            }
            });
            }
            
            @Override
            public Observable&amp;amp;lt;String&amp;amp;gt; deletePerson(int id) {
            Observable&amp;amp;lt;String&amp;amp;gt; observable=
            serviceGenerator.getService().deletePeronInfo(id);
            return observable
            .map(new Function&amp;amp;lt;String, String&amp;amp;gt;() {
            @Override
            public String apply(@NonNull String s) throws Exception {
            Log.e("map",s);
            return s;
            }
            });
            }
            } 

            خب کلا وظیفه این دو کلاس رو بخوایم توضیح بدیم میتونیم اینطور بگیم که این کلاس ها رابط بین ما درخواست های سرور هستند.
            بدین صورت که ما از هر کلاسی میتونیم با استفاده از یک شی از نوع اینترفیس PersonRepository یکی از متدهای اون رو بسته به نیاز صدا بزنیم و اون متد هم دستورات رتروفیت داخل اینترفیس TaskService رو اجرا میکنه.
            میبینید که متدها با RxJava نوشته شدند برای مثال یکی از متدهارو با هم بررسی میکنیم

            @Override
            public Observable&amp;amp;lt;Person&amp;amp;gt; insertNewPerson(Person person) {
            Observable&amp;amp;lt;Person&amp;amp;gt; observable =
            serviceGenerator.getService().addNewPerson(person);
            return observable
            .flatMap(new Function&amp;amp;lt;Person, Observable&amp;amp;lt;Person&amp;amp;gt;&amp;amp;gt;() {
            @Override
            public Observable&amp;amp;lt;Person&amp;amp;gt; apply(@NonNull Person person) throws Exception {
            return Observable.just(person);
            }
            });
            }
            

            خب ابتدا نوع متد رو میبینم که به صورت Observable<Person> هست که یک شی از نوع Person رو برمیگردونه و سپس Observable که ایجاد کردیم که از طریق اون به متد سرور دسترسی پیدا کنیم

            serviceGenerator.getService().addNewPerson(person);
            

            دقیقا از نوع متد addNewPerson در اینترفیس TaskService میباشد Observable<Person>
            و در اخر هم با استفاده از Operator , (از اینجا ببینید) flatMap() مقدار شی person دریافتی رو دریافت میکنه و با استفاده از just اون رو برمیگردونه

            @Override
            public Observable&amp;amp;lt;Person&amp;amp;gt; insertNewPerson(Person person) {
            Observable&amp;amp;lt;Person&amp;amp;gt; observable =
            serviceGenerator.getService().addNewPerson(person);
            return observable
            .flatMap(new Function&amp;amp;lt;Person, Observable&amp;amp;lt;Person&amp;amp;gt;&amp;amp;gt;() {
            @Override
            public Observable&amp;amp;lt;Person&amp;amp;gt; apply(@NonNull Person person) throws Exception {
            return Observable.just(person);
            }
            });
            }
            

            خب حالا قبل از اینکه بریم ViewModel هارو ایجاد کنیم یک اینترفیس دیگه با عنوان Interactor ایجادمیکنیم که رابطی بین ViewModel ها و View است

            ;package com.tejariapp.mvvmrxjava.ui.persons
            
            import com.tejariapp.mvvmrxjava.data.model.Person;
            
            /**
            * Created by Marjan on 24/10/2017.
            */
            
            public interface Interactor {
            
            /*
            * delete all list item when user click read button
            */
            void deleteAll();
            /*
            * show person info in EditTexts when user click in each list item
            */
            void showPersonInfo(Person person);
            
            /*
            * add new person item to list after added in server
            */
            void addNewPerson(Person person);
            
            /*
            * update person item in list after updated in server
            */
            void updatePerson(String response,Person person);
            
            /*
            * delete person item after deleted in server
            */
            void deletePerson(String response,int id);
            }
            

            خب حالا باید بریم سراغ viewModel ها که layout ها که در ادامه بررسی شون میکنیم بهش bind شدن
            ما یه PersonVM درایم که ViewModel بیس مامحسوب میشه و اشاره کامل داره به مدل Person به صورت زیر

            
            package com.tejariapp.mvvmrxjava.ui.persons;
            
            import android.databinding.BaseObservable;
            import android.databinding.ObservableField;
            
            import com.tejariapp.mvvmrxjava.data.model.Person;
            import com.tejariapp.mvvmrxjava.data.repository.PersonsRepository;
            
            /**
            * Created by Marjan on 25/10/2017.
            */
            
            public class PersonVM extends BaseObservable {
            
            public final ObservableField&amp;amp;lt;Integer&amp;amp;gt; id = new ObservableField&amp;amp;lt;&amp;amp;gt;();
            public final ObservableField&amp;amp;lt;String&amp;amp;gt; name = new ObservableField&amp;amp;lt;&amp;amp;gt;();
            public final ObservableField&amp;amp;lt;String&amp;amp;gt; family = new ObservableField&amp;amp;lt;&amp;amp;gt;();
            private final ObservableField&amp;amp;lt;Person&amp;amp;gt; observablePerson = new ObservableField&amp;amp;lt;&amp;amp;gt;();
            
            public PersonVM(){
            
            observablePerson.addOnPropertyChangedCallback(new OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(android.databinding.Observable sender,
            int propertyId) {
            Person person=observablePerson.get();
            
            if (person != null){
            id.set(getId(person));
            name.set(getName(person));
            family.set(getFamily(person));
            }
            }
            });
            }
            
            public int getId(Person person) {
            return person.getpID();
            }
            
            public String getFamily(Person person) {
            return person.getpFamily();
            }
            
            public String getName(Person person) {
            return person.getpName();
            }
            
            public Person getObservablePerson() {
            return observablePerson.get();
            }
            
            public void setObservablePerson(Person observablePerson){
            this.observablePerson.set(observablePerson);
            }
            }
            

            همونطور که میبینید فیلدها به صورت ObservableField تعریف شدند چون داریم با RxJava کار میکنیم.
            داخل سازنده این کلاس ما از Callback زیر استفاده کردیم

            observablePerson.addOnPropertyChangedCallback(
            new OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(android.databinding.Observable sender
            , int propertyId) {
            Person person=observablePerson.get();
            
            if (person != null){
            id.set(getId(person));
            name.set(getName(person));
            family.set(getFamily(person));
            }
            }
            }); 

            این تیکه زمانی اجرا میشه که متد setObservablePerson اجرا شده باشه و فیلد observablePerson مقداردهی شده باشه تا با استفاده از متد get() به شی perosn رو بگیریم و فیلدهای id, name, family رو مقداردهی کنیم.
            یک viewmodel دیگه نیاز داریم برای activity_main.xml که کامپوننت های داخل این لایه رو به متدها و یا فیلدهای viewModel متصل یا bind کنیم.
            پس کلاس جدید با عنوان personsVM ایجاد میکنیم که از کلاس PersonVM ارث بری میکنه (تا بتونیم به فیلدهای id,name,family در این کلاس دسترسی داشته باشیم)

            package com.tejariapp.mvvmrxjava.ui.persons;
            
            import android.databinding.ObservableArrayList;
            import android.databinding.ObservableList;
            import android.util.Log;
            
            import com.tejariapp.mvvmrxjava.data.model.Person;
            import com.tejariapp.mvvmrxjava.data.repository.PersonsRepository;
            import com.tejariapp.mvvmrxjava.databinding.ActivityMainBinding;
            
            import java.util.List;
            
            import io.reactivex.Observer;
            import io.reactivex.android.schedulers.AndroidSchedulers;
            import io.reactivex.annotations.NonNull;
            import io.reactivex.disposables.Disposable;
            import io.reactivex.observers.DisposableObserver;
            import io.reactivex.schedulers.Schedulers;
            
            /**
            * Created by Marjan on 23/10/2017.
            */
            
            public class personsVM extends PersonVM {
            
            //fill with persons info that come from server
            public final ObservableList&amp;amp;lt;Person&amp;amp;gt; persons = new ObservableArrayList&amp;amp;lt;&amp;amp;gt;();
            
            private final PersonsRepository personsRepository;
            Interactor interactor;
            ActivityMainBinding mainBinding;
            
            /*
            * @param personsRepository - execute server mthods
            * @param interactor - execute methods in MainActivity base of server response
            * @param mainBinding - for access to activity_main view values
            */
            
            public personsVM(PersonsRepository personsRepository,
            Interactor interactor, ActivityMainBinding mainBinding){
            this.personsRepository=personsRepository;
            this.interactor=interactor;
            this.mainBinding=mainBinding;
            }
            
            /*
            * execute deletePerson base of his id in server and get String response
            */
            public void deletePerson(){
            final int id=Integer.parseInt(mainBinding.id.getText().toString());
            personsRepository.deletePerson(id)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(new Observer&amp;amp;lt;String&amp;amp;gt;() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {
            Log.e("delete onSubscribe",d.toString());
            }
            
            @Override
            public void onNext(@NonNull String s) {
            if (s !=null)
            interactor.deletePerson(s,id);
            Log.e("delete onNext",s.toString());
            }
            
            @Override
            public void onError(@NonNull Throwable e) {
            Log.e("delete onError",e.toString());
            }
            
            @Override
            public void onComplete() {
            Log.e("delete","onComplete");
            }
            });
            }
            
            /*
            * update person base of his id in server and get String response
            */
            public void updatePerson(){
            int id=Integer.parseInt(mainBinding.id.getText().toString());
            String name=mainBinding.name.getText().toString();
            String family=mainBinding.family.getText().toString();
            final Person person=new Person(id,name,family);
            personsRepository.updatePerson(person)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribeWith(new DisposableObserver&amp;amp;lt;String&amp;amp;gt;() {
            @Override
            public void onNext(@NonNull String s) {
            if (s != null)
            interactor.updatePerson(s,person);
            Log.d("update response is",s);
            }
            
            @Override
            public void onError(@NonNull Throwable e) {
            Log.e("onError",e.toString());
            }
            
            @Override
            public void onComplete() {
            Log.e("onComplete","onComplete");
            }
            });
            }
            
            /*
            * insert new person in server and return it
            */
            public void insertNewPerson(){
            String name=mainBinding.name.getText().toString();
            String family=mainBinding.family.getText().toString();
            personsRepository.insertNewPerson(new Person(name,family))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribeWith(new DisposableObserver&amp;amp;lt;Person&amp;amp;gt;() {
            @Override
            public void onNext(@NonNull Person person) {
            if (person != null)
            interactor.addNewPerson(person);
            }
            
            @Override
            public void onError(@NonNull Throwable e) {
            Log.e("onError",e.toString());
            }
            
            @Override
            public void onComplete() {
            Log.e("onComplete","onComplete");
            }
            });
            }
            
            /*
            * get all persons info in server
            */
            public void getPersons(){
            personsRepository.getAllPersons()
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribeWith(new DisposableObserver&amp;amp;lt;List&amp;amp;lt;Person&amp;amp;gt;&amp;amp;gt;() {
            @Override
            public void onNext(List&amp;amp;lt;Person&amp;amp;gt; value) {
            //Log.e("list get and size is",value.getpName() + value.getpFamily());
            interactor.deleteAll();
            persons.addAll(value);
            Log.e("persons array size",String.valueOf(persons.size()));
            }
            
            @Override
            public void onError(Throwable throwable) {
            Log.e("onError",throwable.toString());
            }
            
            @Override
            public void onComplete() {
            Log.e("onComplete","onComplete");
            }
            });
            }
            }
            

            در ارتباط با پارامترها توضیحات لازم کامنت شده پس بهتره بریم یکی ازمتدهای Observe رو توضیح بدیم برای مثال متد insert

            /*
            * insert new person in server and return it
            */
            public void insertNewPerson(){
            String name=mainBinding.name.getText().toString();
            String family=mainBinding.family.getText().toString();
            personsRepository.insertNewPerson(new Person(name,family))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribeWith(new DisposableObserver&amp;amp;lt;Person&amp;amp;gt;() {
            @Override
            public void onNext(@NonNull Person person) {
            if (person != null)
            interactor.addNewPerson(person);
            }
            
            @Override
            public void onError(@NonNull Throwable e) {
            Log.e("onError",e.toString());
            }
            
            @Override
            public void onComplete() {
            Log.e("onComplete","onComplete");
            }
            });
            } 

            خب میبینید که با استفاده از شی personRepository متد insertNewPerson رو صدازده و با ObserveOn گفته شده Observe در mainThread اجرا بشه و با استفاده از subscriceOn گفته شده Observable در ترد io اجرا بشه و در نهایت هم با استفاده از subscribeWith گفته شده در هر شرایط چه عملیاتی رو انجام بده.

            ما توی فایل xml یک RecyclerView هم داشتیم که حالا Adapterی که براش ساخته بودیم باید کمی ویرایش کنیم اما قبل از اون باید viewModel مربوط به اون رو ایجاد کنیم پس یک کلاس جدید که از کلاس PersonVM ارث بری میکنه ایجاد میکنیم

            package com.tejariapp.mvvmrxjava.ui.persons
            import com.tejariapp.mvvmrxjava.data.model.Person;
            import com.tejariapp.mvvmrxjava.data.repository.PersonsRepository;
            
            /**
            * Created by Marjan on 24/10/2017.
            */
            
            public class personsItemVM extends PersonVM {
            
            Interactor interactor;
            
            public personsItemVM( Interactor interactor) {
            this.interactor=interactor;
            }
            
            /*
            * execute when user click on each list item
            */
            public void clickPersonInfo() {
            Person person = getObservablePerson();
            if (person != null) {
            interactor.showPersonInfo(person);
            }
            }
            }
            
            

            و در این کلاس یک متد برای اجرا شدن زمانی که کاربر روی هرکدام از آیتم های لیست کلیک کرد قرار میدیم

            و حالا هم PersonAdapter مطابق زیر

            package com.tejariapp.mvvmrxjava.ui.persons;
            
            import android.databinding.DataBindingUtil;
            import android.support.annotation.NonNull;
            import android.support.v7.widget.RecyclerView;
            import android.view.LayoutInflater;
            import android.view.ViewGroup;
            
            import com.tejariapp.mvvmrxjava.R;
            import com.tejariapp.mvvmrxjava.data.model.Person;
            import com.tejariapp.mvvmrxjava.data.repository.PersonsRepository;
            import com.tejariapp.mvvmrxjava.databinding.ListItemLayoutBinding;
            
            import java.util.ArrayList;
            import java.util.List;
            
            /**
            * Created by Marjan on 24/10/2017.
            */
            
            public class PersonsAdapter extends
            RecyclerView.Adapter&amp;amp;lt;PersonsAdapter.MyViewHolder&amp;amp;gt; {
            
            private List&amp;amp;lt;Person&amp;amp;gt; persons;
            Interactor interactor;
            
            public PersonsAdapter(Interactor interactor) {
            this.persons = new ArrayList&amp;amp;lt;&amp;amp;gt;();
            this.interactor = interactor;
            }
            
            /*
            * delete all items in list(when user click read button
            */
            public void deleteAll() {
            persons.clear();
            notifyDataSetChanged();
            }
            /*
            * set list of person that come from server for list
            */
            public void setPersons(@NonNull List&amp;amp;lt;Person&amp;amp;gt; persons) {
            this.persons = persons;
            notifyDataSetChanged();
            }
            
            /*
            * add one person to list when insert
            */
            public void setPerson(Person person) {
            this.persons.add(person);
            notifyDataSetChanged();
            }
            
            /*
            * update selected item person in list
            */
            public void updatePerson(int id, Person person) {
            int pos = findPos(id);
            this.persons.set(pos, person);
            notifyDataSetChanged();
            }
            
            /*
            * delete selected person item base of his id
            */
            public void deletePerson(int id) {
            int pos = findPos(id);
            persons.remove(pos);
            notifyDataSetChanged();
            }
            
            /*
            * find position of person id for update or delete
            */
            private int findPos(int id) {
            int pos = 0;
            for (int i = 0; i &amp;amp;lt; persons.size(); i++) {
            if (persons.get(i).getpID() == id) {
            pos = i;
            break;
            }
            }
            return pos;
            }
            
            @Override
            public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            ListItemLayoutBinding listItemLayoutBinding = DataBindingUtil
            .inflate(LayoutInflater.from(parent.getContext()),
            R.layout.list_item_layout, parent, false);
            
            return new MyViewHolder(listItemLayoutBinding);
            }
            
            @Override
            public void onBindViewHolder(PersonsAdapter.MyViewHolder holder, int position) {
            Person person = persons.get(position);
            
            //create new PersonItemVM to run interactor method when click on list item
            final personsItemVM personItemVM = new personsItemVM( interactor);
            //set this object to ObservableField&amp;amp;lt;Person&amp;amp;gt; and then on
            // addOnPropertyChangedCallback fill id , name,family for list item views
            personItemVM.setObservablePerson(person);
            holder.setPersonItemVM(personItemVM);
            }
            
            @Override
            public int getItemCount() {
            return persons.size();
            }
            
            public class MyViewHolder extends RecyclerView.ViewHolder {
            ListItemLayoutBinding listItemLayoutBinding;
            
            public MyViewHolder(ListItemLayoutBinding listItemLayoutBinding) {
            super(listItemLayoutBinding.getRoot());
            this.listItemLayoutBinding = listItemLayoutBinding;
            }
            
            //fill each list item with Observable items(id,name,family)
            public void setPersonItemVM(personsItemVM personItemVM) {
            listItemLayoutBinding.setItemVM(personItemVM);
            listItemLayoutBinding.executePendingBindings();
            }
            }
            }
            

            همونطور که میبینید ما لیست personهارو ارسال نکردیم به adapter چون اونو داخل RecyclerView بایند کردیم که در ادامه بررسی میکنیم.
            اما میبینید که ما ListItemLayoutBinding رو داریم که اشاره میکنه به فایل xml مربوط به itemهای لیست که قاعدتا اسمش باید list_item_layout باشه پس این فایل رو با همین نام ایجاد میکنیم

            &amp;amp;lt;?xml version="1.0" encoding="utf-8"?&amp;amp;gt;
            &amp;amp;lt;layout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:bind="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"&amp;amp;gt;
            
            &amp;amp;lt;data class="ListItemLayoutBinding"&amp;amp;gt;
            
            &amp;amp;lt;variable
            name="itemVM"
            type="com.tejariapp.mvvmrxjava.ui.persons.personsItemVM" /&amp;amp;gt;
            &amp;amp;lt;/data&amp;amp;gt;
            
            &amp;amp;lt;android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"&amp;amp;gt;
            
            &amp;amp;lt;android.support.v7.widget.CardView
            android:id="@+id/personCard"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginTop="8dp"
            android:onClick="@{() -&amp;amp;gt; itemVM.clickPersonInfo()}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"&amp;amp;gt;
            
            &amp;amp;lt;android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            &amp;amp;gt;
            
            &amp;amp;lt;TextView
            android:id="@+id/id"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginTop="8dp"
            android:text="@{String.valueOf(itemVM.id)}"
            android:textColor="@android:color/background_dark"
            android:textSize="15sp"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" /&amp;amp;gt;
            
            &amp;amp;lt;TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginTop="8dp"
            android:text="@{itemVM.name}"
            android:textColor="@android:color/background_dark"
            android:textSize="15sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/id"
            app:layout_constraintVertical_bias="0.0" /&amp;amp;gt;
            
            &amp;amp;lt;TextView
            android:id="@+id/family"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginTop="8dp"
            android:text="@{itemVM.family}"
            android:textColor="@android:color/background_dark"
            android:textSize="15sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@+id/name"
            app:layout_constraintTop_toBottomOf="@+id/id"
            app:layout_constraintVertical_bias="0.0" /&amp;amp;gt;
            &amp;amp;lt;/android.support.constraint.ConstraintLayout&amp;amp;gt;
            
            &amp;amp;lt;/android.support.v7.widget.CardView&amp;amp;gt;
            
            &amp;amp;lt;/android.support.constraint.ConstraintLayout&amp;amp;gt;
            &amp;amp;lt;/layout&amp;amp;gt;
            

            خب میبیند که به personItemVM هم اشاره میکنه جهت دسترسی به ObservableField های موجود در همین کلاس یا PersonVM که از آن ارث بری میکند.
            بعد از ایجاد این فایل xml باید یکبار پروژتون رو build کنید تا کلاس ListItemLayoutBinding ایجاد بشه و خطایی که تاحال از این کلاس میگرفت(که وجود ندارد) از بین برود.

            خب حالا باید فایل activity_main.xml رو یه سری تغییرات که برای DataBinding هستش رو بدیم بدین صورت

            &amp;amp;lt;?xml version="1.0" encoding="utf-8"?&amp;amp;gt;
            &amp;amp;lt;layout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            xmlns:bind="http://schemas.android.com/apk/res-auto"
            xmlns:app="http://schemas.android.com/apk/res-auto"&amp;amp;gt;
            
            &amp;amp;lt;data class="ActivityMainBinding"&amp;amp;gt;
            
            &amp;amp;lt;variable
            name="viewModel"
            type="com.tejariapp.mvvmrxjava.ui.persons.personsVM" /&amp;amp;gt;
            &amp;amp;lt;/data&amp;amp;gt;
            
            &amp;amp;lt;ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true"&amp;amp;gt;
            
            &amp;amp;lt;android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"&amp;amp;gt;
            
            &amp;amp;lt;android.support.design.widget.TextInputLayout
            android:id="@+id/input_layout_id"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginEnd="24dp"
            android:layout_marginLeft="24dp"
            android:layout_marginRight="24dp"
            android:layout_marginStart="24dp"
            android:layout_marginTop="16dp"
            app:layout_constraintBottom_toTopOf="@+id/insert"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.0"&amp;amp;gt;
            
            &amp;amp;lt;EditText
            android:id="@+id/id"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:text="@{String.valueOf(viewModel.id)}"
            android:hint="@string/id" /&amp;amp;gt;
            
            &amp;amp;lt;/android.support.design.widget.TextInputLayout&amp;amp;gt;
            
            &amp;amp;lt;android.support.design.widget.TextInputLayout
            android:id="@+id/input_layout_name"
            android:layout_width="0dp"
            android:layout_height="63dp"
            android:layout_marginBottom="8dp"
            android:layout_marginEnd="24dp"
            android:layout_marginLeft="24dp"
            android:layout_marginRight="24dp"
            android:layout_marginStart="24dp"
            android:layout_marginTop="16dp"
            app:layout_constraintBottom_toTopOf="@+id/insert"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/input_layout_id"
            app:layout_constraintVertical_bias="0.0"&amp;amp;gt;
            
            &amp;amp;lt;EditText
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:text="@{viewModel.name}"
            android:hint="@string/name" /&amp;amp;gt;
            
            &amp;amp;lt;/android.support.design.widget.TextInputLayout&amp;amp;gt;
            
            &amp;amp;lt;android.support.design.widget.TextInputLayout
            android:id="@+id/input_layout_family"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginEnd="24dp"
            android:layout_marginLeft="24dp"
            android:layout_marginRight="24dp"
            android:layout_marginStart="24dp"
            android:layout_marginTop="16dp"
            app:layout_constraintBottom_toTopOf="@+id/read"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/input_layout_name"
            app:layout_constraintVertical_bias="0.0"&amp;amp;gt;
            
            &amp;amp;lt;EditText
            android:id="@+id/family"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:text="@{viewModel.family}"
            android:hint="@string/family" /&amp;amp;gt;
            
            &amp;amp;lt;/android.support.design.widget.TextInputLayout&amp;amp;gt;
            
            &amp;amp;lt;Button
            android:id="@+id/insert"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:onClick="@{() -&amp;amp;gt; viewModel.insertNewPerson()}"
            android:text="insert"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@+id/read"
            app:layout_constraintRight_toLeftOf="@+id/delete" /&amp;amp;gt;
            
            &amp;amp;lt;Button
            android:id="@+id/read"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:onClick="@{() -&amp;amp;gt; viewModel.getPersons()}"
            android:text="read"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@+id/insert" /&amp;amp;gt;
            
            &amp;amp;lt;Button
            android:id="@+id/update"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:onClick="@{() -&amp;amp;gt; viewModel.updatePerson()}"
            android:text="update"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@+id/delete"
            app:layout_constraintRight_toRightOf="parent" /&amp;amp;gt;
            
            &amp;amp;lt;Button
            android:id="@+id/delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:onClick="@{() -&amp;amp;gt; viewModel.deletePerson()}"
            android:text="delete"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@+id/insert"
            app:layout_constraintRight_toLeftOf="@+id/update" /&amp;amp;gt;
            
            &amp;amp;lt;android.support.v7.widget.RecyclerView
            android:id="@+id/persons"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginBottom="24dp"
            android:layout_marginEnd="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="24dp"
            app:layout_constraintBottom_toTopOf="@+id/insert"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/input_layout_family"
            bind:persons="@{viewModel.persons}"/&amp;amp;gt;
            &amp;amp;lt;/android.support.constraint.ConstraintLayout&amp;amp;gt;
            &amp;amp;lt;/ScrollView&amp;amp;gt;
            &amp;amp;lt;/layout&amp;amp;gt;
            

            توجه کنید که فایل xml که dataBinding شده باید تمامی کامپوننت ها در تگ layout باشند!
            خب ابتدا viewModel رو برای این layout با تگ variable مشخص میکنیم و بعد هر view رو که میخوایم bind کنیم با این ساختار @{viewModel.family}
            برای فیلدها و @{() -> viewModel.insertNewPerson()}
            برای متدها bind میکنیم تا مثلا با فشردن هر کلید متد bind شده در viewModel اجرا شود.

            اگر توجه کنید ما برای RecyclerView از bind:persons=”@{viewModel.persons}”
            استفاده کردیم تا لیست داده هایی که باید درون آیتم های خودقرار دهد مشخص شود اما برای این bind هم یک کلاس ایجاد کردیم

            package com.tejariapp.mvvmrxjava.ui.persons;
            
            import android.databinding.BindingAdapter;
            import android.support.v7.widget.RecyclerView;
            
            import com.tejariapp.mvvmrxjava.data.model.Person;
            
            import java.util.List;
            
            /**
            * Created by Marjan on 25/10/2017.
            */
            
            public class PersonListBinding {
            
            /*
            * bind:persons use in recyclerView
            * @Parameter recyclerView is that we bind on it
            * @parameter personList is which ObservableList that we bind on it
            */
            @BindingAdapter("bind:persons")
            public static void setPersons(RecyclerView recyclerView,
            List&amp;amp;lt;Person&amp;amp;gt; personList){
            RecyclerView.Adapter adapter=recyclerView.getAdapter();
            
            //check if adapter object isn't null and is from PersonAdapter
            if (adapter != null &amp;amp;amp;&amp;amp;amp; adapter instanceof PersonsAdapter)
            //set retrieve array in Adapter arrayList
            ((PersonsAdapter) adapter).setPersons(personList);
            else
            throw new IllegalStateException("RecyclerView either" +
            " has no adapter set or the "
            + "adapter isn't of type MovieAdapter");
            }
            }
            

            که مشخص میکنه اگر adapter همان PersonAdapter مدنظرما بود لیست Personهارو که داخل RecyclerView تعیین کردیم و به آرایه persons

            در personVM اشاره داره ارسال میکنه به PersonAdapter ارسال میکنه

            خب حالا هم میرسیم به مرحله آخر و MainActivity که باید متدهای داخل اینترفیس interactor رو اجرا کنه

            package com.tejariapp.mvvmrxjava.ui.base;
            
            import android.databinding.DataBindingUtil;
            import android.support.v7.app.AppCompatActivity;
            import android.os.Bundle;
            import android.support.v7.widget.LinearLayoutManager;
            
            import com.tejariapp.mvvmrxjava.R;
            import com.tejariapp.mvvmrxjava.data.model.Person;
            import com.tejariapp.mvvmrxjava.data.api.ServiceGenerator;
            import com.tejariapp.mvvmrxjava.data.repository.PersonsRemoteRepository;
            import com.tejariapp.mvvmrxjava.databinding.ActivityMainBinding;
            import com.tejariapp.mvvmrxjava.ui.persons.Interactor;
            import com.tejariapp.mvvmrxjava.ui.persons.PersonsAdapter;
            import com.tejariapp.mvvmrxjava.ui.persons.personsVM;
            
            public class MainActivity extends AppCompatActivity
            implements Interactor {
            
            private ActivityMainBinding mBinding;
            private personsVM mVM;
            PersonsAdapter personsAdapter;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            
            mBinding= DataBindingUtil.setContentView(this, R.layout.activity_main);
            
            //setup viewmodel
            PersonsRemoteRepository personsRemoteRepository=
            new PersonsRemoteRepository(new ServiceGenerator());
            mVM=new personsVM(personsRemoteRepository,this,mBinding);
            //set viewModel to layout
            mBinding.setViewModel(mVM);
            
            //setup PersonAdapter and recyclerView
            personsAdapter=new PersonsAdapter(this);
            mBinding.persons.setLayoutManager(new LinearLayoutManager(this));
            mBinding.persons.setAdapter(personsAdapter);
            
            //get all persons from server
            mVM.getPersons();
            
            }
            
            /*
            * delete all list items
            */
            @Override
            public void deleteAll() {
            personsAdapter.deleteAll();
            }
            
            /*
            * @param person - return a selected person item
            * when execute this method new PersonsVM
            * created and set as viewModel obj in layout
            * to fill id ,name, family base person info that user clicked
            */
            @Override
            public void showPersonInfo(Person person) {
            mVM.setObservablePerson(person);
            mBinding.setViewModel(mVM);
            }
            
            /*
            * @param person - inserted person
            * here inserted person add to list item
            */
            @Override
            public void addNewPerson(Person person) {
            personsAdapter.setPerson(person);
            }
            
            /*
            * @param person - updated person
            * @param response - string response that come from server
            * update selected person item in list
            */
            @Override
            public void updatePerson(String response,Person person) {
            if (response.equals("success"))
            personsAdapter.updatePerson(person.getpID(),person);
            else
            mBinding.id.setError(getResources()
            .getString(R.string.idError));
            }
            
            /*
            * @param id - id of deleted person
            * @param response - string response that come from server
            * update selected person item in list
            */
            @Override
            public void deletePerson(String response,int id) {
            if (response.equals("successful"))
            personsAdapter.deletePerson(id);
            else
            mBinding.id.setError(getResources().getString(R.string.idError));
            }
            }
            
            

            توضیحات کامل به صورت کامنت ارائه شده.
            برای دانلود سورس کدهم میتونید به کانال تلگرام ما مراجعه کنید
            موفق و پیروز باشید 🙂


            امیدوارم این پست براتون مفید بوده باشه.

            اشتراک گذاری

            پست های مرتبط

            دستورات جریان کنترل (Control flow statements) یا دستورات شرطی و حلقه ها در زبان برنامه نویسی دارت Dart

            دستورات جریان کنترل (Control flow statements) یا دستورات شرطی و حلقه ها در زبان برنامه نویسی دارت Dart

            30 بهمن 1400

            دستورات شرطی و حلقه ها در زبان برنامه نویسی دارت (Dart)


            ادامه مطلب
            آموزش عملگرها یا Operator ها در زبان برنامه نویسی دارت یا Dart

            آموزش عملگرها یا Operator ها در زبان برنامه نویسی دارت یا Dart

            30 بهمن 1400

            آموزش عملگرها یا Operator ها در زبان برنامه نویسی دارت (Dart)


            ادامه مطلب
            توابع در زبان برنامه نویسی دارت (Dart)

            توابع در زبان برنامه نویسی دارت (Dart)

            27 بهمن 1400

            توابع در زبان برنامه نویسی دارت (Dart)


            ادامه مطلب

            7 Comments

            1. محسن گفت:
              20 آبان 1396 در 23:16

              سلام آموزشتون عالی بود.
              فقط یک سوال بنظر شما mvp بهتره استفاده کنیم برای پروژه هامون یا MvvM ؟؟؟

              پاسخ
              • مرجان داودی نژاد گفت:
                21 آبان 1396 در 10:55

                سلام ,خیلی ممنونم 🙂
                ببینید الگوی mvp بعد از mvc ساده ترینه چون به جای اکتیویتی یه کلاس تحت عنوان presenter دارید و تمام دستورات و متداهارو اونجا قرار میگیرند و نتیجه رو به view که اکتیویتی میشه ارسال میکنید ، پس پیچیدگی خاصی نداره
                اما mvvm علاوه بر جدا کردن کامل منطق از view این امکان رو به شما میده ک view رو با استفاده از databinding متصل کنی به بانک و از حجم زیادی از کدنویسی جلوگیری کنید
                و جدا از اون هم الگوی پیشنهادی اندروید توی آموزشات فعلیش هست
                حالا انتخاب با شماست که با کدوم راحتتر هستید و توی پروژتون جوابگو شما میتونه باشه

                پاسخ
            2. مهسا گفت:
              28 دی 1397 در 13:22

              کلاس ActivityMainBinding v رو فراموش کردین بنویسین. و این که سورس این مثال چطوری دانلود میشه؟؟ تو گروه تلگرامتون هم نبود

              پاسخ
              • مرجان داودی نژاد گفت:
                28 دی 1397 در 13:47

                با سلام
                سورس مورد نظر رو می تونید در کانال تلگرام ما دریافت کنید
                آدرس کانال تلگرام : @progrun

                برای پیدا کردن سریعتر سورس میتونید کلمه MVVM رو داخل کانال سرچ کنید

                با احترام

                پاسخ
            3. مهسا منامی گفت:
              28 دی 1397 در 16:26

              خیلی لطف کردی عزیزم

              پاسخ
            4. اسماعیل گفت:
              18 آذر 1398 در 13:00

              سلام و خسته نباشید
              مطلبی خیلی خوب هست ممنون از این مقالتون فقط سورس این پروژه توی کانال تلگرامتون پیدا نکردم اگر ممکن هست به ایمیلم ارسال کنید ممنون از لطفتون

              پاسخ
            5. asghar گفت:
              21 آذر 1399 در 23:43

              سلام
              چرا کدها اینطورین؟ انگار نتونستن رو تشخیص بدن.
              و اما به درخواست مهم چطوری در کنار Retrofit و Rx و MVVM از Dagger2 هم استفاده کنیم؟ اگه آموزشی در این مورد هم بزارید عالی میشه.
              ممنون

              پاسخ

            دیدگاهتان را بنویسید لغو پاسخ

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

            ساخت اپلیکیشن های موبایل

            • ساخت اپلیکیشن فروشگاهی
            • ساخت اپلیکشن ابزاری و خدماتی
            • ساخت اپلیکیشن آموزشی
            • و هزاران موضوع دیگر

             
            کلیک کنید

            آخرین دیدگاه ها

            • 9 اسفند 1401

              مهری اصغری نظر در پیاده سازی اولین پروژه با فلاتر Flutter

            • 26 آبان 1401

              سجاد نظر در پروژه مدیریت سیستم مدرسه با سی شارپ و sql server

            • 7 خرداد 1401

              داودی نظر در آموزش استفاده از ckeditor همراه با آپلود عکس در لاراول 6

            تجاری اپ در شبکه های اجتماعی

            لوگوی تایید پرداخت آنلاین

            2015-2022 © تمامي حقوق مادي و معنوي اين وب سايت نزد تجاری اپ محفوظ بوده و هر گونه کپي برداري از مطالب پيگرد قانوني به همراه دارد! | طراح سایت : ProgRun
            سفارش پروژه
                      هیچ نتیجه ای یافت نشدمشاهده همه نتایج