当前位置: 首页 > news >正文

百度竞价一个月5000够吗性能优化大师

百度竞价一个月5000够吗,性能优化大师,王野天照片,东莞企业网站找谁引言#xff1a;为什么需要文件上传进度监听#xff1f; 在移动应用开发中#xff0c;文件上传是常见需求。特别是当用户上传大文件#xff08;如视频、高清图片#xff09;时#xff0c;缺乏进度反馈会导致糟糕的用户体验。本文将深入探讨如何通过封装OkHttp的RequestB…引言为什么需要文件上传进度监听 在移动应用开发中文件上传是常见需求。特别是当用户上传大文件如视频、高清图片时缺乏进度反馈会导致糟糕的用户体验。本文将深入探讨如何通过封装OkHttp的RequestBody实现高效、灵活的文件上传进度监听。 技术架构图 #mermaid-svg-0JD3JMBGMFzYzhor {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-0JD3JMBGMFzYzhor .error-icon{fill:#552222;}#mermaid-svg-0JD3JMBGMFzYzhor .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0JD3JMBGMFzYzhor .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-0JD3JMBGMFzYzhor .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0JD3JMBGMFzYzhor .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0JD3JMBGMFzYzhor .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0JD3JMBGMFzYzhor .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0JD3JMBGMFzYzhor .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0JD3JMBGMFzYzhor .marker.cross{stroke:#333333;}#mermaid-svg-0JD3JMBGMFzYzhor svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0JD3JMBGMFzYzhor .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0JD3JMBGMFzYzhor .cluster-label text{fill:#333;}#mermaid-svg-0JD3JMBGMFzYzhor .cluster-label span{color:#333;}#mermaid-svg-0JD3JMBGMFzYzhor .label text,#mermaid-svg-0JD3JMBGMFzYzhor span{fill:#333;color:#333;}#mermaid-svg-0JD3JMBGMFzYzhor .node rect,#mermaid-svg-0JD3JMBGMFzYzhor .node circle,#mermaid-svg-0JD3JMBGMFzYzhor .node ellipse,#mermaid-svg-0JD3JMBGMFzYzhor .node polygon,#mermaid-svg-0JD3JMBGMFzYzhor .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0JD3JMBGMFzYzhor .node .label{text-align:center;}#mermaid-svg-0JD3JMBGMFzYzhor .node.clickable{cursor:pointer;}#mermaid-svg-0JD3JMBGMFzYzhor .arrowheadPath{fill:#333333;}#mermaid-svg-0JD3JMBGMFzYzhor .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0JD3JMBGMFzYzhor .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0JD3JMBGMFzYzhor .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-0JD3JMBGMFzYzhor .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-0JD3JMBGMFzYzhor .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0JD3JMBGMFzYzhor .cluster text{fill:#333;}#mermaid-svg-0JD3JMBGMFzYzhor .cluster span{color:#333;}#mermaid-svg-0JD3JMBGMFzYzhor div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0JD3JMBGMFzYzhor :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端 ProgressRequestBody CountingSink OkHttp原始Sink 网络传输 ProgressListener UI更新 关键技术组件 ProgressListener进度回调接口CountingSink字节计数拦截器ProgressRequestBodyRequestBody封装器 完整代码实现 1. 进度监听接口 interface ProgressListener {fun onProgress(bytesWritten: Long, contentLength: Long, identifier: String? null,done: Boolean false) }2. 字节计数Sink实现 import okio.ForwardingSink import okio.Sink import java.io.IOExceptionclass CountingSink(delegate: Sink,private val listener: ProgressListener,private val contentLength: Long,private val identifier: String? null ) : ForwardingSink(delegate) {private var bytesWritten 0Lprivate var lastReportedPercent -1Throws(IOException::class)override fun write(source: Buffer, byteCount: Long) {super.write(source, byteCount)bytesWritten byteCount// 优化每1%进度回调一次避免频繁更新UIval currentPercent (100 * bytesWritten / contentLength).toInt()if (currentPercent ! lastReportedPercent) {listener.onProgress(bytesWritten, contentLength, identifier)lastReportedPercent currentPercent}}Throws(IOException::class)override fun close() {super.close()// 最终完成回调listener.onProgress(bytesWritten, contentLength, identifier, true)} }3. 可监听进度的RequestBody封装 import okhttp3.MediaType import okhttp3.RequestBody import okio.BufferedSink import okio.Okioclass ProgressRequestBody(private val delegate: RequestBody,private val listener: ProgressListener,private val identifier: String? null ) : RequestBody() {override fun contentType(): MediaType? delegate.contentType()override fun contentLength(): Long delegate.contentLength()Throws(IOException::class)override fun writeTo(sink: BufferedSink) {val countingSink CountingSink(sink, listener, contentLength(),identifier)val bufferedSink Okio.buffer(countingSink)delegate.writeTo(bufferedSink)// 确保所有数据写入bufferedSink.flush()} }实战应用多文件上传示例 Retrofit服务接口定义 interface UploadService {MultipartPOST(upload)suspend fun uploadFiles(Part files: ListMultipartBody.Part): ResponseUploadResult }多文件上传管理器 import android.os.Handler import android.os.Looper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import okhttp3.MultipartBody import retrofit2.Response import java.io.Fileclass UploadManager(private val service: UploadService,private val uiHandler: Handler Handler(Looper.getMainLooper()) ) {// 进度回调映射文件路径 - 进度百分比private val progressMap mutableMapOfString, Int()// 进度监听器实现private val progressListener object : ProgressListener {override fun onProgress(bytesWritten: Long, contentLength: Long, identifier: String?, done: Boolean) {identifier?.let { filePath -val progress (100 * bytesWritten / contentLength).toInt()progressMap[filePath] progress// 更新UI切换到主线程uiHandler.post {// 这里简化处理实际应通过LiveData或回调通知println(文件 $filePath 上传进度: $progress%)}}}}suspend fun uploadFiles(files: ListFile): UploadResult {return withContext(Dispatchers.IO) {// 准备上传部件val parts files.map { file -val requestBody file.asRequestBody(application/octet-stream.toMediaType())val progressBody ProgressRequestBody(requestBody,progressListener,file.absolutePath // 使用文件路径作为标识符)MultipartBody.Part.createFormData(files, file.name, progressBody)}// 执行上传val response service.uploadFiles(parts)if (response.isSuccessful) {response.body() ?: throw UploadException(上传成功但返回空数据)} else {throw UploadException(上传失败: ${response.code()})}}} }class UploadException(message: String) : Exception(message)Android中使用示例 // 在ViewModel中 class UploadViewModel : ViewModel() {private val uploadManager UploadManager(RetrofitClient.uploadService)// 使用LiveData跟踪进度和结果val uploadProgress MutableLiveDataMapString, Int()val uploadResult MutableLiveDataResultUploadResult()fun uploadFiles(files: ListFile) {viewModelScope.launch {uploadResult.value Result.loading()try {val result uploadManager.uploadFiles(files)uploadResult.value Result.success(result)} catch (e: Exception) {uploadResult.value Result.error(e)}}}// 更新进度实际应用中UploadManager应回调此方法fun updateProgress(progressMap: MapString, Int) {uploadProgress.value progressMap} }// 在Activity/Fragment中观察 viewModel.uploadProgress.observe(this) { progressMap -progressMap.forEach { (filePath, progress) -// 更新对应文件的进度条fileProgressBars[filePath]?.progress progress} }viewModel.uploadResult.observe(this) { result -when (result.status) {Status.LOADING - showLoading()Status.SUCCESS - showSuccess(result.data)Status.ERROR - showError(result.message)} }性能优化策略 1. 回调频率控制 // 在CountingSink中添加优化逻辑 private var lastReportedTime 0L private val REPORT_INTERVAL 200L // 200毫秒override fun write(source: Buffer, byteCount: Long) {super.write(source, byteCount)bytesWritten byteCountval currentTime System.currentTimeMillis()if (currentTime - lastReportedTime REPORT_INTERVAL || bytesWritten contentLength) {listener.onProgress(bytesWritten, contentLength, identifier)lastReportedTime currentTime} }2. 弱引用防止内存泄漏 class WeakProgressListener(private val delegate: ProgressListener ) : ProgressListener {private val weakRef WeakReference(delegate)override fun onProgress(bytesWritten: Long, contentLength: Long, identifier: String?, done: Boolean) {weakRef.get()?.onProgress(bytesWritten, contentLength, identifier, done)} }// 使用方式 val progressBody ProgressRequestBody(requestBody,WeakProgressListener(progressListener),file.absolutePath )3. 大文件分块上传 class ChunkedUploader(private val file: File,private val chunkSize: Long 1024 * 1024 // 1MB ) {suspend fun uploadWithProgress(listener: ProgressListener) {val totalSize file.length()var uploaded 0Lvar chunkIndex 0file.inputStream().use { input -val buffer ByteArray(chunkSize.toInt())var bytesRead: Intwhile (input.read(buffer).also { bytesRead it } ! -1) {// 上传当前分块uploadChunk(chunkIndex, buffer, bytesRead)// 更新进度uploaded bytesReadlistener.onProgress(uploaded, totalSize, file.absolutePath)chunkIndex}}// 最终完成回调listener.onProgress(totalSize, totalSize, file.absolutePath, true)}private suspend fun uploadChunk(index: Int, data: ByteArray, size: Int) {// 实现分块上传逻辑} }与其他技术对比 技术方案优点缺点适用场景RequestBody封装底层实现、高效灵活、与OkHttp无缝集成需要自定义封装、对新手有一定难度需要精细控制上传过程的场景Interceptor拦截器统一处理所有请求、位置集中难以区分不同文件进度、实现复杂需要全局监控的场景系统级进度监听简单易用、无需额外代码功能有限、无法自定义回调频率简单小文件上传分块上传自定义协议支持断点续传、精确控制实现复杂、需要服务端配合超大文件上传、不稳定网络环境 关键点总结 核心原理通过自定义Sink拦截写入操作实现字节计数进度计算进度百分比 (已上传字节数 / 文件总大小) * 100线程安全进度回调在IO线程更新UI需切主线程性能优化 控制回调频率时间阈值或进度阈值使用弱引用防止内存泄漏大文件采用分块上传策略 多文件支持为每个文件分配唯一标识符容错处理处理除零异常和取消上传逻辑 高级应用场景 1. 断点续传实现 class ResumableProgressRequestBody(delegate: RequestBody,listener: ProgressListener,identifier: String?,private val startPosition: Long // 从上次中断处继续 ) : ProgressRequestBody(delegate, listener, identifier) {override fun writeTo(sink: BufferedSink) {val countingSink CountingSink(sink, listener, contentLength(),identifier).apply {bytesWritten startPosition // 设置起始位置}val bufferedSink Okio.buffer(countingSink)delegate.writeTo(bufferedSink)bufferedSink.flush()} }2. 上传速度计算 // 在ProgressListener中添加速度回调 interface AdvancedProgressListener : ProgressListener {fun onSpeedCalculated(bytesPerSecond: Double, identifier: String?) }// 在CountingSink中实现速度计算 private var lastBytesWritten 0L private var lastTimeMillis System.currentTimeMillis()override fun write(source: Buffer, byteCount: Long) {super.write(source, byteCount)val currentTime System.currentTimeMillis()val elapsed currentTime - lastTimeMillisif (elapsed 1000) { // 每秒计算一次val deltaBytes bytesWritten - lastBytesWrittenval speed deltaBytes / (elapsed / 1000.0)(listener as? AdvancedProgressListener)?.onSpeedCalculated(speed, identifier)lastBytesWritten bytesWrittenlastTimeMillis currentTime} }最佳实践建议 进度显示策略 小文件5MB显示百分比中等文件5-50MB显示百分比剩余时间大文件50MB显示百分比速度剩余时间 异常处理增强 override fun writeTo(sink: BufferedSink) {try {// ... 正常写入逻辑} catch (e: IOException) {listener.onError(e, identifier)throw e} finally {// 清理资源} }取消上传支持 class CancellableProgressRequestBody(delegate: RequestBody,listener: ProgressListener,identifier: String?,private val isCancelled: () - Boolean // 取消状态检查 ) : ProgressRequestBody(delegate, listener, identifier) {Throws(IOException::class)override fun writeTo(sink: BufferedSink) {val countingSink object : CountingSink(sink, listener, contentLength(), identifier) {override fun write(source: Buffer, byteCount: Long) {if (isCancelled()) throw IOException(Upload cancelled)super.write(source, byteCount)}}// ... 其余逻辑} }总结 本文详细介绍了通过封装OkHttp的RequestBody实现文件上传进度监听的技术方案。核心要点包括 通过自定义CountingSink拦截和计算已上传字节数使用ProgressRequestBody包装原始RequestBody实现多文件上传的进度区分性能优化和内存管理技巧高级应用如断点续传和速度计算 这种方案具有高度灵活性和可扩展性能够满足从简单到复杂的各种文件上传需求。
http://www.dnsts.com.cn/news/134477.html

相关文章:

  • 深圳网站建设前十名苏州新区高端网站制作
  • 农业网站建设模板网站升级通知
  • 网站 毕业设计代做广告公司海报用的易拉
  • 郴州竞价网站建设方案wordpress手机导航栏模板
  • 温州微网站品牌注册号
  • 自贡普通网站建设费用郴州招聘网直招最新招聘
  • 上海医疗网站备案knowall wordpress
  • 网站建设规划书主题网站建设与维护典型案例
  • dede 网站地图样式做网站排名需要多少钱
  • 蒲城做网站网站seo检测
  • 网站做优化效果怎样怎样做当地网站推广
  • 江苏网站建设价格低360网站关键词排名优化
  • 哪个网站推广好中国最新的国内军事新闻
  • 做外贸一般去什么网站找客户西数网站管理助手 伪静态
  • 大理建网站视频网站推广怎么做
  • 企业网站如何制作空间平面的网页设计素材
  • 设计的网站源代码怎么做哪些客户需要做网站
  • 网站制作公司员工郑州网站优化渠道
  • 金华公司网站建设网络公司排名
  • 有什么做ppt参考的网站wordpress 福利
  • 工信部网站备案查询步骤html教程 it教程网
  • 改网站字体颜色代码小程序开发平台哪家产品好
  • 网站的建设步骤包括常州企业免费建站
  • 建网站程序怎么办学校网站网页制作
  • 南昌公路建设有限公司网站wordpress模版手机
  • 在线做汉字头像的网站开发软件的工具
  • 那些做环保网站的好处网站建设好与管理在哪就业
  • 在线免费网站模板网站 备案号查询
  • 网站有哪些风格亚马逊做deal的网站
  • 网站建设怎么配置伪静态文件最酷炫的wordpress the7