Android Aria 下载框架的优化实践:封装、任务管理与持久化存储

本文详细介绍了如何在 Android 项目中使用 Aria 下载框架,并通过封装、任务队列管理、网络状态检查以及持久化存储等优化手段,提升下载功能的代码质量和用户体验。主要内容包括:

1.封装下载逻辑:将 Aria 的下载逻辑封装到一个单独的类中,便于复用和维护。

2.任务队列管理:支持多个下载任务的有序执行,避免同时下载过多文件。

3.网络状态检查:在下载前检查网络状态,避免在无网络时启动下载任务。

4.持久化存储:使用 Room 数据库存储下载任务信息,支持应用重启后恢复下载任务。

通过本文的实践,你将掌握如何高效地使用 Aria 实现强大的下载功能,并优化代码结构和性能

以下是完整代码,包括封装下载逻辑、任务队列管理、网络状态检查以及持久化存储。
你需要引入以下库:
Aria 下载框架:

dependencies {
    // Aria 核心库
    implementation 'com.arialyy.aria:core:3.8.16'

    // Aria 注解处理器(如果需要)
    annotationProcessor 'com.arialyy.aria:compiler:3.8.16'
}

Room 数据库(用于持久化存储)

dependencies {
    // Room 数据库
    implementation "androidx.room:room-runtime:2.5.2"
    kapt "androidx.room:room-compiler:2.5.2" // Kotlin 注解处理器
    implementation "androidx.room:room-ktx:2.5.2" // 支持 Kotlin 扩展函数
}

Kotlin 协程(用于异步操作)

dependencies {
    // Kotlin 协程
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1"
}

AndroidX 核心库

dependencies {
    // AndroidX 核心库
    implementation 'androidx.core:core-ktx:1.10.1'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'com.google.android.material:material:1.9.0'
}

完整的 build.gradle 文件

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt' // Kotlin 注解处理器
}

android {
    compileSdk 34

    defaultConfig {
        applicationId "com.example.myapp"
        minSdk 21
        targetSdk 34
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }

    kotlinOptions {
        jvmTarget = '17'
    }
}

dependencies {
    // Aria 下载框架
    implementation 'com.arialyy.aria:core:3.8.16'
    annotationProcessor 'com.arialyy.aria:compiler:3.8.16'

    // Room 数据库
    implementation "androidx.room:room-runtime:2.5.2"
    kapt "androidx.room:room-compiler:2.5.2"
    implementation "androidx.room:room-ktx:2.5.2"

    // Kotlin 协程
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1"

    // AndroidX 核心库
    implementation 'androidx.core:core-ktx:1.10.1'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'com.google.android.material:material:1.9.0'
}

代码如下:

1. 封装下载逻辑
将 Aria 的下载逻辑封装到一个单独的类中,便于复用和维护。

DownloadManager.kt

package com.example.myapp.download

import android.content.Context
import com.arialyy.aria.core.Aria
import com.arialyy.aria.core.task.DownloadTask
import com.arialyy.aria.core.common.AbsDownloadTaskListener
import com.example.myapp.utils.NetworkUtils
import com.example.myapp.utils.FileUtils

class DownloadManager(private val context: Context) {

    private val downloadQueue = mutableListOf<DownloadTask>()
    private var isDownloading = false

    fun downloadFile(url: String, fileName: String, listener: DownloadListener) {
        if (!NetworkUtils.isNetworkAvailable(context)) {
            listener.onFail("No network available")
            return
        }

        val savePath = FileUtils.getDownloadPath(context, fileName)
        val task = Aria.download(context)
            .load(url)
            .setFilePath(savePath)
            .addTaskListener(object : AbsDownloadTaskListener() {
                override fun onTaskStart(task: DownloadTask) {
                    listener.onStart()
                }

                override fun onTaskRunning(task: DownloadTask) {
                    val progress = task.percent
                    val speed = task.convertSpeed
                    listener.onProgress(progress, speed)
                }

                override fun onTaskComplete(task: DownloadTask) {
                    listener.onComplete(savePath)
                    downloadQueue.remove(task)
                    startNextDownload()
                }

                override fun onTaskFail(task: DownloadTask) {
                    listener.onFail("Download failed")
                    downloadQueue.remove(task)
                    startNextDownload()
                }
            })
            .create()

        downloadQueue.add(task)
        if (!isDownloading) {
            startNextDownload()
        }
    }

    private fun startNextDownload() {
        if (downloadQueue.isNotEmpty()) {
            isDownloading = true
            val task = downloadQueue[0]
            task.start()
        } else {
            isDownloading = false
        }
    }

    interface DownloadListener {
        fun onStart()
        fun onProgress(progress: Int, speed: String)
        fun onComplete(filePath: String)
        fun onFail(error: String)
    }
}

2. 工具类
FileUtils.kt:管理下载路径

package com.example.myapp.utils

import android.content.Context
import android.os.Environment
import java.io.File

object FileUtils {

    fun getDownloadPath(context: Context, fileName: String): String {
        val directory = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
        return File(directory, fileName).absolutePath
    }
}

NetworkUtils.kt:检查网络状态

package com.example.myapp.utils

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities

object NetworkUtils {

    fun isNetworkAvailable(context: Context): Boolean {
        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val network = connectivityManager.activeNetwork ?: return false
        val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
        return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    }
}

3. 在 Activity 中使用封装后的下载逻辑
MainActivity.kt

package com.example.myapp

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.myapp.download.DownloadManager

class MainActivity : AppCompatActivity() {

    private lateinit var downloadManager: DownloadManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        downloadManager = DownloadManager(this)

        // 下载文件的 URL 和文件名
        val downloadUrl = "https://example.com/file.zip"
        val fileName = "file.zip"

        // 开始下载
        downloadManager.downloadFile(downloadUrl, fileName, object : DownloadManager.DownloadListener {
            override fun onStart() {
                println("Download started")
            }

            override fun onProgress(progress: Int, speed: String) {
                println("Download progress: $progress%, speed: $speed")
            }

            override fun onComplete(filePath: String) {
                println("Download completed. File saved at: $filePath")
            }

            override fun onFail(error: String) {
                println(error)
            }
        })
    }
}

4. 持久化存储(可选)
使用 Room 数据库存储下载任务信息,以便应用重启后恢复下载任务。

DownloadTaskEntity.kt:定义实体类

package com.example.myapp.data

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "download_tasks")
data class DownloadTaskEntity(
    @PrimaryKey val url: String,
    val fileName: String,
    val savePath: String,
    val status: String // e.g., "pending", "completed", "failed"
)

DownloadTaskDao.kt:定义 DAO 接口

package com.example.myapp.data

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query

@Dao
interface DownloadTaskDao {

    @Insert
    suspend fun insert(task: DownloadTaskEntity)

    @Query("SELECT * FROM download_tasks WHERE status = :status")
    suspend fun getTasksByStatus(status: String): List<DownloadTaskEntity>

    @Query("UPDATE download_tasks SET status = :status WHERE url = :url")
    suspend fun updateTaskStatus(url: String, status: String)
}

AppDatabase.kt:创建数据库

package com.example.myapp.data

import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import android.content.Context

@Database(entities = [DownloadTaskEntity::class], version = 1)
abstract class AppDatabase : RoomDatabase() {

    abstract fun downloadTaskDao(): DownloadTaskDao

    companion object {
        @Volatile
        private var INSTANCE: AppDatabase? = null

        fun getDatabase(context: Context): AppDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    AppDatabase::class.java,
                    "app_database"
                ).build()
                INSTANCE = instance
                instance
            }
        }
    }
}

在 DownloadManager 中使用 Room 数据库

class DownloadManager(private val context: Context) {

    private val database = AppDatabase.getDatabase(context)
    private val downloadQueue = mutableListOf<DownloadTask>()
    private var isDownloading = false

    fun downloadFile(url: String, fileName: String, listener: DownloadListener) {
        if (!NetworkUtils.isNetworkAvailable(context)) {
            listener.onFail("No network available")
            return
        }

        val savePath = FileUtils.getDownloadPath(context, fileName)
        val task = Aria.download(context)
            .load(url)
            .setFilePath(savePath)
            .addTaskListener(object : AbsDownloadTaskListener() {
                override fun onTaskStart(task: DownloadTask) {
                    listener.onStart()
                    saveTaskToDatabase(url, fileName, savePath, "pending")
                }

                override fun onTaskRunning(task: DownloadTask) {
                    val progress = task.percent
                    val speed = task.convertSpeed
                    listener.onProgress(progress, speed)
                }

                override fun onTaskComplete(task: DownloadTask) {
                    listener.onComplete(savePath)
                    updateTaskStatus(url, "completed")
                    downloadQueue.remove(task)
                    startNextDownload()
                }

                override fun onTaskFail(task: DownloadTask) {
                    listener.onFail("Download failed")
                    updateTaskStatus(url, "failed")
                    downloadQueue.remove(task)
                    startNextDownload()
                }
            })
            .create()

        downloadQueue.add(task)
        if (!isDownloading) {
            startNextDownload()
        }
    }

    private fun saveTaskToDatabase(url: String, fileName: String, savePath: String, status: String) {
        val task = DownloadTaskEntity(url, fileName, savePath, status)
        database.downloadTaskDao().insert(task)
    }

    private fun updateTaskStatus(url: String, status: String) {
        database.downloadTaskDao().updateTaskStatus(url, status)
    }

    private fun startNextDownload() {
        if (downloadQueue.isNotEmpty()) {
            isDownloading = true
            val task = downloadQueue[0]
            task.start()
        } else {
            isDownloading = false
        }
    }

    interface DownloadListener {
        fun onStart()
        fun onProgress(progress: Int, speed: String)
        fun onComplete(filePath: String)
        fun onFail(error: String)
    }
}

5. 总结
我们实现了以下功能:
1.封装下载逻辑:提高代码复用性和可维护性。

2.任务队列管理:支持多个下载任务的有序执行。

3.网络状态检查:避免在无网络时启动下载。

4.持久化存储:支持应用重启后恢复下载任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值