جایگزینی برای NetworkInfo
شغل خویش را با ساختوساز یک جایگزین NetworkInfo استارت می کنیم که یک شیوه ناهمگام برای اخذ موقعیت اتصال کانال ساختوساز مینماید. بهدنبال طراحی اپلیکیشن در مشهد مثالی از اینترفیس آن را می بینید:
1interface NetworkState {
2 val isConnected: Boolean
3 val network: Network?
4 val networkCapabilities: NetworkCapabilities?
5 val linkProperties: LinkProperties?
6}
اینک بایستی این اینترفیس را پیادهسازی کنیم و مطمئن شویم که مقادیر آن اتصالپذیری دستگاه را رفلکس میدهند:
1internal class NetworkStateImp : NetworkState {
2 override var isConnected: Boolean = false
3 override var network: Network? = null
4 override var linkProperties: LinkProperties? = null
5 override var networkCapabilities: NetworkCapabilities? = null
6}
در حال حاضر میتوانیم از این پیادهسازی باطن NetworkCallback به کار گیری کنیم و وضعیت کانال را داخل آن ذخیره کرده و هر توشه که موقعیت تغییر تحول مییابد بهروزرسانی کنیم:
1internal class NetworkCallbackImp(private val holder: NetworkStateImp) : ConnectivityManager.NetworkCallback() {
2 override fun onAvailable(network: Network) {
3 holder.network = true
4 holder.isConnected = isAvailable
5 }
6 override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
7 holder.networkCapabilities = networkCapabilities
8 }
9 override fun onLost(network: Network) {
10 holder.network = network
11 holder.isConnected = false
12 }
13 override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) {
14 holder.linkProperties = linkProperties
15 }
16 }
مشاهده بدون نقص کدها
براین اساس برنده شدیم خلل را حل کنیم، البته هنوز مواقعی میباشند که می بایست تغییر تحول دهیم:
اولیه آیتم این میباشد که می بایست یک نوبت از NetworkState ساخت کنیم که از هر جایی در نرم افزار و خیر صرفا NetworkStateImp قابل دسترسی باشد. بدین مراد یک شیء صرفا-خواندنی نیاز داریم.
گزینه دوم نحوه استحضاررسانی به هر مورد از طرفین ذینفع درخصوص تغییرو تحول موقعیت اتصالپذیری کانال میباشد.
در غایت گزینه سوم اتصال کلیه این مفاد به NetworkStateImp میباشد.
نکته دوم و سوم چند چاره داراهستند. بعضا ممکن میباشد از یک کانتینر DI استعمال نمایند که از قبلی برای نرم افزار تهیه و تنظیم کردهاند، البته چنانچه بخواهیم تمامی چیز معمولی باشد، قادر خواهیم بود از کد کاتلین ذیل به کارگیری کنیم:
1object NetworkStateHolder : NetworkState {
2
3 private lateinit var holder: NetworkStateImp
4
5 override val isConnected: Boolean
6 get() = holder.isConnected
7 override val network: Network?
8 get() = holder.network
9 override val networkCapabilities: NetworkCapabilities?
10 get() = holder.networkCapabilities
11 override val linkProperties: LinkProperties?
12 get() = holder.linkProperties
13
14 fun Application.registerConnectivityMonitor() {
15 holder = NetworkStateImp()
16 val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
17 connectivityManager.registerNetworkCallback(NetworkRequest.Builder().build(), NetworkCallbackImp(holder))
18 }
19
20}
مشاهده بی نقص کدها
در کد فوق شغل های ذیل را ایفا میدهیم:
Object یک syntactic sugar کاتلین برای تهیه الگوی سینگلتون به حساب می آید.
NetworkStateHolder یک دفعه از NetworkState میباشد، البته مقادیر در مشخصه holder ذخیره گردیدهاند. Holder یک NetworkStateImp و قابل دستکاری، البته سری میباشد و نکته نخستین فوق را برآورده میسازد.
registerConnectivityBroadcaster یک اکستنشن Application میباشد که holder را به callback اتصال میدهد و نکته سوم فوق را برآورده میسازد.
برای فعال سازی تمامی معماری نظارتی کافی میباشد registerConnectivityBroadcaster را به طور تحت فراخوانی کنیم:
1class MainApplication : Application() {
2 override fun onCreate() {
3 super.onCreate()
4 registerConnectivityBroadcaster()
5 }
6}
در حال حاضر صرفا نکته دوم فوق مانده میباشد یعنی تغییرات کانال را منتشر کنیم. یک شیوه دیرین در این زمینه میتواند به کارگیری از نوعی الگوی Broadcaster -> Intent -> Receiver -> Function برای اخذ حادثه ها در اکتیویتیها باشد.
البته قرار وجود ندارد مدام در قبل بمانیم و می بایست استارت به استعمال از راهکارهای جت پک اندروید بکنیم. بهاین مراد میخواهیم از کامپوننتهای معماری سود بگیریم.
به کارگیری از نوعی LiveData
ما با استعمال از LiveData نکته فوق فهرست اشتباهات فوق را که پیشخیس ارائه کردیم حل می کنیم، یعنی رویدادهای اتصالپذیری را به سایر قسمتهای نرم افزار استحضاررسانی می کنیم. آغاز بایستی بعضا حادثه ها را تعریف و تمجید کنیم. در این باره نیز از کد کاتلین به کار گیری میکنیم:
1sealed class Event {
2
3 val networkState: NetworkState = NetworkStateHolder
4
5 object ConnectivityLost : Event()
6 object ConnectivityAvailable : Event()
7 data class NetworkCapabilityChanged(val old: NetworkCapabilities?) : Event()
8 data class LinkPropertyChanged(val old: LinkProperties?) : Event()
9}
در کد معمولی فوق تعدادی سرمشق تعریفوتمجید گردیدهاند:
کلیک فرمایید
Enumeration – کلاس sealed قابلیت گروه محدودی از گونه های بر پایه ی Event را مهیا میسازد که همگی آن ها باطن event قرار داراهستند و خواندشان راحت میباشد.
Polymorphism – هر دفعه از Event یک شرایط کانال را محافظت مینماید، البته بعضا دادههای خاص مربوط به تغییر تحول صورت داده نیز ذخیره نموده است.
Abstraction – در شرایطیکه هیچ دادههای مایحتاج نباشد، میتوانیم تنهاً از نوع برای مدیر روی داد استعمال کنیم که دقیقاً شبیه مدیر likeException میباشد. این شرایط در خصوص ConnectivityLost و ConnectivityAvailable مصداق دارااست. همینطور برای آسانی بیشتر به کارگیری از object/singletons مصرف شده میباشد.
به فولدرهای تحت دقت فرمائید:
فولدر NetworkEvents.kt
1object NetworkEvents : LiveData() {
2 internal fun notify(event: Event) {
3 postValue(event)
4 }
5}
فولدر NetworkStateImp.kt
1internal class NetworkStateImp : NetworkState {
2 override var network: Network? = null
3
4 override var isConnected: Boolean = false
5 set(value) {
6 field = value
7 NetworkEvents.notify(if (value) Event.ConnectivityAvailable else Event.ConnectivityLost)
8 }
9 override var linkProperties: LinkProperties? = null
10 set(value) {
11 val event = Event.LinkPropertyChanged(field)
12 field = value
13 NetworkEvents.notify(event)
14 }
15
16 override var networkCapabilities: NetworkCapabilities? = null
17 set(value) {
18 val event = Event.NetworkCapabilityChanged(field)
19 field = value
20 NetworkEvents.notify(event)
21 }
22}
مشاهده بدون نقص کدها
در حال حاضر مفاد ذیل را داریم:
NetworkEvents یک LiveData میباشد و با به کار گیری از NetworkEvents.observe(lifecycleowner, observer) میقدرت آن را از هر LifeCycleOwner روءیت کرد. همینطور میقدرت از هر مکانی که دارنده NetworkEvents.observeForever(observer) باشد آن را روءیت کرد.
Notify تابعی میباشد که برای ارسال رویدادهای تازه به کار گیری می گردد. در NetworkHolderImp که پیش از اینً ارائه کردیم با اضافه کردن یک setter که NetworkEvents.notify را فراخوانی مینماید، میتوانیم هر چیزی که تغییر تحول یافته را به اگاهی کلیه observer-ها برسانیم.
صحبت آخری
احتمالاً درین نوشته ی علمی برخی کلیدواژههای internal را در اولِ کلاسها و مشخصهها دیدید. خواسته از آن این میباشد که صرفا از باطن ماژول قابل مشاهده می باشند. به ذکر خلاصه کد را در ماژول خاص خویش قرار میدهیم و نمایانی آن را به کلاسهای خودمان محصور میکنیم. برای مشاهده کد بی نقص این پروژه می توانید بهاین رپیوی گیتهاب (+) بروید.
جایگزینی برای NetworkInfo
شغل خویش را با ساختوساز یک جایگزین NetworkInfo استارت می کنیم که یک شیوه ناهمگام برای اخذ موقعیت اتصال کانال ساختوساز مینماید. بهدنبال طراحی اپلیکیشن در مشهد مثالی از اینترفیس آن را می بینید:
1interface NetworkState {
2 val isConnected: Boolean
3 val network: Network?
4 val networkCapabilities: NetworkCapabilities?
5 val linkProperties: LinkProperties?
6}
اینک بایستی این اینترفیس را پیادهسازی کنیم و مطمئن شویم که مقادیر آن اتصالپذیری دستگاه را رفلکس میدهند:
1internal class NetworkStateImp : NetworkState {
2 override var isConnected: Boolean = false
3 override var network: Network? = null
4 override var linkProperties: LinkProperties? = null
5 override var networkCapabilities: NetworkCapabilities? = null
6}
در حال حاضر میتوانیم از این پیادهسازی باطن NetworkCallback به کار گیری کنیم و وضعیت کانال را داخل آن ذخیره کرده و هر توشه که موقعیت تغییر تحول مییابد بهروزرسانی کنیم:
1internal class NetworkCallbackImp(private val holder: NetworkStateImp) : ConnectivityManager.NetworkCallback() {
2 override fun onAvailable(network: Network) {
3 holder.network = true
4 holder.isConnected = isAvailable
5 }
6 override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
7 holder.networkCapabilities = networkCapabilities
8 }
9 override fun onLost(network: Network) {
10 holder.network = network
11 holder.isConnected = false
12 }
13 override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) {
14 holder.linkProperties = linkProperties
15 }
16 }
مشاهده بدون نقص کدها
براین اساس برنده شدیم خلل را حل کنیم، البته هنوز مواقعی میباشند که می بایست تغییر تحول دهیم:
اولیه آیتم این میباشد که می بایست یک نوبت از NetworkState ساخت کنیم که از هر جایی در نرم افزار و خیر صرفا NetworkStateImp قابل دسترسی باشد. بدین مراد یک شیء صرفا-خواندنی نیاز داریم.
گزینه دوم نحوه استحضاررسانی به هر مورد از طرفین ذینفع درخصوص تغییرو تحول موقعیت اتصالپذیری کانال میباشد.
در غایت گزینه سوم اتصال کلیه این مفاد به NetworkStateImp میباشد.
نکته دوم و سوم چند چاره داراهستند. بعضا ممکن میباشد از یک کانتینر DI استعمال نمایند که از قبلی برای نرم افزار تهیه و تنظیم کردهاند، البته چنانچه بخواهیم تمامی چیز معمولی باشد، قادر خواهیم بود از کد کاتلین ذیل به کارگیری کنیم:
1object NetworkStateHolder : NetworkState {
2
3 private lateinit var holder: NetworkStateImp
4
5 override val isConnected: Boolean
6 get() = holder.isConnected
7 override val network: Network?
8 get() = holder.network
9 override val networkCapabilities: NetworkCapabilities?
10 get() = holder.networkCapabilities
11 override val linkProperties: LinkProperties?
12 get() = holder.linkProperties
13
14 fun Application.registerConnectivityMonitor() {
15 holder = NetworkStateImp()
16 val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
17 connectivityManager.registerNetworkCallback(NetworkRequest.Builder().build(), NetworkCallbackImp(holder))
18 }
19
20}
مشاهده بی نقص کدها
در کد فوق شغل های ذیل را ایفا میدهیم:
Object یک syntactic sugar کاتلین برای تهیه الگوی سینگلتون به حساب می آید.
NetworkStateHolder یک دفعه از NetworkState میباشد، البته مقادیر در مشخصه holder ذخیره گردیدهاند. Holder یک NetworkStateImp و قابل دستکاری، البته سری میباشد و نکته نخستین فوق را برآورده میسازد.
registerConnectivityBroadcaster یک اکستنشن Application میباشد که holder را به callback اتصال میدهد و نکته سوم فوق را برآورده میسازد.
برای فعال سازی تمامی معماری نظارتی کافی میباشد registerConnectivityBroadcaster را به طور تحت فراخوانی کنیم:
1class MainApplication : Application() {
2 override fun onCreate() {
3 super.onCreate()
4 registerConnectivityBroadcaster()
5 }
6}
در حال حاضر صرفا نکته دوم فوق مانده میباشد یعنی تغییرات کانال را منتشر کنیم. یک شیوه دیرین در این زمینه میتواند به کارگیری از نوعی الگوی Broadcaster -> Intent -> Receiver -> Function برای اخذ حادثه ها در اکتیویتیها باشد.
البته قرار وجود ندارد مدام در قبل بمانیم و می بایست استارت به استعمال از راهکارهای جت پک اندروید بکنیم. بهاین مراد میخواهیم از کامپوننتهای معماری سود بگیریم.
به کارگیری از نوعی LiveData
ما با استعمال از LiveData نکته فوق فهرست اشتباهات فوق را که پیشخیس ارائه کردیم حل می کنیم، یعنی رویدادهای اتصالپذیری را به سایر قسمتهای نرم افزار استحضاررسانی می کنیم. آغاز بایستی بعضا حادثه ها را تعریف و تمجید کنیم. در این باره نیز از کد کاتلین به کار گیری میکنیم:
1sealed class Event {
2
3 val networkState: NetworkState = NetworkStateHolder
4
5 object ConnectivityLost : Event()
6 object ConnectivityAvailable : Event()
7 data class NetworkCapabilityChanged(val old: NetworkCapabilities?) : Event()
8 data class LinkPropertyChanged(val old: LinkProperties?) : Event()
9}
در کد معمولی فوق تعدادی سرمشق تعریفوتمجید گردیدهاند:
کلیک فرمایید
Enumeration – کلاس sealed قابلیت گروه محدودی از گونه های بر پایه ی Event را مهیا میسازد که همگی آن ها باطن event قرار داراهستند و خواندشان راحت میباشد.
Polymorphism – هر دفعه از Event یک شرایط کانال را محافظت مینماید، البته بعضا دادههای خاص مربوط به تغییر تحول صورت داده نیز ذخیره نموده است.
Abstraction – در شرایطیکه هیچ دادههای مایحتاج نباشد، میتوانیم تنهاً از نوع برای مدیر روی داد استعمال کنیم که دقیقاً شبیه مدیر likeException میباشد. این شرایط در خصوص ConnectivityLost و ConnectivityAvailable مصداق دارااست. همینطور برای آسانی بیشتر به کارگیری از object/singletons مصرف شده میباشد.
به فولدرهای تحت دقت فرمائید:
فولدر NetworkEvents.kt
1object NetworkEvents : LiveData() {
2 internal fun notify(event: Event) {
3 postValue(event)
4 }
5}
فولدر NetworkStateImp.kt
1internal class NetworkStateImp : NetworkState {
2 override var network: Network? = null
3
4 override var isConnected: Boolean = false
5 set(value) {
6 field = value
7 NetworkEvents.notify(if (value) Event.ConnectivityAvailable else Event.ConnectivityLost)
8 }
9 override var linkProperties: LinkProperties? = null
10 set(value) {
11 val event = Event.LinkPropertyChanged(field)
12 field = value
13 NetworkEvents.notify(event)
14 }
15
16 override var networkCapabilities: NetworkCapabilities? = null
17 set(value) {
18 val event = Event.NetworkCapabilityChanged(field)
19 field = value
20 NetworkEvents.notify(event)
21 }
22}
مشاهده بدون نقص کدها
در حال حاضر مفاد ذیل را داریم:
NetworkEvents یک LiveData میباشد و با به کار گیری از NetworkEvents.observe(lifecycleowner, observer) میقدرت آن را از هر LifeCycleOwner روءیت کرد. همینطور میقدرت از هر مکانی که دارنده NetworkEvents.observeForever(observer) باشد آن را روءیت کرد.
Notify تابعی میباشد که برای ارسال رویدادهای تازه به کار گیری می گردد. در NetworkHolderImp که پیش از اینً ارائه کردیم با اضافه کردن یک setter که NetworkEvents.notify را فراخوانی مینماید، میتوانیم هر چیزی که تغییر تحول یافته را به اگاهی کلیه observer-ها برسانیم.
صحبت آخری
احتمالاً درین نوشته ی علمی برخی کلیدواژههای internal را در اولِ کلاسها و مشخصهها دیدید. خواسته از آن این میباشد که صرفا از باطن ماژول قابل مشاهده می باشند. به ذکر خلاصه کد را در ماژول خاص خویش قرار میدهیم و نمایانی آن را به کلاسهای خودمان محصور میکنیم. برای مشاهده کد بی نقص این پروژه می توانید بهاین رپیوی گیتهاب (+) بروید.

راهکارهای کاهش CPC در کمپینها