欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

移動端開發(fā)之Jetpack?Hilt技術(shù)實現(xiàn)解耦

 更新時間:2023年02月17日 08:58:51   作者:守住Android最后的光  
Hilt的出現(xiàn)解決前兩點問題,因為Hilt是Dagger針對Android平臺的場景化框架,比如Dagger需要我們手動聲明注入的地方,而Android聲明的地方不都在onCreate()嗎,所以Hilt就幫我們做了,除此之外還做了很多事情

Hilt是什么

Hilt 是基于 Dagger2 的針對 Android場景定制化 的框架。

這有點像什么? RxAndroid 是 RxJava 的Android平臺定制化擴展。Andorid雖然由Java、Kotlin構(gòu)成,但是它有很多平臺的特性,比如它有 Java開發(fā) 所不知道的 Context 等。

Dagger框架雖然很出名,在國外也很流行,但是在國內(nèi)使用其的App少之又少,列舉一些缺點:

  • 上手難,眾多Android應(yīng)用框架中,Dagger必定是最難學(xué)的那一檔;
  • 它就是一個復(fù)雜框架,沒有針對任何平臺,所以對于所有平臺來說會難用;
  • 在Android Studio4.0版本以前,無法追蹤Dagger的依賴關(guān)系(就類比IDE無法通過快捷鍵知道一個接口有哪些實現(xiàn)類) 開發(fā)者不知道為啥要做依賴注入
  • 對于第三點,Android Studio4.1已經(jīng)支持了該功能,但是4.1有許多Bug,很多開發(fā)者都沒有升級 。

Hilt的出現(xiàn)解決前兩點問題,因為 Hilt 是 Dagger 針對Android平臺的場景化框架,比如Dagger需要我們手動聲明注入的地方,而Android聲明的地方不都在 onCreate()嗎,所以Hilt就幫我們做了,除此之外還做了很多事情,這樣一來,相較于Dagger,我們能用更少代碼、更容易、更輕松的配置依賴注入。

Hilt使用地方

Google認為移動端應(yīng)用的架構(gòu)設(shè)計,最重要的 Separation of concerns(分離關(guān)注點)。上網(wǎng)找解釋,其實它就是 模塊解耦。下面是Google官方推薦的Android應(yīng)用架構(gòu)圖:

依賴注入(DI)概念

而 Hilt 是被定義為 依賴注入框架而被發(fā)布。什么?又是依賴注入框架?不是之前已經(jīng)有了一個 Dagger2 了嗎?除了 Dagger2, 還有 ButterKnife ,Kotlin甚至還有輕量級的 Koin。

什么是依賴注入?先來看下面代碼:

class MyClass {
    val user = User()
}

我們在一個類 MyClass 中 聲明了一個變量 user,并初始化-------調(diào)用 User 構(gòu)造函數(shù),創(chuàng)建一個對象。

上面這段代碼就產(chǎn)生了一個依賴關(guān)系。

我們要先看懂誰依賴了誰?首先 MyClass 是我們的類,User 可以是我們自己寫的類,也可以是通過第三方Jar包或SDK里面的類。 在我們寫的 MyClass 的代碼里面,我們需要一個 User 對象來完成一些任務(wù),所以我們創(chuàng)建了 User 對象,這就說明 MyClass 依賴了 User。對于 MyClass來說,User是外面之物,但是又需要依賴它。

如果上面這個 User,不是由自己創(chuàng)建,而是由外部創(chuàng)建,然后在本類只做賦值工作 ,這個過程就是 依賴注入。

有一個我們非常熟悉的設(shè)計模式,就使用了依賴注入的方法—工廠模式:

class UserFactory {
    fun newUser(): User{
        return User()
    }
}
class MyClass {
    val user = UserFactory.newUser()
}

我們的 MyClass 類需要使用 User 類,但是這次沒有自己來創(chuàng)建(沒有自己new出來),而是交由給 UserFactory 來創(chuàng)建出來,MyClass就做了最后的賦值工作。

對于 MyClass 來說,這就是一次依賴注入,和上面例子相比,把對象創(chuàng)建的過程交由給了別的類。

所以我們通過上面兩個例子就能知道依賴注入的本質(zhì)是什么:借由外部得到對象。依賴注入框架就是這個外部

現(xiàn)在流行的 Dagger2、Koin框架,只是讓我們更輕松、更容易的去得到對象。

Dagger的中文翻譯是 “刀”,它就像一把刀,插進我們代碼中。那相信你也知道 ButterKnife 為什么這么取名了吧。

Hilt使用

導(dǎo)入

在 app 的 build.gradle 中加入:

plugins {
    ...
    id 'kotlin-kapt'
    id 'dagger.hilt.android.plugin'
}
dependencies {
    ...
    implementation 'com.google.dagger:hilt-android:2.28-alpha'
    kapt 'com.google.dagger:hilt-android-compiler:2.28-alpha'
}

在 project的 build.gradle 中加入:

classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'

一個簡單的例子 Hilt 需要 AndroidManifest 使用帶有 @HiltAndroidApp 注解的 Application 類,所以我們的 Application需要這樣:

@HiltAndroidApp
class HiltApp : Application() {
   ...
}

然后在 AndroidManifest 文件中聲明:

<application
        android:name=".HiltApp"
        ...
    </application>

假如我們要在 MainActivity 中注入一個 User 對象, 我們首先編寫一個 User 類,User類有兩個屬性 name 和 age 。 誒,這個時候有同學(xué)就會問了:我通過 @Inject 聲明一個User,Hilt就能給我創(chuàng)建一個 User 對象,那這個User對象里面的name和age是啥?答案是:編譯會報錯,因為我們自己都不知道這兩個參數(shù)是啥,Hilt怎么可能會知道,所以這兩個屬性也要通過依賴注入的方式來注入。

為了簡化這個問題,我定義一個默認的無參構(gòu)造函數(shù),反正創(chuàng)建之后,里面的值也是可以修改的嘛。

data class User(var name: String, var age: Int) {
    // 定義一個默認的無參構(gòu)造函數(shù),并使用 @Inject 注解修飾
    @Inject
    constructor() : this("Rikka", 23)
}

接著我們在 MainActivity 中聲明一個 User,通過 @Inject 來修飾,并且MainActivity 需要通過 @AndroidEntryPoint 修飾:

// 1
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    // 2
    @Inject
    lateinit var user: User
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d(TAG, "user name:${user.name} age:${user.age}")
    }
}

Logcat 打印結(jié)果如下:

代碼解析:

注釋1: 為 MainActivity 修飾 @AndroidEntryPoint,該注解表明 該類為需要進行依賴注入的 Android類,是Dagger針對Android場景化的地方。當我們類中需要進行依賴注入,我們?yōu)樵擃惣尤脒@個注解,它會幫助創(chuàng)建一個單獨的 Hilt組件。它不能修飾Abstract,它只能修飾:

  • ComponentActivity
  • (Support)Fragment
  • View
  • Service
  • BroadcastReceiver

注釋2:我們需要注入一個 User,所以我們給它加一個 @Inject 注解,告訴 Hilt。因為Kotlin的語法問題,這里不得不聲明 lateinit(而這里Koin的寫法更加優(yōu)雅),接下來步驟大概是這樣的:

  • Hilt 會去找User 這個類的構(gòu)造函數(shù),以此來創(chuàng)建一個對象
  • Hilt 發(fā)現(xiàn) 有兩個個構(gòu)造函數(shù),而無參構(gòu)造函數(shù)被@Inject 聲明
  • Hilt 會去調(diào)用被@Inject 的構(gòu)造函數(shù),創(chuàng)建一個User(“Rikka”, 23) 對象
  • 返回這個對象, MainActivity 實現(xiàn)外部幫忙創(chuàng)建 User對象,實現(xiàn) User 的依賴注入。

Inject 的中文翻譯是 “注入、注射”,所以可以形象的認為, @Inject 修飾的變量是被外界通過針筒注入進來的。

  • @Inject 可以修飾
  • 構(gòu)造函數(shù) Constructors
  • 變量 Fields
  • 方法 Methods

構(gòu)造函數(shù)是最先被注解的,然后再是變量和方法。所以它修飾構(gòu)造函數(shù)和修飾變量,其實是不同的作用。但為了便于理解,我們可以把它看成是一個插眼工具,便于Hilt去尋找要注入的地方。

我們上面的 User 類是無參構(gòu)造函數(shù),這次假設(shè)我們要有參數(shù)的呢?其實就是參數(shù)也要注入嘛,這就是套娃來的,來看看我們給User新增一個 屬性:Clothes:

class Clothes @Inject constructor() {
}
class User @Inject constructor(var clothes: Clothes){
}
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    ...
        Log.d(TAG, "user clothes:${user.clothes}")
}

打印結(jié)果:

PS:大家不要太拘泥于有參構(gòu)造函數(shù)的創(chuàng)建,我認為注入的作用是創(chuàng)建出一個對象,這個對象里面的內(nèi)容可以后續(xù)再傳入,它更多的體現(xiàn)、或者我們需要注意的是 “分離關(guān)注點”

實現(xiàn)接口實例注入

因為接口沒有構(gòu)造函數(shù),所以當我們想要依賴一些接口時,該怎么辦。

我們來下面的示例,我們寫一個 Profession 接口,代表職業(yè):

interface Profession {
    fun doJob()
}

假設(shè)我們有兩個實現(xiàn)接口的類:醫(yī)生類和程序猿類:

class Doctor : Profession{
    override fun doJob() {
        Log.d("Doctor", "doctor do job")
    }
}
class Programmer : Profession{
    override fun doJob() {
        Log.d("Programmer", "programmer do job")
    }
}

這個時候我給 User 類添加一個職業(yè)的屬性,并希望它能夠自動注入:

class User @Inject constructor(var clothes: Clothes){
    @Inject
    lateinit var profession: Profession
}

因為 Profession 是一個接口,它有兩個實現(xiàn)類,所以這樣 Hilt 并不能知道我們要實例化哪個具體的實現(xiàn)類,所以編譯的時候就會報錯。

而 Hilt 也解決這種問題,首先我們要在每個實現(xiàn)類上注入構(gòu)造函數(shù):

class Doctor @Inject constructor() : Profession{
    ...
}
class Programmer @Inject constructor() : Profession{
    ...
}

接著我們需要實現(xiàn)一個和該接口有關(guān)的 XXXModule類,它被 @Module 修飾,這個和 Dagger 中的一樣,代表它會為接口提供一個創(chuàng)建實例的工廠,同時需要加上 @InstallIn 注解,用來聲明它是被安裝到哪個組件中,該注解后面會說到。 代碼如下:

@Module
@InstallIn(ActivityComponent::class)
abstract class ProfessionModule {  // 1
    // 2
    @Binds
    abstract fun bindDoctor(doctor: Doctor): Profession
}

注釋1: 我們寫出來的類是一個抽象類,因為我們不需要具體的實現(xiàn)它,而且它沒有具體的命名規(guī)則,因為我們也不會在代碼中直接調(diào)用它,但是為了便于理解,我們起名一般叫 接口名 + Module。

注釋2: 我們假設(shè)該Module提供一個 Doctor 的職業(yè),那我們需要定義一個 抽象方法 來獲取一個Doctor類。 并且 該方法需要被 @Binds 注解修飾。這樣就能被 Hilt 識別。

這樣一來,我們就實現(xiàn)了接口的一個實例化的注入,我們來實驗一下,在 User 中去展示它:

class User @Inject constructor(var clothes: Clothes){
    @Inject
    lateinit var profession: Profession
    fun showMyself() {
        profession.doJob()
    }
}
// MainActivity
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    @Inject
    lateinit var user: User
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        user.showMyself()
    }
}

打印結(jié)果為:

可以看到我們的 Doctor 成功的注入了。

OK,我們了解了接口某一個實現(xiàn)類的注入 (Doctor),那假設(shè)這個時候,另外一個類需要注入接口的另一個實現(xiàn)類 Programmer,那我們是不是也得按照同樣的做法,在 Module類中添加呢?

@Module
@InstallIn(ActivityComponent::class)
abstract class ProfessionModule {
    @Binds
    abstract fun bindDoctor(doctor: Doctor): Profession
    @Binds
    abstract fun bindProgrammer(programmer: Programmer): Profession
}

這個時候發(fā)現(xiàn)運行,編譯也會報錯:

提示我們被綁定多次了。

這是因為 Doctor 和 Programmer 都是相同類型,當他們一起被 Binds 注解,那 Hilt 不知道要去綁定哪一個。

這個時候就需要使用 @Qualifier 注解來幫助我們了,它就是為了這種 相同類型 依賴注入而產(chǎn)生的:

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class BindDoctor
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class

我們創(chuàng)建了新的注解 BindDoctor 和 BindProgrammer,他們都被 @Qualifier 修飾,表示他們用來作用在同種類型上, @Retention 選擇使用 BINARY類型,表明該注解保留到編譯后,但無法通過反射來得到,是比較適合的注解。

接下來,我們要將這些注解作用在被 Binds 注解的抽象方法上:

@Module
@InstallIn(ActivityComponent::class)
abstract class ProfessionModule {
    @BindDoctor
    @Binds
    abstract fun bindDoctor(doctor: Doctor): Profession
    @BindProgrammer
    @Binds
    abstract fun bindProgrammer(programmer: Programmer): Profession
}

最后,在 User 中聲明使用哪一個類型的注入:

class User @Inject constructor(var clothes: Clothes){
    @BindProgrammer  // 這次注入一個 Programmer
    @Inject
    lateinit var profession: Profession
    fun showMyself() {
        profession.doJob()
    }
}

打印結(jié)果如下所示:

這下我們就實現(xiàn)了具體某個實例的注入啦。

實現(xiàn)第三方依賴注入

假設(shè)一些類不是由我們自己寫的,而是由第三方庫導(dǎo)入的。比如 OkHttp ,我們在使用網(wǎng)絡(luò)請求的時候,需要使用它,為了分離關(guān)注點,我們需要對他進行依賴注入。

但是 OkHttp 是我們不能修改的類,所以我們不能在它的構(gòu)造函數(shù)上加入 @Inject, 這個時候該怎么辦呢?

Dagger 中也有類似的場景,我們需要 @Providers 來幫助我們。除此之外,我們也需要 @Module 注解來聲明一個 Module 類, 基于上面的例子,我們可以把這種 Module 類看成是一個工廠:

@Module
@InstallIn(ApplicationComponent::class)
class NetModule { // 1
    // 2
    @Provides
    fun provideOkHttpClient(): OkHttpClient {
        // 3
        return OkHttpClient.Builder().build()
    }
}

注釋1: 聲明一個 NetModule,提供網(wǎng)絡(luò)庫相關(guān)的組件,并沒有和上面例子一樣聲明為抽象函數(shù),這是因為里面的都有具體的實現(xiàn)方法。

注釋2: 編寫一個 provideOkHttpClient() 方法,返回一個 OkHttpClient對象。 聲明一個 @Providers 注解,表示這個提供的依賴對象,是第三方的類或者系統(tǒng)類,我們因為不能直接更改其構(gòu)造函數(shù),所以得加上這個注解。

注釋3:new 一個對象,并返回。

這樣,我們就能在我們代碼中直接使用了:

@Inject
    lateinit var okHttpClient:

@Providers 的本質(zhì)是什么? 第三方類因為其只讀性,Hilt不能找到其構(gòu)造函數(shù),所以需要我們自己手動的創(chuàng)建,創(chuàng)建的方法被 @Providers 修飾, Hilt 找到這個方法,并提供由我們手動創(chuàng)建的對象。

所以 @Providers 的本質(zhì),是由我們自己創(chuàng)建對象, Hilt 幫我們注入。

現(xiàn)在大家都不會直接使用 OkHttp,而是使用 Retrofit,所以我們來提供一個 Retrofit 把:

...
    @Provides
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .client(okHttpClient)
            .build()
    }

因為 Retrofit的創(chuàng)建需要依賴一個 OkHttpClient 對象,所以我們需要創(chuàng)建一個,但是我們也可以注入一個,因為我們之前已經(jīng)有 provideOkHttpClient,所以它就能提供一個實例,我們不用在擔心什么了。

Hilt 的內(nèi)置組件和作用域

@InstallIn 注解

我們之前看到了 @InstallIn 這個注解,它的作用是用來表明 Module 作用的地方,它的參數(shù)時 xxxComponent格式,前面xx代表作用域。

因為 Hilt 是Dagger的Android場景化,所以它能作用的地方和我們Android息息相關(guān),有下面幾處:

  • Application ->ApplicationComponent
  • ViewModel ->ActivityRetainedComponent
  • Activity ->ActivityComponent
  • Fragment ->FragmentComponent
  • View ->ViewComponent
  • Service ->ServiceComponent
  • View Annotation with@WithFragmentBindings ->ViewWithFragemntComponent

除了最后一個,別的作用域還是挺常見的。他們都要通過 @InstallIn 注入。

比如我們ProfessionModule是聲明成 @InstallIn(ActivityComponent::class),這就說明只有在 Activity 的代碼中可以使用它,而在 Service 中是不能使用的。 而 NetModule 則是聲明成 InstallIn(ApplicationComponent::class)的,這說明在全局都可以使用它提供的 OkHttpClient 和 Retrofit 對象。

使注入對象單例

像 Retrofit 、 OkHttpClient 這樣的全局都需要使用到的對象,我們希望它的作用域是全局,并且單例的。

但是 Hilt 提供的 @Inject 對象并不是單例的,每次 注入時都會重新生成一個新的實例,這就說明,假設(shè)我們要使用 Retrofit 來做網(wǎng)絡(luò)請求, @Providers 每次提供的都是不一樣的,這樣對性能來說很不友好,而且不符合常規(guī)的邏輯設(shè)定。

按照以往,我們可以通過給 NetModule 聲明一個 @Singleton 注解,來讓這個類實現(xiàn)單例,來解決這個問題。

Hilt 也有自己的解決方案,那就是使用 @xxxScope 注解,它和上面的 xxxComponent所對應(yīng),表示 在這個作用域內(nèi)單例,來看看對應(yīng)關(guān)系:

  • Application ->ApplicationComponent ->@Singleton
  • ViewModel ->ActivityRetainedComponent ->@ActivityRetainedScoped
  • Activity ->ActivityComponent ->@ActivityScoped
  • Fragment ->FragmentComponent ->@FragmentScoped
  • View ->ViewComponent ->@ViewScoped
  • Service ->ServiceComponent ->@ServiceScoped
  • View Annotation with@WithFragmentBindings ->ViewWithFragemntComponent ->@ViewScoped

使用 @xxScoped 來替代 @InstallIn(xxxComponent::class) 聲明組件為單例。

因為 Application 是作用于全局,所以它的注解是 @Singleton,比較好理解。

作用域的包含關(guān)系

作用域也有自己的包含關(guān)系,比如被 @ActivityScoped聲明的組件,可以在 Fragment 或者 View 中使用,他們的具體包含關(guān)系如下圖所示:

Hilt 預(yù)置的 Qualifier

我介紹過 Hilt 是 Dagger針對Android的場景化,所以它低層做了很多事情,使得在Android上更好的使用。除了上面介紹過的那些注解外,還有很多別的東西,可以讓我們?nèi)ヌ剿?,同時也了解了Dagger本身。

Context 上下文是Android 獨特的存在,它代表著 Application、Activity、Service的一些fwk層的東西。

而我們的代碼中經(jīng)常會需要 Context 來創(chuàng)建一些東西:

class A @Inject constructor(context: Context) {
   ...
}

但是我們知道,它是系統(tǒng)類,我們無法注入 Context。那我們可以通過使用 @Providers 來創(chuàng)建嗎?

@Providers
fun provideContext() {
   ???
}

很明顯,Context 是由AMS來創(chuàng)建的,我們無法直接創(chuàng)建一個上下文出來。這個問題該如何解決呢?

答案是:我們不用解決,Hilt 為我們提供了它自己預(yù)置的注解 @ApplicationContext 和 @ActivityContext,我們直接使用,Hilt會幫我們注入上下文。

class A @Inject constructor(@ApplicaitonContext context: Context)

而現(xiàn)在沒有 ServiceContext,可能是用的比較少吧?

@ApplicationContext 提供的類型是 Application, 而不是我們自己的 App 自定義的 Application,加入我們要使用自己的該怎么辦呢?答案是也很簡單:

@Providers
fun provideApplicaiton(application: Application): MyApplication {
    return  applicaiton as MyApplication
}

直接在 Module 中提供一個,并強轉(zhuǎn)就 OK啦。

注意

ApplicationContext 的作用域是全局, 所以它修飾的類的作用只能是 @InstallIn(Applicaiton) 或 @Singleton,其他的也同理。

之前沒有用過 Dagger,因為項目不需要,且難學(xué),問題多。 Hilt 出來之后解決了大部分的痛點,再不上車屬實就有點說不過去了。

Hilt 相較與 Dagger,肯定是更好用,更適合Android來使用。 它和 Koin的比較,只是性能上的差異,網(wǎng)上大部分的文章都認為 Hilt 性能更優(yōu),但是代碼量更多,在大的項目使用 Hilt 會更好,而小的項目兩者差別不會太大。具體還請開發(fā)者自己研究。

Hilt 作用是 提供依賴注入,幫助程序分離關(guān)注點,幫助搭建低耦合高內(nèi)聚的框架,學(xué)習(xí)它,有利于我們學(xué)習(xí) Android應(yīng)用架構(gòu) 方面的技能。

到此這篇關(guān)于移動端開發(fā)之Jetpack Hilt技術(shù)實現(xiàn)解耦的文章就介紹到這了,更多相關(guān)Jetpack Hilt解耦內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android實現(xiàn)文字翻轉(zhuǎn)動畫的效果

    Android實現(xiàn)文字翻轉(zhuǎn)動畫的效果

    本文實現(xiàn)了Android程序文字翻轉(zhuǎn)動畫的實現(xiàn),具有一定的參考價值,有需要的朋友可以了解一下。
    2016-10-10
  • Android自定義PopupWindow簡單小例子

    Android自定義PopupWindow簡單小例子

    這篇文章主要為大家詳細介紹了Android自定義PopupWindow簡單小例子,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android開發(fā)Activity的生命周期詳解

    Android開發(fā)Activity的生命周期詳解

    這篇文章主要介紹了Android開發(fā)Activity的生命周期詳解,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參一下
    2022-07-07
  • Qt for Android開發(fā)實例教程

    Qt for Android開發(fā)實例教程

    這篇文章主要介紹了Qt for Android開發(fā)的方法,具有一定的參考借鑒價值,需要的朋友可以參考下
    2014-08-08
  • Android手電筒兼容各個手機與版本

    Android手電筒兼容各個手機與版本

    這篇文章主要為大家詳細介紹了Android手電筒兼容各個手機與版本,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • Android網(wǎng)絡(luò)開發(fā)中GET與POST請求詳解

    Android網(wǎng)絡(luò)開發(fā)中GET與POST請求詳解

    這篇文章主要介紹了android實現(xiàn)網(wǎng)絡(luò)請求的get和post請求的簡單封裝與使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧<BR>
    2022-12-12
  • Android日歷控件PickTime代碼實例

    Android日歷控件PickTime代碼實例

    這篇文章主要介紹了Android日歷控件PickTime代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-09-09
  • viewPager+fragment刷新緩存fragment的方法

    viewPager+fragment刷新緩存fragment的方法

    這篇文章主要介紹了viewPager+fragment刷新緩存fragment的方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-03-03
  • 詳解Android Studio中Git的配置及協(xié)同開發(fā)

    詳解Android Studio中Git的配置及協(xié)同開發(fā)

    這篇文章主要介紹了詳解Android Studio中Git的配置及協(xié)同開發(fā),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Android開發(fā)之使用SQLite存儲數(shù)據(jù)的方法分析

    Android開發(fā)之使用SQLite存儲數(shù)據(jù)的方法分析

    這篇文章主要介紹了Android開發(fā)之使用SQLite存儲數(shù)據(jù)的方法,結(jié)合實例形式分析了Android使用SQLite數(shù)據(jù)庫實現(xiàn)針對數(shù)據(jù)的增刪改查操作相關(guān)技巧,需要的朋友可以參考下
    2017-07-07

最新評論