IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 基于Sunflower演示项目学习下目前的Android Jetpack架构最佳实践 -> 正文阅读

[移动开发]基于Sunflower演示项目学习下目前的Android Jetpack架构最佳实践

Sunflower项目是google发布的Android kotlin Demo项目,展示了使用Jetpack架构开发App的最佳实践),这个项目是持续更新的,第一次提交是2017.8,2021年6月还在更新,我的代码是7月下载的。 里面主要介绍google 最新的一些工具和理念,使用databinding,viewModel,liveData实现MVVM架构, 使开发者可以快速构建自己的APP项目,具体源码:https://github.com/googlesamples/android-sunflower

项目的就是个简单的花园demo, 包括我的花园,植物目录,植物详情,分享等页面,基于kotlin MVVP架构实现,

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

一、主要技术

1、MVVM 利用databinding,viewModel,liveData实现MVVM架构,

2、利用navigation框架做导航,APP只有一个Activity,其余的都是Fragment

二、具体说明

1、界面实现

首先看看manifest文件

    <application
        android:name=".MainApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Sunflower">
        <activity
            android:name=".GardenActivity"
            android:theme="@style/Theme.Sunflower.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <provider
            android:name="androidx.work.impl.WorkManagerInitializer"
            android:authorities="${applicationId}.workmanager-init"
            tools:node="remove" />
    </application>

主Activity:GardenActivity 加载了一个布局

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_garden" />

</layout>

有个来封装其实没啥用,因为没有使用Binding的内容,可以去掉

这里用到Navigation,我们来看看nav_garden

//使用navigation来包装,加载两个fragment app:startDestination设置主界面
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    app:startDestination="@+id/view_pager_fragment">

//主fragment
    <fragment
        android:id="@+id/view_pager_fragment"
        android:name="com.gl.samples.apps.sunflower.HomeViewPagerFragment"
        tools:layout="@layout/fragment_view_pager">

        <action
                android:id="@+id/action_view_pager_fragment_to_plant_detail_fragment"
                app:destination="@id/plant_detail_fragment"
                app:enterAnim="@anim/slide_in_right"
                app:exitAnim="@anim/slide_out_left"
                app:popEnterAnim="@anim/slide_in_left"
                app:popExitAnim="@anim/slide_out_right" />

    </fragment>
//详情页
    <fragment
        android:id="@+id/plant_detail_fragment"
        android:name="com.gl.samples.apps.sunflower.PlantDetailFragment"
        android:label="@string/plant_details_title"
        tools:layout="@layout/fragment_plant_detail">
        <argument
            android:name="plantId"
            app:argType="string" />
    </fragment>

</navigation>

这个也不难,HomeViewPagerFragment主界面,PlantDetailFragment植物详情页,具体内容可以去了解下Navigation
HomeViewPagerFragment 主要是一个viewPager,包含两个Fragment :GardenFragment和 PlantListFragment

class SunflowerPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {

    /**
     * Mapping of the ViewPager page indexes to their respective Fragments
     */
    private val tabFragmentsCreators: Map<Int, () -> Fragment> = mapOf(
        MY_GARDEN_PAGE_INDEX to { GardenFragment() },
        PLANT_LIST_PAGE_INDEX to { PlantListFragment() }
    )

    override fun getItemCount() = tabFragmentsCreators.size

    override fun createFragment(position: Int): Fragment {
        return tabFragmentsCreators[position]?.invoke() ?: throw IndexOutOfBoundsException()
    }
}

viewPager适配器SunflowerPagerAdapter中定义一个map,在创建Fragment的时候通过反射来执行构建Fragment的方法。

这里要注意viewPager和我们以前使用的viewPager并不是一个东西,而是在androidx.viewpager2.widget里面的新的类,主要通过RecyclerView来实现,适配器当然

也是继承RecyclerView.Adapter实现的,具体实现请查看源码,具体不细说。

GardenFragment和 PlantListFragment里面就比较简单,运用DataBinding来把数据绑定到View上,实现数据变化view改变,ViewModel来处理和管理数据,并进行数据通信。

这个里面涉及到的内容比较复杂,可以查看我另一个源码,比较简单的介绍DataBinding和ViewModel的用法,传送门

2、数据加载

这个应用可以说是一个离线应用(数据离线,图片加载不是),主要的数据都是存储在plants.json,于是需要把内容都加载出来:

package com.google.samples.apps.sunflower.workers

import android.content.Context
import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.samples.apps.sunflower.data.AppDatabase
import com.google.samples.apps.sunflower.data.Plant
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class SeedDatabaseWorker(
        context: Context,
        workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
    override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
        try {
            val filename = inputData.getString(KEY_FILENAME)
            if (filename != null) {
                applicationContext.assets.open(filename).use { inputStream ->
                    JsonReader(inputStream.reader()).use { jsonReader ->
                        val plantType = object : TypeToken<List<Plant>>() {}.type
                        val plantList: List<Plant> = Gson().fromJson(jsonReader, plantType)

                        val database = AppDatabase.getInstance(applicationContext)
                        database.plantDao().insertAll(plantList)

                        Result.success()
                    }
                }
            } else {
                Log.e(TAG, "Error seeding database - no valid filename")
                Result.failure()
            }
        } catch (ex: Exception) {
            Log.e(TAG, "Error seeding database", ex)
            Result.failure()
        }
    }

    companion object {
        private const val TAG = "SeedDatabaseWorker"
        const val KEY_FILENAME = "PLANT_DATA_FILENAME"
    }
}

主要在SeedDatabaseWorker类中,主要使用的是WorkManager这个框架来实现异步加载,加载后把数据存入room数据库,便于后续使用。

CoroutineWorker是Worker的子类,一般在使用Kotlin开发的时候使用来和协程配合开发,

看这部分代码可以先去学习下WorkManager,

3、网络请求

主要是获取植物的图片url, 基于okhttp3和retrofit2框架实现
图片的加载使用glide, 这几个框架都是安卓开发的主流框架

package com.google.samples.apps.sunflower.api

import com.google.samples.apps.sunflower.BuildConfig
import com.google.samples.apps.sunflower.data.UnsplashSearchResponse
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import okhttp3.logging.HttpLoggingInterceptor.Level
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query

/**
 * Used to connect to the Unsplash API to fetch photos
 */
interface UnsplashService {

    @GET("search/photos")
    suspend fun searchPhotos(
        @Query("query") query: String,
        @Query("page") page: Int,
        @Query("per_page") perPage: Int,
        @Query("client_id") clientId: String = BuildConfig.UNSPLASH_ACCESS_KEY
    ): UnsplashSearchResponse

    companion object {
        private const val BASE_URL = "https://api.unsplash.com/"

        fun create(): UnsplashService {
            val logger = HttpLoggingInterceptor().apply { level = Level.BASIC }

            val client = OkHttpClient.Builder()
                .addInterceptor(logger)
                .build()

            return Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .build()
                .create(UnsplashService::class.java)
        }
    }
}

总结:

Sunflower这个应用主要的技术包括:DataBinding、ViewModel、LiveData、Navigation、WorkManager和Room,

当然还有一些简单的Android的知识和协程的内容,把这个应用过一遍,对自己也很有帮助。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-13 17:34:48  更:2021-07-13 17:37:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:09:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码