Lifecycle+Retrofit+Room完美结合 领略架构之美

本文详细探讨了如何将Retrofit、Room框架整合到Android项目中,实现数据的初始化和UI更新。首先介绍了Room的EntityInsertionAdapter和SQLiteStatement在数据库操作中的作用,以及如何使用Migration进行数据库升级。接着分析了Retrofit的工作原理,包括动态代理、CallAdapter和Converter的作用,展示了如何构建自定义返回类型。此外,还展示了如何构建ViewModel、Repository,以及如何封装Room数据库回调。最后,文章总结了LiveData在架构中的重要性,并提及了对RxJava的考虑。
摘要由CSDN通过智能技术生成

this.__insertionAdapterOfZhihuItemEntity = new EntityInsertionAdapter(__db) {
public String createQuery() {
return “INSERT OR REPLACE INTO zhuhulist(id,date,stories,top_stories) VALUES (nullif(?, 0),?,?,?)”;
}

public void bind(SupportSQLiteStatement stmt, ZhihuItemEntity value) {
//通过SQLiteStatement的bind方法,可以很巧妙的将类对象数据转化为数据库要操作的数据类型。
stmt.bindLong(1, (long)value.getId());//按顺序依次放入SQLiteStatement对象。
if(value.date == null) {
stmt.bindNull(2);
} else {
stmt.bindString(2, value.date);
}

//通过DB类注入的自定义转化器,我们可以将任何对象类型持久化到数据库中,并且很便捷的从数据库反序列化出来
String _tmp = DateConverter.toZhihuStoriesEntity(value.stories);
if(_tmp == null) {
stmt.bindNull(3);
} else {
stmt.bindString(3, _tmp);
}

String _tmp_1 = DateConverter.toZhihuStoriesEntity(value.top_stories);
if(_tmp_1 == null) {
stmt.bindNull(4);
} else {
stmt.bindString(4, _tmp_1);
}

}
};
}

public void insertItem(ZhihuItemEntity products) {
this.__db.beginTransaction();

try {
//借助SQLiteStatement类操作数据库,既优化了数据库操作性能,又巧妙的bind了对象类型数据。
this.__insertionAdapterOfZhihuItemEntity.insert(products);
this.__db.setTransactionSuccessful();
} finally {
//这里很重要,我们平时操作数据库或流必须要做 finally块 关闭资源。
this.__db.endTransaction();
}
}

实现类中可以看出insert是通过EntityInsertionAdapter类完成操作的,而EntityInsertionAdapter内部会持有个SupportSQLiteStatement,其实就是_SQLiteStatement_类的抽象封装。 其实例获取是通过RoomData内部方法compileStatement()得到的。

研究下RoomData抽象类源码:

public abstract class RoomDatabase {
// set by the generated open helper.
protected volatile SupportSQLiteDatabase mDatabase;//SQLiteDatabase类的封装抽象层
private SupportSQLiteOpenHelper mOpenHelper;//SQLiteOpenHelper类的封装抽象层
private final InvalidationTracker mInvalidationTracker;//绑定数据变更监听器,如在数据变化时通知LiveData

protected abstract SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration config);
protected abstract InvalidationTracker createInvalidationTracker();

public Cursor query(String query, @Nullable Object[] args) {
return mOpenHelper.getWritableDatabase().query(new SimpleSQLiteQuery(query, args));
}

public Cursor query(SupportSQLiteQuery query) {
assertNotMainThread();//每次数据库操作检查线程
return mOpenHelper.getWritableDatabase().query(query);
}

public SupportSQLiteStatement compileStatement(String sql) {
assertNotMainThread();
return mOpenHelper.getWritableDatabase().compileStatement(sql);
}

public void beginTransaction() {
assertNotMainThread();
mInvalidationTracker.syncTriggers();
mOpenHelper.getWritableDatabase().beginTransaction();
}

public void endTransaction() {
mOpenHelper.getWritableDatabase().endTransaction();
if (!inTransaction()) {
// enqueue refresh only if we are NOT in a transaction. Otherwise, wait for the last
// endTransaction call to do it.
mInvalidationTracker.refreshVersionsAsync();
}
}

public static class Builder {
private MigrationContainer mMigrationContainer;//数据库升级辅助类

@NonNull
public Builder addCallback(@NonNull Callback callback) {
if (mCallbacks == null) {
mCallbacks = new ArrayList<>();
}
mCallbacks.add(callback);
return this;
}

@NonNull
public T build() {
//noinspection ConstantConditions
if (mContext == null) {
throw new IllegalArgumentException(“Cannot provide null context for the database.”);
}
//noinspection ConstantConditions
if (mDatabaseClass == null) {
throw new IllegalArgumentException(“Must provide an abstract class that”

  • " extends RoomDatabase");
    }
    if (mFactory == null) {
    //默认的SupportSQLiteOpenHelper创建工厂
    mFactory = new FrameworkSQLiteOpenHelperFactory();//SupportSQLiteOpenHelper的实现类,通过mDelegate带来类操作真正的SQLiteOpenHelper
    }
    DatabaseConfiguration configuration =
    new DatabaseConfiguration(mContext, mName, mFactory, mMigrationContainer,
    mCallbacks, mAllowMainThreadQueries, mRequireMigration);
    //最终通过反射加载系统帮我们实现的真正RoomData
    T db = Room.getGeneratedImplementation(mDatabaseClass, DB_IMPL_SUFFIX);
    db.init(configuration);
    return db;
    }

public abstract static class Callback {

public void onCreate(@NonNull SupportSQLiteDatabase db) {
}

public void onOpen(@NonNull SupportSQLiteDatabase db) {
}
}
}

DB是通过Build设计模式获取实例的,在build过程中,可以添加CallBack抽象类回调数据的_onCreate_和_onOpen_。

当然,我很愿意回答您的问题。下面是一个 Kotlin + 协程 + Retrofit + MVVM 实现网络请求的示例: 1. 在 build.gradle 中添加以下依赖: ``` implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0' implementation 'com.squareup.retrofit2:retrofit:2.8.1' implementation 'com.squareup.retrofit2:converter-gson:2.8.1' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9' ``` 2. 创建 Retrofit 接口: ```kotlin interface ApiService { @GET("users/{user}/repos") suspend fun getRepos(@Path("user") user: String): List<Repo> } ``` 3. 创建数据模型: ```kotlin data class Repo(val name: String) ``` 4. 创建 Repository: ```kotlin class MainRepository(private val apiService: ApiService) { suspend fun getRepos(user: String): List<Repo> { return apiService.getRepos(user) } } ``` 5. 创建 ViewModel: ```kotlin class MainViewModel(private val repository: MainRepository) : ViewModel() { private val _repos = MutableLiveData<List<Repo>>() val repos: LiveData<List<Repo>> = _repos fun getRepos(user: String) { viewModelScope.launch { _repos.value = repository.getRepos(user) } } } ``` 6. 创建 Activity/Fragment: ```kotlin class MainActivity : AppCompatActivity() { private lateinit var viewModel: MainViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val apiService = Retrofit.Builder() .baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build() .create(ApiService::class.java) val repository = MainRepository(apiService) viewModel = ViewModelProvider(this, MainViewModelFactory(repository))[MainViewModel::class.java] viewModel.repos.observe(this, Observer { repos -> // do something with repos }) viewModel.getRepos("octocat") } } ``` 以上就是一个使用 Kotlin + 协程 + Retrofit + MVVM 实现网络请求的示例。希望对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值