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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android -- 带你从源码角度领悟Dagger2入门到放弃(一)

發(fā)布時(shí)間:2024/1/17 Android 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android -- 带你从源码角度领悟Dagger2入门到放弃(一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1,以前的博客也寫了兩篇關(guān)于Dagger2,但是感覺自己使用的時(shí)候還是云里霧里的,更不談各位來看博客的同學(xué)了,所以今天打算和大家再一次的入坑試試,最后一次了,保證最后一次了。

2,接入項(xiàng)目

? ? 在項(xiàng)目的Gradle添加如下代碼

dependencies {classpath 'com.android.tools.build:gradle:2.3.0'// 添加android-apt 插件classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'}

  在app中的Gradle中添加導(dǎo)入

// 應(yīng)用插件apply plugin: 'com.neenbedankt.android-apt'// dagger 2 的配置compile 'com.google.dagger:dagger:2.4'apt 'com.google.dagger:dagger-compiler:2.4'compile 'org.glassfish:javax.annotation:10.0-b28'// 添加java 注解庫(kù)

  簡(jiǎn)單的注解標(biāo)簽的介紹,由于之前寫過一篇博客和大家思考過為什么使用Dagger2(它這么難使用為什么還要使用!!),并且還有一些常見注解標(biāo)簽的使用,所以這里就不和大家廢話這么引入了,直接上干貨

@Inject Inject主要有兩個(gè)作用,一個(gè)是使用在構(gòu)造函數(shù)上,通過標(biāo)記構(gòu)造函數(shù)讓Dagger2來使用(Dagger2通過Inject標(biāo)記可以在需要這個(gè)類實(shí)例的時(shí)候來找到這個(gè)構(gòu)造函數(shù)并把相關(guān)實(shí)例new出來)從而提供依賴,另一個(gè)作用就是標(biāo)記在需要依賴的變量讓Dagger2為其提供依賴。@Provide 用Provide來標(biāo)注一個(gè)方法,該方法可以在需要提供依賴時(shí)被調(diào)用,從而把預(yù)先提供好的對(duì)象當(dāng)做依賴給標(biāo)注了@Injection的變量賦值。provide主要用于標(biāo)注Module里的方法@Module 用Module標(biāo)注的類是專門用來提供依賴的。有的人可能有些疑惑,看了上面的@Inject,需要在構(gòu)造函數(shù)上標(biāo)記才能提供依賴,那么如果我們需要提供的類構(gòu)造函數(shù)無法修改怎么辦,比如一些jar包里的類,我們無法修改源碼。這時(shí)候就需要使用Module了。Module可以給不能修改源碼的類提供依賴,當(dāng)然,能用Inject標(biāo)注的通過Module也可以提供依賴@Component Component一般用來標(biāo)注接口,被標(biāo)注了Component的接口在編譯時(shí)會(huì)產(chǎn)生相應(yīng)的類的實(shí)例來作為提供依賴方和需要依賴方之間的橋梁,把相關(guān)依賴注入到其中。@Singleton 該注解就是通過@scope定義的注解,一般用于提供全局單例。

   現(xiàn)在在實(shí)際場(chǎng)景中有這種情況,存在學(xué)生在老師的課堂上上課,那么一個(gè)學(xué)生可能存在多個(gè)老師,而一個(gè)老師也可能存在多個(gè)學(xué)生。這里我們?yōu)榱朔奖憬忉?#xff0c;就直接轉(zhuǎn)換成1對(duì)1的模式即一個(gè)學(xué)生只有一個(gè)老師,一個(gè)老師只有一個(gè)學(xué)生,然我們來看看轉(zhuǎn)換成我們的java對(duì)象是什么樣的,首先創(chuàng)建學(xué)生實(shí)體類

  Student.java

public class Student {private int id;private String name;private Course[] course;public Student() {System.out.println("Student create!!!");}public Student(int id, String name, Course[] course) {this.id = id;this.name = name;this.course = course;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Course[] getCourse() {return course;}public void setCourse(Course[] course) {this.course = course;}public void startLessons() {System.out.println("開始上課了");} }

  我們的學(xué)生有一些基本的屬性,如id、姓名、所學(xué)的課程,還有上課的動(dòng)作。再看看我們創(chuàng)建老師類

public class Teacher {Student student;public Teacher() {student = new student();}public void teacher() {student.startLessons();} }

  這里我們就有一個(gè)問題了,我們老師類中需要一個(gè)學(xué)生的對(duì)象,而按照以前的方法我們肯定是在老師的構(gòu)造方法中傳遞學(xué)生對(duì)象,毫無疑問肯定是new Student創(chuàng)建學(xué)生對(duì)象的,這里我們要使用Dagger2來代替(至于為什么要使用Dagger2代替,和代替之后有什么好處我以前寫過,這里就不和大家廢話了)

  首先在確定是我們Teacher類中的student屬性需要Student對(duì)象,所以添加@Inject注解標(biāo)簽

@InjectStudent student;

  而我們Dagger2要知道到底我是調(diào)用那個(gè)構(gòu)造函數(shù)來創(chuàng)建Student對(duì)象啊,所以要在Student類中構(gòu)造函數(shù)中添加@Inject標(biāo)簽,標(biāo)明你Dagger2是要在這個(gè)構(gòu)造方法里面創(chuàng)建的

public class Student {private int id;private String name;private Course[] course;@Injectpublic Student() {System.out.println("Student create!!!");}public Student(int id, String name, Course[] course) {this.id = id;this.name = name;this.course = course;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Course[] getCourse() {return course;}public void setCourse(Course[] course) {this.course = course;}public void startLessons() {System.out.println("開始上課了");} }

  然后我們 Student中對(duì)象被創(chuàng)建了,而我們Teacher中需要這個(gè)student對(duì)象,這時(shí)候我們差一個(gè)橋梁來鏈接這兩個(gè)類,從而讓我們被創(chuàng)建的student對(duì)象運(yùn)送到需要它的地方,所以現(xiàn)在我們需要使用@Component標(biāo)簽,來修飾我們自定義的一個(gè)接口,創(chuàng)建TeacherComponent接口,并使用@Component注解標(biāo)簽修飾,創(chuàng)建inject方法(這里很多看過不少Dagger2文章的同學(xué)坑定會(huì)有疑問,這里的inject是固定方法名嗎,能不能使用injectA啊之類的,先把問題留著,我們后面再講)

package com.qianmo.rxjavatext;import dagger.Component;/*** Created by Administrator on 2017/4/20 0020.* E-Mail:543441727@qq.com*/ @Component public interface TeacherComponent {void inject(Teacher teacher); }

  再在我們Teacher類中初始化

public Teacher() {DaggerTeacherComponent.builder().build().inject(this);}

  這時(shí)候可能有同學(xué)又有疑問了,DaggerTeacherComponent這個(gè)類怎么報(bào)錯(cuò)啊 ,其實(shí)這個(gè)類是編譯時(shí)產(chǎn)生的類大家不用慌,把代碼寫完了crtl+F9編譯一下就可以了,但是!!!這里DaggerTeacherComponent的書寫方法是Dagger加上你前面自定義的Component接口類的類名,一定要注意,不然很多同學(xué)都會(huì)在這翻車(我曾經(jīng)在這兒翻出無數(shù)次),然后再說一下我們上一個(gè)問題?TeacherComponent 中的inject方法是固定方法嗎?很明顯這里調(diào)用的是inject(this);所以不是固定方法,只不過你Component接口類寫成injectA(Teacher teacher),那么你這里調(diào)用的方法就是injectA(this)

  ok,上面這些都寫好了,我們?cè)赥eacher類中添加測(cè)試類來測(cè)試測(cè)試

public class Teacher {//想持有學(xué)生對(duì)象@InjectStudent student;public Teacher() {DaggerTeacherComponent.builder().build().injectA(this);}public void teacher() {student.startLessons();}public static void main(String[] args) {new Teacher().teacher();} }

  看一下打印效果

Student create!!! 開始上課了

3,源碼分析

  ok,沒什么問題,那我們現(xiàn)在只是停留在會(huì)用的階段,底層我們的源碼到底是怎么吧我們的對(duì)象創(chuàng)建出來的,還有怎么將我們的對(duì)象設(shè)置到需要它的地方呢,不要慌,老司機(jī)現(xiàn)在就帶你來看看源碼是什么實(shí)現(xiàn)的。這里的源碼很簡(jiǎn)單,一共涉及到三個(gè)類,都是我們運(yùn)行時(shí)生成的DaggerTeacherComponent、Teacher_MembersInjector、Student_Factory。

  先來看看DaggerTeacherComponent,按照字面意思這是我們Teacher的橋梁類,源碼如下:

package com.qianmo.rxjavatext;import dagger.MembersInjector; import javax.annotation.Generated;@Generated(value = "dagger.internal.codegen.ComponentProcessor",comments = "https://google.github.io/dagger" ) public final class DaggerTeacherComponent implements TeacherComponent {private MembersInjector<Teacher> teacherMembersInjector;private DaggerTeacherComponent(Builder builder) {assert builder != null;initialize(builder);}public static Builder builder() {return new Builder();}public static TeacherComponent create() {return builder().build();}@SuppressWarnings("unchecked")private void initialize(final Builder builder) {this.teacherMembersInjector = Teacher_MembersInjector.create(Student_Factory.create());}@Overridepublic void injectA(Teacher teacher) {teacherMembersInjector.injectMembers(teacher);}public static final class Builder {private Builder() {}public TeacherComponent build() {return new DaggerTeacherComponent(this);}} }

  我們首先來看我們之前的調(diào)用方法如下

DaggerTeacherComponent.builder().build().injectA(this);

  首先看一下DaggerTeacherComponent.builder()方法,我們從源碼中可以看到DaggerTeacherComponent.builder()調(diào)用生成了一個(gè)Builder 對(duì)象,我們繼續(xù)代用builder.builder()方法,而我們的build類中代碼如下(這里再次吐槽博客園的編輯器,在線編輯的時(shí)候無法顯示引用代碼的行號(hào),這樣我們就沒法通過行號(hào)來解釋每一行代碼的意思,而必須要重寫貼一次代碼,操蛋!!!):

public static final class Builder {private Builder() {}public TeacherComponent build() {return new DaggerTeacherComponent(this);}}

  “new DaggerTeacherComponent(this);” 看到?jīng)],實(shí)際上是調(diào)用我們的DaggerTeacherComponent對(duì)象,而我們的DaggerTeacherComponent構(gòu)造函數(shù)是調(diào)用的initialize()方法,看一下方法里面具體代碼

@SuppressWarnings("unchecked")private void initialize(final Builder builder) {this.teacherMembersInjector = Teacher_MembersInjector.create(Student_Factory.create());}

  這時(shí)候出現(xiàn)了Teacher_MembersInjector、Student_Factory類,我們先不要管,繼續(xù)往下看,上面我們調(diào)用完builder.builder()方法方法之后,再調(diào)用injectA(this)的方法,具體代碼如下:

@Overridepublic void injectA(Teacher teacher) {teacherMembersInjector.injectMembers(teacher);}

  呃,這里我們又看到Teacher_MembersInjector這個(gè)類對(duì)象了,所以這時(shí)候看看我們Teacher_MembersInjector的源碼了,我們上面一共在兩個(gè)地方使用了Teacher_MembersInjector,一個(gè)是.create方法,一個(gè)是injectMember方法,所以我們主要要留心源碼里面這兩個(gè)類,具體源碼如下:

package com.qianmo.rxjavatext;import dagger.MembersInjector; import javax.annotation.Generated; import javax.inject.Provider;@Generated(value = "dagger.internal.codegen.ComponentProcessor",comments = "https://google.github.io/dagger" ) public final class Teacher_MembersInjector implements MembersInjector<Teacher> {private final Provider<Student> studentProvider;public Teacher_MembersInjector(Provider<Student> studentProvider) {assert studentProvider != null;this.studentProvider = studentProvider;}public static MembersInjector<Teacher> create(Provider<Student> studentProvider) {return new Teacher_MembersInjector(studentProvider);}@Overridepublic void injectMembers(Teacher instance) {if (instance == null) {throw new NullPointerException("Cannot inject members into a null reference");}instance.student = studentProvider.get();}public static void injectStudent(Teacher instance, Provider<Student> studentProvider) {instance.student = studentProvider.get();} }

  先看看.create方法,可以看到就是很簡(jiǎn)單的new Teacher_MembersInjector ,相當(dāng)于初始化了一些成員變量studentProvider ,至于studentProvider 是什么,從字面的意思上來看是我們student的提供者,那么是時(shí)候我們就再來看看Student_Factory.create()方法了,因?yàn)槭沁@個(gè)類提供了studentProvider 對(duì)象

package com.qianmo.rxjavatext;import dagger.internal.Factory; import javax.annotation.Generated;@Generated(value = "dagger.internal.codegen.ComponentProcessor",comments = "https://google.github.io/dagger" ) public enum Student_Factory implements Factory<Student> {INSTANCE;@Overridepublic Student get() {return new Student();}public static Factory<Student> create() {return INSTANCE;} }

  窩草,請(qǐng)看get方法中的 “new Student()”代碼,這不就是我們的student對(duì)象的創(chuàng)建嘛,原來你在這里,再看一下在哪里調(diào)用我們的studentProvider.get方法拿到創(chuàng)建的Student對(duì)象,這時(shí)候請(qǐng)看Teacher_MembersInjector.injectMembers()方法,具體代碼如下

@Overridepublic void injectMembers(Teacher instance) {if (instance == null) {throw new NullPointerException("Cannot inject members into a null reference");}instance.student = studentProvider.get();}

  看到我們倒數(shù)第二行了沒,在這里我們拿到teacher對(duì)象,設(shè)置它的成員變量student。ok,到這里我們就懂了,整個(gè)邏輯就全部通了,首先DaggerTeacherComponent.builder().build()執(zhí)行完在Student_Factory中創(chuàng)建好了student對(duì)象,然后在調(diào)用injectA(this)方法,將創(chuàng)建的student對(duì)象放置到teacher對(duì)象中的student屬性上。

  OK,到這里我們就簡(jiǎn)單的了解了Dagger2的使用了,寫到這里篇幅已經(jīng)比較長(zhǎng)了,所以我打算用三篇文章來和大家吃透Dagger2,和大家一起從源碼入坑到跳坑,最后,還有一個(gè)很關(guān)鍵事忘說了:最近打算辭職回北京,有沒有大神同學(xué)推薦工作,帶帶小弟啊.

  下一篇:Android -- 帶你從源碼角度領(lǐng)悟Dagger2入門到放棄(二)

?

總結(jié)

以上是生活随笔為你收集整理的Android -- 带你从源码角度领悟Dagger2入门到放弃(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。