iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0
Mobile Development

Android Studio 30天進階學習系列 第 6

Android Studio 30天進階學習-DAY06_Dagger2_04(架構實作_下)

  • 分享至 

  • xImage
  •  

今天要來補完剩下的一些註解標籤。

@Component.Builder和@BindsInstance

  • @Component.Builder
    @Component.Builder 是一個標記型的接口注解,用於指示 Dagger 2 生成一個 Builder 類來建立相應的 Component 實例,也就是前面都是由Dagger2自己產生的Builder去建立,這邊我們用了@Component.Builder標籤去建立一個自訂義的Builder接口

它通常與 Dagger 2@Component 注解一起使用,以自定義 Component 建立過程。

在這當中允許我們自己新增一些自訂義的功能去延伸。

  • @BindsInstance
    @BindsInstanceDagger 2 中的一個方法注解,用於將特定的實例或值綁定到 Dagger 2Component 中。這允許我們在 Component 建立過程中將自定義的實例或值提供給 Dagger 2,以便在依賴注入過程中使用。

@BindsInstance 這個註解標籤是 Dagger 2 中可用於向 Component 傳遞特定的實例或值,以滿足不同的依賴注入需求。這是設計更具靈活性和可擴展性的應用程式架構的重要元素之一。

程式碼

這邊我就直上程式碼就不再進行詳解了,只會放上與昨天對比有改動的部分。

  • StateSchool
    這邊的程式碼大致改動如下:
    1. 添加score參數傳入。
    2. 透過Dagger的架構取得方法後log出來。
public class State_School implements School{
    // 公立&國立學校\
    private static final String TAG = "State_School";
    private int score;

    @Inject
    public State_School(int score) {
        this.score = score;
    }

    @Override
    public void buildSchoolType() {
        Log.e(TAG, "buildSchoolType: "+TAG+"\nscore: "+score);

    }
}
  • SchoolComponent
@Singleton
@Component(modules = {StudentModule.class,
                    TeacherModule.class,
                    StateSchoolModule.class})
public interface SchoolComponent {
    // 以上內容無更改

    // 添加以下的程式碼做自訂義Builder。
    @Component.Builder
    interface Builder{
        @BindsInstance
        Builder score(int score);

        SchoolComponent build();
    }
}
  • MainActivity
    這邊在修改並build的時候也如同前面剛開始建立時的步驟一致。
    1. 先以SchoolComponent schoolComponent;的格式才能完成建立並取得在Component中創建的自訂義Builder。
public class MainActivity extends AppCompatActivity {

    @Inject
    EducationSystem educationSystem01, educationSystem02;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 修改Builder。
        SchoolComponent schoolComponent = DaggerSchoolComponent.builder()
                .score(985)
                .build();

        schoolComponent.inject(this);

        educationSystem01.start();
        educationSystem02.start();
    }
}

結果截圖

https://ithelp.ithome.com.tw/upload/images/20230916/20150370eKzeXqnx9J.png

@Named

這個標籤簡單來說就是當有兩個相同的類要綁定就可能會需要@Named標籤來做區分。
錯誤訊息我放到最後面再來說明,這邊先繼續開始修改。

  • 添加修改的步驟如下:
    1. 先添加String型態的Name作為校名
    2. 然後再到Component添加name並與上面建立的score一致的格式。
    3. 回到Acitivity進行Build並加入Name,這時會發現好像沒有錯誤,這是因為score是int型態、然後name是String型態,並且Builder這邊並沒有出現複數綁定的問題。
    4. 接著按照同樣的步驟新增'worldRanking'並設定為int型態。
    5. 當Component建立好後按下build會迸出一個錯誤,如最下方的(圖1.)一樣。
    6. 最後添加完成@Named註解標籤後就成功了。

程式碼

這邊與上面一樣我就只放有修改的部分。

  • StateSchool
public class State_School implements School{
    private int score;
    private String name;
    private int worldRanking;
    
    @Inject
    public State_School(@Named("score")int score, String name, @Named("worldRanking") int worldRanking) {
        this.score = score;
        this.name = name;
        this.worldRanking = worldRanking;
    }

    @Override
    public void buildSchoolType() {
        Log.e(TAG, "buildSchoolType: "+TAG+"\nscore: "+score+"\nname: "+name+"\nworldRanking: "+worldRanking);
    }
}
  • SchoolComponent
@Singleton
@Component(modules = {StudentModule.class,
                    TeacherModule.class,
                    StateSchoolModule.class})
public interface SchoolComponent {
    School getSchool();
    void inject(MainActivity mainActivity);

    @Component.Builder
    interface Builder{
        @BindsInstance
        Builder score(@Named("score") int score);

        @BindsInstance
        Builder worldRanking(@Named("worldRanking") int worldRanking);

        @BindsInstance
        Builder name(String name);

        SchoolComponent build();
    }
}
  • MainActivity
public class MainActivity extends AppCompatActivity {

    @Inject
    EducationSystem educationSystem01, educationSystem02;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SchoolComponent schoolComponent = DaggerSchoolComponent.builder()
                .score(700)
                .name("清華大學")
                .worldRanking(233)
                .build();

        schoolComponent.inject(this);

        educationSystem01.start();
        educationSystem02.start();
    }
}

最終結果截圖

https://ithelp.ithome.com.tw/upload/images/20230916/20150370JTfv8OgQkP.png

@Named建立的注意事項

https://ithelp.ithome.com.tw/upload/images/20230916/20150370giGPw5awGY.png
這個錯誤訊息是 Dagger 2 中的一個編譯錯誤,它表示在你的 Dagger 2 的Component:SchoolComponent中存在重複的綁定(bindings)。

由上方的錯誤訊息指出了兩次綁定了 Integer 型態的物件:

  • 第一次綁定是在 SchoolComponent.Builder 的 score(int) 方法上使用 @BindsInstance 標籤註解。
  • 第二次綁定是在 SchoolComponent.Builder 的 worldRanking(int) 方法上使用 @BindsInstance 標籤註解。

這邊解決的方法有在旁邊加入@Named標籤註解以供Dagger辨別。

以上是今天包含了@Component.Builder@BindsInstance@Named的註解標籤添加說明與實作內容修改。/images/emoticon/emoticon06.gif


上一篇
Android Studio 30天進階學習-DAY05_Dagger2_03(架構實作_中)
下一篇
Android Studio 30天進階學習-DAY07_DataBinding的介紹
系列文
Android Studio 30天進階學習30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言