自定義xUtils框架

来源:https://www.cnblogs.com/tangZH/archive/2018/01/14/8284180.html
-Advertisement-
Play Games

xUtils是基於Afinal開發的目前功能比較完善的一個Android開源框架,最近又發佈了xUtil3.0,在增加新功能的同時又提高了框架的性能。它的功能很強大,但是有時候我們只需要其中的一些功能,如果把整個xUtils引進去沒什麼必要。 下麵我們就講講如何自定義小型的xUtils,只有兩個功能 ...


xUtils是基於Afinal開發的目前功能比較完善的一個Android開源框架,最近又發佈了xUtil3.0,在增加新功能的同時又提高了框架的性能。它的功能很強大,但是有時候我們只需要其中的一些功能,如果把整個xUtils引進去沒什麼必要。

 

下麵我們就講講如何自定義小型的xUtils,只有兩個功能:通過註解找到省去findViewById()和setContentView().

 

一、首先:要自定義兩個註解:

(1)找到activity視圖的註解,即用來省去setContentView()的:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ContentView {
    int value();
}

(2)找到控制項的註解,即用來省去findViewById()的。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ViewInject {
    int value();
}

 

給大家解釋一下,@Target ,@Retentio這種註解叫元註解。

Target的功能就是表明你這個註解是用在什麼地方,它值是一個枚舉類型:

 public enum ElementType {
        /**
         * Class, interface or enum declaration. 用於描述類、介面(包括註解類型) 
         */
        TYPE,
        /**
         * Field declaration. 欄位聲明
         */
        FIELD,
        /**
         * Method declaration. 方法聲明
         */
        METHOD,
        /**
         * Parameter declaration. 參數聲明
         */
        PARAMETER,
        /**
         * Constructor declaration.   構造器聲明
         */
        CONSTRUCTOR,
        /**
         * Local variable declaration.  局部變數
         */
        LOCAL_VARIABLE,
        /**
         * Annotation type declaration. 註釋類型聲明。
         */
        ANNOTATION_TYPE,
        /**
         * Package declaration. 用於描述包
         */
        PACKAGE
    }

 

Retention大概意思是註解的生命周期什麼時候生效。

public enum RetentionPolicy {
        /**
         * Annotation is only available in the source code. 在源文件中有效(指定註解只保留在源文件當中,
編譯成類文件後就把註解去掉;)
*/ SOURCE, /** * Annotation is available in the source code and in the class file, but not * at runtime. This is the default policy. 在class文件中有效,不是在運行時有效(指定註解只保留在源文件和編譯後的class
文件中,當jvm載入類時就把註解去掉)
*/ CLASS, /** * Annotation is available in the source code, the class file and is * available at runtime. 運行時有效 */ RUNTIME }

 

二、我們需要自定義一個工具類,這個工具類裡面可以獲得我們的註解,通過反射來找到我們的View。

public class InjectUtils {
    public static void initContext(Object context) {
        //injectLayout必須在injectView前面,因為必須先找到contentView才能夠找到控制項
        injectLayout(context); //找到contentView
        injectView(context); //找到控制項
    }

    private static void injectView(Object context) {
        Class<?> clazz = context.getClass();
        Field[] fields = clazz.getDeclaredFields();

        for(Field field : fields){
            //獲取註解
            ViewInject viewInject = field.getAnnotation(ViewInject.class);
            //如果上面沒有標明註解
            if (viewInject == null)
                continue;

            //獲取註解裡面的Id
            int valueId = viewInject.value();
            try {
                //用反射調用findViewById()方法
                Method findViewById = context.getClass().getMethod("findViewById",int.class);
                View view = (View) findViewById.invoke(context,valueId);
                //反射訪問私有成員,必須加上這句
                field.setAccessible(true);
                //然後對這個屬性複製
                field.set(context,view);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    private static void injectLayout(Object context) {
        int layoutId = 0;

        //獲得類
        Class<?> clazz = context.getClass();

        //獲得該類聲明的註解
        ContentView contentView = clazz.getAnnotation(ContentView.class);
        //如果該類沒有聲明註解
        if (contentView == null)
        {
            return;
        }

        //獲得註解裡面設置的Id
        layoutId = contentView.value();

        try {
            //利用反射調用setContentView()方法
            Method setContentView = context.getClass().getMethod("setContentView",int.class);
            setContentView.invoke(context,layoutId);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }


}

具體含義請看註釋。

 

三、定義一個BaseActivity

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        InjectUtils.initContext(this);
    }
}

 

四、實現我們的activity

//給該class加上我們自定義的註解,InjectUtils會通過找到
//註解裡面的R.layout.activity_main,然後通過反射調用
//setContentView()方法
@ContentView(R.layout.activity_main) public class MainActivity extends BaseActivity { //給該組件加上我們自定義的註解,InjectUtils會通過找到 //註解裡面的R.id.xx,然後通過反射調用 //findViewById()方法找到控制項 @ViewInject(R.id.text1) private TextView textView1; @ViewInject(R.id.text2) private TextView textView2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); textView1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { textView1.setText("text1"); } }); textView2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { textView2.setText("text2"); } }); } }

 

要註意一點:如果某個註解屬性使用value作為名稱如ContentView中的value,那麼賦值的時候可以直接@ContentView(類的ID),但是如果你使用的是其他名稱,比如下麵這個註解:

public @interface Person
{
  //name是屬性而不是方法,t是它的預設值,在定義的時候可以不用給定預設值
  String name() default t;
}

 那麼必須@Person(name=xx)這樣調用



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • zabbix工具監控伺服器是以組的形式來管理,創建單個被監控伺服器之前需要先創建一個主機組,然後將被監控機添加到這個組中即可 1 創建主機群組: 2 向主機群組中添加主機 3 向主機中添加模板,選擇要監控哪些服務等 4 查看監控的內容以及數據成圖 ...
  • 本章目錄 1.1 Shell,Bash介紹 1.2 內部命令與外部命令 1.3 命令別名 1.4 命令歷史 1.5 Bash快捷鍵 1.1 Shell,Bash介紹 ◆Shell:Linux系統的用戶界面,提供了用戶與內核進行交互操作的一種介面。它接收用戶輸入的命令並把它送入內核去執行。 ◆Bash ...
  • 前言: Linux一般將文件可存取的身份分為三個類別,分別是 owner/group/others,根據許可權劃分,每個目錄都可以擁有相對身份的-rwx[可讀可寫可執行] 使用者與群組: Owner :文件擁有者,如jane擁有此文件所屬權,可對該文件進行相應許可權操作。 Group :文件擁有組,如一 ...
  • 概述 由於目前生產環境的mysql資料庫分佈在兩台伺服器,若從單一主從來看,配置很簡單,但是需要將兩台伺服器的資料庫同步到一臺從庫上面,需要進行更多配置和註意事項。多源複製有兩種方案,Binlog+Position和GTID,我們採用的是第一種方案Binlog+Position進行的多源複製。 安裝 ...
  • select * from scott.dept;select * from scott.emp; --dual 是 Oracle提供的一個虛表select length('hello') from dual; --常用函數--lower把大寫轉小寫 upper把小寫轉大寫select * from ...
  • --註意:rownum和rowid只有Oracle有,其它資料庫是不支持的 select * from scott.dept;--查詢的結果稱為'結果集' --rownum 偽列 '結果集'中產生的序列--在下麵的結果集中deptno為20的rownum為2select rownum,deptno, ...
  • 資料查找https://www.cnblogs.com/tdws/p/5836122.html https://www.cnblogs.com/lori/p/5794454.html private static readonly ConnectionMultiplexer _sentinel; s ...
  • 在看 carthage 時,其中需要配置一個 copy-frameworks 腳本,此腳本特殊的地方,需要手動填寫 Input Files 和 Output Files.一個一個填寫,很糟心~ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...