Jetpack
Jetpack 是一個(gè)由多個(gè)庫(kù)組成的套件,可幫助開發(fā)者遵循最佳做法屠橄,減少樣板代碼并編寫可在各種 Android 版本和設(shè)備中一致運(yùn)行的代碼梁厉,讓開發(fā)者精力集中編寫重要的代碼。
Android Architecture Component (AAC)刽射。
官方推薦架構(gòu)
請(qǐng)注意听隐,每個(gè)組件僅依賴于其下一級(jí)的組件补鼻。例如,Activity 和 Fragment 僅依賴于視圖模型。存儲(chǔ)區(qū)是唯一依賴于其他多個(gè)類的類风范;在本例中咨跌,存儲(chǔ)區(qū)依賴于持久性數(shù)據(jù)模型和遠(yuǎn)程后端數(shù)據(jù)源。
MVVM
MVVM即Model - View - ViewModel的縮寫硼婿,它的出現(xiàn)是為了將圖形界面與業(yè)務(wù)邏輯锌半,數(shù)據(jù)模型進(jìn)行解耦。
MVVM也是Google推崇的一種Android項(xiàng)目架構(gòu)模型寇漫。
之前學(xué)習(xí)的Jetpack組建刊殉,大部分都是為了能夠更好地架構(gòu)MVVM應(yīng)用程序而設(shè)計(jì)的。
API接口
接口:https://api.github.com/users/yaoxin521123
工程結(jié)構(gòu)
bean:實(shí)體類州胳。
api:網(wǎng)絡(luò)請(qǐng)求接口记焊。
repository:倉(cāng)儲(chǔ)層。用于存放Room數(shù)據(jù)栓撞,網(wǎng)絡(luò)數(shù)據(jù)遍膜,本地?cái)?shù)據(jù)等。
viewmodel:從倉(cāng)儲(chǔ)層獲取數(shù)據(jù)瓤湘,不需要關(guān)心數(shù)據(jù)來(lái)源瓢颅。
view:Activity,F(xiàn)ragment和布局文件弛说,用會(huì)用到DataBinding組件
dao:Room數(shù)據(jù)庫(kù)操作
application:實(shí)例化全局文件和獲取全局上下文惜索。
bindingAdapter:放一些
添加依賴
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'de.hdodenhof:circleimageview:3.0.1'
搭建項(xiàng)目
通過(guò)獲取GitHub API獲取個(gè)人信息進(jìn)行展示。
1. 定義User實(shí)體類
@Entity(tableName = "user")
data class User(
@PrimaryKey @ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER) var id: Int,
@ColumnInfo(name = "login", typeAffinity = ColumnInfo.TEXT) var login: String,
@ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT) var name: String?,
@ColumnInfo(name = "avatar_url", typeAffinity = ColumnInfo.TEXT) @SerializedName("avatar_url")var avatar: String?,
@ColumnInfo(name = "blog", typeAffinity = ColumnInfo.TEXT) var blog: String,
@ColumnInfo(name = "company", typeAffinity = ColumnInfo.TEXT) var company: String?,
@ColumnInfo(name = "bio", typeAffinity = ColumnInfo.TEXT) var bio: String?,
@ColumnInfo(name = "location", typeAffinity = ColumnInfo.TEXT) var location: String?,
@ColumnInfo(name = "htmlUrl", typeAffinity = ColumnInfo.TEXT) @SerializedName("html_url") var htmlUrl: String?
)
2. 定義Dao類
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertUser(user: User)
@Delete
fun deleteUser(user: User)
@Query("select * from user where login =:name")
fun getUserByName(name: String): LiveData<User>
}
3. 定義DataBase類
@Database(entities = [User::class], version =7)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
private var instance: AppDatabase? = null
@Synchronized
fun getDatabase(context: Context): AppDatabase {
instance?.let {
return it
}
return Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"user_db"
).fallbackToDestructiveMigration().build().apply {
instance = this
}
}
}
}
4. 定義API接口
interface Api {
@GET("users/{userName}")
fun getUser(@Path("userName") userName: String): Call<User>
}
5. 定義Retrofit訪問(wèn)網(wǎng)絡(luò)
object RetrofitClient {
private const val BASE_URL = "https://api.github.com/"
var retrofit: Retrofit
init {
retrofit =
Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create())
.build()
}
fun getApi(): Api? {
return retrofit.create(Api::class.java)
}
}
6. 定義Application類
class MyApplication : Application() {
companion object {
lateinit var context: Context
}
override fun onCreate() {
super.onCreate()
context = applicationContext
}
}
7. 定義Repository
object UserRepository {
var userDao: UserDao = AppDatabase.getDatabase(MyApplication.context).userDao()
fun getUser(name: String): LiveData<User> {
refresh(name)
return userDao.getUserByName(name)
}
fun refresh(name: String) {
RetrofitClient.getApi()?.getUser(name)?.enqueue(object : Callback<User> {
override fun onResponse(call: Call<User>, response: Response<User>) {
if (response.body() != null) {
insertUser(response.body()!!)
}
}
override fun onFailure(call: Call<User>, t: Throwable) {
Log.d("UserRepository", "onFailure$t")
}
})
}
fun insertUser(user: User) {
thread {
userDao.insertUser(user)
}
}
}
8. 定義ViewModel
class MvvmViewModel : ViewModel() {
val userName = "yaoxin521123"
fun getUser() = UserRepository.getUser(userName)
fun refresh() = UserRepository.refresh(userName)
}
9. 繪制xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="user"
type="com.yx.androidseniorpreparetest.eighth.bean.User" />
</data>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/srl_SwipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".eighth.MvvmActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="95dp"
android:layout_height="95dp"
android:layout_gravity="center"
android:layout_marginTop="20dp"
app:image="@{user.avatar}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="@{user.name}"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="@{user.login}"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="@{user.blog}"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="@{user.company}"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="@{user.bio}"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="@{user.location}"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="@{user.htmlUrl}"
android:textColor="#000000"
android:textSize="20sp" />
</LinearLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout
</layout>
10. 在Activity觸發(fā)事件
class MvvmActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding =
DataBindingUtil.setContentView<ActivityMvvmBinding>(this, R.layout.activity_mvvm)
val viewModel = ViewModelProviders.of(this).get(MvvmViewModel::class.java)
viewModel.getUser().observe(this, {
if (it != null) {
binding.user = it
}
})
binding.srlSwipeRefreshLayout.setOnRefreshListener {
viewModel.refresh()
binding.srlSwipeRefreshLayout.isRefreshing = false
}
}
}
11. 定義BindingAapter
class BindingAdapter {
companion object {
@JvmStatic
@BindingAdapter(value = ["image", "defaultImageResource"], requireAll = false)
fun setImage(imageView: ImageView, imageUrl: String?, imageResource: Int) {
if (!TextUtils.isEmpty(imageUrl)) {
Picasso.get()
.load(imageUrl)
.placeholder(R.drawable.ic_launcher_background)
.error(R.drawable.ic_launcher_background)
.into(imageView)
} else {
imageView.setImageResource(imageResource)
}
}
}
}
結(jié)語(yǔ):后續(xù)會(huì)持續(xù)更新哦剃浇,喜歡的話點(diǎn)贊關(guān)注一下吧。
相關(guān)視頻
【Android進(jìn)階】jetpack教程