日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《撸代码 学习 IOC注入技术1 》—— 布局注入 与 控件注入

發(fā)布時間:2024/1/18 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《撸代码 学习 IOC注入技术1 》—— 布局注入 与 控件注入 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

不詩意的女程序媛不是好廚師~
轉載請注明出處,From李詩雨—https://blog.csdn.net/cjm2484836553/article/details/104539874

【源代碼下載地址】:https://github.com/junmei520/iocStudy

《擼代碼 學習 IOC注入技術1 》—— 布局注入 與 控件注入

  • 1.概念再理解
  • 2.布局注入
  • 3.控件注入

在前面的文章中我們已經學習了 依賴注入與控制反轉的概念、注解、和反射 ,有了這些知識做鋪墊,我們就可以 更加深入的來學習一下 IOC注入技術了。

今天我們主要 來學習運行時注入,并親自擼代碼來一步一步的實現 布局注入控件注入

文章的邏輯思路講的很細,也很好懂,沒有什么難點,并且文章篇幅也不長,不妨一讀哦~

1.概念再理解

溫故而知新,上篇文章中跟大家提到了 控制反轉(IOC) 和 依賴注入的概念,可能大家還是有點 花非花霧非霧的 感覺,今天經過親自的擼代碼之后,我有了新的體會。在此與大家分享~

【控制反轉(IOC)】:是原來由程序代碼中主動獲取的資源,轉變由第三方獲取并使原來的代碼被動接收的方式,以達到解耦的效果。

按照上篇文章的內容,我們把它看成是一種控制權的反轉。

但其實,我們還可以把它看成是一種義務的轉交,即 把我們自己應該做的事轉交給別人來做,從而讓自己變得更輕松。

再舉個形象的栗子來說吧:

在一個月黑風高的寒冷的夜晚,你有事要出門,由于天氣太冷你要披肩大棉襖才能出去,于是你就自己乖乖的拿了棉襖再乖乖的穿好出門,消失在寒冷的黑夜中。

IOC就是你有了一個女朋友,你只告訴她你要出門,于是貼心的女朋友便給你拿來棉衣,幫你穿上,才放心讓你出門。于是你在愛的目光中出了門~

恩,女朋友就好比IOC,把你本來要拿衣服穿衣服的事情 轉交給了女朋友來做。

畫個圖來幫助大家理解:

好的,現在我們就開始擼代碼來學習 IOC注入技術吧~

2.布局注入

我們都知道在Activity中我們 通過自己的 setContentView(R.layout.activity_main)來加入、顯示布局的。

那如果我現在采用ioc,不是自己來注入布局,而是讓我的女朋友來注入布局,該怎么做呢?

  • ①首先,我得造一個女朋友出來!她里面有布局注入的方法。
  • ②其次,我們考慮到可能所有的Activity都要用到,所以,我們在BaseActivity的onCreat中完成注入。
  • ③MainActivity繼承BaseActivity。并且把setContentView(R.layout.activity_main)這句代碼去掉!
//①造了一個女朋友 public class InjectUtils {public static void inject(Object context) {//布局的注入injectLayout(context);}private static void injectLayout(Object context) {} } public class BaseActivity extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);InjectUtils.inject(this);//②在這里注入} } //③繼承BaseActivity ,并去掉setContentView(R.layout.activity_main)這句代碼 public class MainActivity extends BaseActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//setContentView(R.layout.activity_main);//把這行代碼去掉!讓女朋友來完成} }

好的,到這里大家應該都沒有什么問題吧。

現在大家想想,我們既然去掉了setContentView(R.layout.activity_main);這句代碼,那此時我們的MainActivity是不知道需要哪個布局的。

這該怎么辦?怎么才能知道MainActivity需要哪個布局文件呢?

那我們就要標識出來我們所需要的布局文件呀,那怎么標識呢?

對!用注解。就像這樣:

那接下來我們就要來自定義這個注解啦~

  • ④自定義注解MyContentView。
//④自定義注解MyContentView @Target(ElementType.TYPE) //表明:注解將來是使用在類上面的 @Retention(RetentionPolicy.RUNTIME) //表明注解的存活周期,我們希望可以在運行時讀取到它的信息 public @interface MyContentView {int value(); }

好了,到目前為止,我們的主要邏輯就完成了。但是,此時運行還是不能加載出布局的,因為這還是個假貨,我們InjectUtils中的injectLayout()還是空的,里面什么都沒有做。

所以,接下來我們的重點就是實現injectLayout()方法了。

⑤實現injectLayout()方法:

我們先來分析一下,在該方法中我們要做什么:

首先我們要明確的是,此處我們肯定要 運用反射 去獲取所需信息和執(zhí)行對應方法了。

  • 第一步 獲取activity對應的Class
  • 第二步 拿到該Class上的MyContentView注解
  • 第三步 取到注解括號后面的內容,即布局id

再接下來 就要 反射在class上去執(zhí)行setContentView了:

  • 第四步 利用反射獲取setContentView()對應的method
  • 第五步 反射執(zhí)行setContentView()方法。
//⑤實現injectLayout()方法 private static void injectLayout(Object context) {// a.獲取到Activity對應的ClassClass<?> clazz = context.getClass();// b.拿到該Class上的MyContentView注解MyContentView myContentView = clazz.getAnnotation(MyContentView.class);if (myContentView != null) { //如果有MyContentView注解就執(zhí)行以下操作// c.取到注解括號后面的內容,即布局idint layoutId = myContentView.value();//====== 接下來就要 反射去執(zhí)行setContentViewtry {// d.利用反射獲取setContentView()對應的methodMethod method = clazz.getMethod("setContentView", int.class);// e.反射執(zhí)行setContentView()方法。即相當于context.method(layoutId);method.invoke(context, layoutId);} catch (Exception e) {e.printStackTrace();}} }

好的,那現在我來運行程序,如果可以正常顯示出來布局是不是就可以證明,我注入布局成功啦!

先給大家看一下我的布局文件:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="10dp"tools:context=".MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"android:text="ioc注入技術,哈哈哈~" /><Buttonandroid:id="@+id/button1"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="按鈕1" /><Buttonandroid:id="@+id/button2"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="按鈕2" /></LinearLayout>

好的,下面就是見證奇跡的時刻啦:

成功啦!我成功啦,啊哈哈哈哈~

完成了布局注入,那我們下面繼續(xù)控件注入吧~

3.控件注入

上面我們的布局已經注入成功,并且可以正常顯示了。

我們可以看到布局中有2個按鈕,那如果我想把這兩個按鈕注入該怎么辦呢?

即:我現在不想自己通過findViewById來注入按鈕,而是想讓我的【ioc女朋友】來幫我實現按鈕的注入~

我們先來看一下我的預期想達到的效果:

那要達到這種效果我們該怎么實現呢?

有了布局注入的經驗,相信對于 控件注入 大家還是會有大體的思路的:

我們還用之前的女朋友InjectUtils,還是在BaseActivity中進行注入。

那我們就要在InjectUtils里添加一個控件注入的方法injectView():

現在我們既然不想自己使用findViewById來獲取控件,而是想用這種形式來注入控件:

那我們肯定還是要通過使用注解,并且在注解后面?zhèn)魅雽丶膇d。

所以第①步,我們要自定義一個BindView注解:

//① 自定義一個BindView注解 @Target(ElementType.FIELD) //說明該注解是用在屬性上的 @Retention(RetentionPolicy.RUNTIME)//該注解可以保留到程序運行的時候 public @interface BindView {int value(); }

第②步,具體實現injectView()方法。

實現injectView()方法是重點,讓我們來仔細分析一下思路:

  • 首先,我們肯定還是要通過反射,所以要先拿到Activity對應的Class.
  • 拿到了clazz后,我們還要拿到clazz上的所有屬性字段(Fields)。▲▲▲
  • 然后我們就要循環(huán)遍歷屬性,看屬性上是否有BindView注解。
  • 如果屬性上確實拿到了BindView注解,那我們就要繼續(xù)拿到注解后面的viewId了。
  • 再接著就是反射執(zhí)行findViewById方法,得到對應的view.
  • 最后要注意,對于私有屬性,無論是對它進行讀寫,都要調用field.setAccessible(true)。▲
private static void injectView(Object context) {//獲取clazzClass<?> clazz = context.getClass();//獲取clazz上的所有屬性Field[] fields = clazz.getDeclaredFields();//循環(huán)遍歷每一個屬性for (Field field : fields) {//獲取屬性上的BindView注解BindView bindView = field.getAnnotation(BindView.class);if (bindView != null) {//如果該屬性上找到了BindView注解//拿到注解后面的viewIdint viewId = bindView.value();//運行到這里,每個按鈕的ID已經取到了//下面就是反射執(zhí)行findViewById方法try {Method method = clazz.getMethod("findViewById", int.class);View view = (View) method.invoke(context, viewId);//對 field 做相關操作//注意:如果獲取的字段是私有的,不管是讀還是寫,都要先 field.setAccessible(true);才可以。否則會報:IllegalAccessException。field.setAccessible(true);field.set(context, view);} catch (Exception e) {e.printStackTrace();}}} }

好的,現在我們控件注入的相關操作就完成了,那讓我們來改個button的名稱測試一下吧:

@MyContentView(R.layout.activity_main) public class MainActivity extends BaseActivity {@BindView(R.id.button1)Button btn1;@BindView(R.id.button2)Button btn2;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//檢測 控件注入 是否成功btn1.setText("我是注入的按鈕01");btn2.setText("我是注入的按鈕02");} }

下面還是見證奇跡的時刻:

怎么樣是不是不擼不知道,一擼代碼才知道原來這就是IOC技術啊,也蠻容易的嘛~

是的,布局注入和控件注入我們都輕松搞定啦。

還有一個事件注入我們沒有實現,這個事件注入就會有點小難度了喲。

害怕文檔太長,大家懶得看(PS:其實是因為我懶),

那我們就在下篇繼續(xù)來擼代碼一步一步實現 事件注入 吧~~~

【源代碼下載地址】:https://github.com/junmei520/iocStudy

積累點滴,做好自己~

總結

以上是生活随笔為你收集整理的《撸代码 学习 IOC注入技术1 》—— 布局注入 与 控件注入的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。