در قسمت قبل بخش های Model و View را نوشتیم و طراحی کردیم. همچنین کلاسی برای بیلدر رتروفیت و اینترفیسی برای درخواست های Http نوشتیم. در این بخش به سراغ مهم ترین قسمت این دوره، یعنی ViewModel خواهیم رفت.
همانطور که در قسمت اول گفته شد، ViewModel ارتباط بین Model و View را برقرار میکند. ViewModel به وسیله LiveData رابط کاربری را بروز نگه میدارد.
در مرحله اول یک کلاس تحت عنوان RetrofitMusicViewModel ایجاد میکنیم که از کلاس androidx.lifecycle.ViewModel ارث بری میکند. همچنین یک MutableLiveData تعریف میکنم که لیستی از نوع AlbumMode است.
private MutableLiveData<List<AlbumModel>> albumListLiveData;
در مهم ترین قسمت این کلاس یک تابع از نوع void به نام loadList مینویسیم.
private void loadList() { RetrofitBuilder retrofitBuilder = new RetrofitBuilder(); Call<List<AlbumModel>> call = retrofitBuilder.retrofitConfig().getAlbum(); call.enqueue(new Callback<List<AlbumModel>>() { @Override public void onResponse(Call<List<AlbumModel>> call, Response<List<AlbumModel>> response) { if (!response.isSuccessful()) { Log.e("Code: ", String.valueOf(response.code())); return; } albumListLiveData.setValue(response.body()); Log.e("onResponse", response.body().toString()); } @Override public void onFailure(Call<List<AlbumModel>> call, Throwable t) { Log.e("onFailure", t.getMessage()); } }); }
در این تابع برای استفاده از رتروفیت یک شی از کلاس RetrofitBuilder که قبلا ایجاد کرده بودیم تعریف و سپس از متد retrofitConfig استفاده کرده و درخواست getAlbum که قبلا در اینترفیس Api نوشته بودیم را در call میریزیم.
سپس درخواست call را برای اجرا کردن نوشته و در onResponse لیستی را که سرور برگردانده بود را در albumListLiveData قرار میدهیم. حالا ما یک متد داریم که درخواست رتروفیت را اجرا میکند و داخل لیستی که تعریف کرده ایم قرار میدهد. همچنین به یک متد دیگر برای برگرداندن لیستی که پر شده نیاز داریم. بنابراین آن تابع را به این صورت تعریف میکنیم:
public LiveData<List<AlbumModel>> getAlbum() { if (albumListLiveData == null) { albumListLiveData = new MutableLiveData<List<AlbumModel>>(); loadList(); } return albumListLiveData; }
یک تابع به نام getAlbum که لیستی LiveData از نوع AlbumModel را برمیگرداند. اگر لیست خالی باشد تابع loadList را فراخوانی میکند و در غیر این صورت لیست را برمیگرداند.
در آخرین مرحله برای اینکه اطلاعات را بگیریم و در RecyclerView نمایش دهیم به نوشتن این تکه کد در کلاس HomeFragment نیاز است:
RetrofitMusicViewModel rmvm = ViewModelProviders.of(getActivity()).get(RetrofitMusicViewModel.class); rmvm.getAlbum().observe(getActivity(), new Observer<List<AlbumModel>>() { @Override public void d(List<AlbumModel> musicModels) { recyclerAlbumAdapter = new RecyclerAlbumAdapter(musicModels, getActivity()); recyclerView.setAdapter(recyclerAlbumAdapter); } });
در این خطوط یک شی از کلاس RetrofitMusicViewModel ایجاد کردیم که با استفاده از ViewModelProviders که یک context دریافت میکند که از متد getActivity استفاده میکنیم (به دلیل اینکه کلاس فرگمنت است و نه اکتیویتی)، و در آخر کلاس RetrofitMusicViewModel را get کرده و در شی rmvm قرار میدهیم.
سپس از شی rmvm استفاده کرده و متد getAlbum که در کلاس ViewModel نوشته بودیم که لیست دریافت شده از سرور را برمیگرداند را صدا زده و observe میکنیم. با تایپ کلمه new و بعد از آن O، اندروید استودیو به شما متد را پیشنهاد میدهد و با زدن اینتر آن را کامل میکند. با زدن اینتر متدی به اسم نوشته میشود. با استفاده از این متد هنگامی که تغییری روی داده ما (لیست musicModels) صورت بگیرد ما مطلع میشویم. در نهایت داخل این متد شی recyclerAlbumAdapter را new کرده و لیستی که observable به ما داده است را به آداپتر ریسایکلر ویو میدهیم. و در نهایت آداپتر را ست میکنیم.
در نهایت صفحه ما به این صورت است:
در این صفحه در فرگمنت اول لیستی از پست ها گرفتیم که عکس های آن ها را با استفاده از کتابخانه Glide دانلود و در ریسایکلر ویو نمایش دادیم.
همانطور که گفته شده بود با کلیک بر روی البوم باید لیست آهنگ های آلبوم در صفحه دیگری ظاهر شود. به همین جهت یک کلاس جاوا و فایل xml دیگری میسازیم.
کد های فایل activity_album.xml:
https://github.com/far7id/Mvvm/blob/master/app/src/main/res/layout/activity_album.xml
همچنین یک آداپتر برای ریسایکلر ویو این صفحه مینویسیم و در متد onBindViewHolder آن این تکه کد را مینویسیم:
musicModel = musicList.get(position); View view = layoutInflater.inflate(R.layout.albums_item, null, false); Glide.with(view.getContext()) .load(musicList.get(position).getPic()) .into(pic); recyclerHolder.itemView.setListener(new View.Listener() { @Override public void (View v) { Intent intent = new Intent(context, AlbumActivity.class); String titlePosition = musicModel.getTitle(); String artistPosition = musicModel.getArtist(); String picPosition = musicList.get(position).getPic(); intent.putExtra("titlePosition", titlePosition); intent.putExtra("artistPosition", artistPosition); intent.putExtra("picPosition", picPosition); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } });
این کلاس مانند آداپتر قبلی است با این تفاوت که در این متد یک رویداد هم نوشتهایم. بنابراین با کلیک بر روی یک آلبوم فیلد های آن گرفته میشود و به وسیله putExtra به اکتیویتی AlbumActivity ارسال میشود.
سپس در کلاس اکتیویتی AlbumActivity که ایجاد کرده بودیم به وسیله Bundle اطلاعات را دریافت میکنیم و روی ویو های مربوطه ست میکنیم.
در نهایت مانند فرگمنت اصلی که طراحی کرده بودیم از ViewModel استفاده و آن را observe میکنیم.
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(AlbumActivity.this); recyclerView.setLayoutManager(layoutManager); RetrofitMusicViewModel rmvm = ViewModelProviders.of(AlbumActivity.this).get(RetrofitMusicViewModel.class); rmvm.getSong().observe(AlbumActivity.this, new Observer<List<SongModel>>() { @Override public void d(List<SongModel> songModels) { recyclerSongAdapter = new RecyclerSongAdapter(songModels, AlbumActivity.this); recyclerView.setAdapter(recyclerSongAdapter); } });
کد های اکتیویتی AlbumActivity:
https://github.com/far7id/Mvvm/blob/master/app/src/main/java/com/example/MvvmDagger/view/ui/Activity/AlbumActivity.java
در نهایت صفحه AlbumActivity به صورت زیر است:
در این پروژه یک نمونه ساده و کاربردی از کار با MVVM تجربه کردیم. همچنین با کامپوننت LiveData آشنا شدیم از آن در یک پروژه استفاده کردیم. هدف از این پروژه آشنایی و درک بیشتر معماری MVVM بود. در نظر داشته باشید که این فقط یک نمونه ساده از پیاده سازی این معماری میباشد و مطمئننا MVVM مباحث بسیار دیگری دارد که با تحقیق و جستجو در اینترنت و تمرین میتوانید از آن ها استفاده کنید.
لینک کد های کامل این پروژه در صفحه گیتهاب من قرار دارد و شما میتوانید به طور کامل از کد های این پروژه استفاده کنید.
https://github.com/far7id/Mvvm
ممنون از وقتی که برای این دوره گذاشتید. امیدوارم این دوره برای شما مفید بوده باشد :)