博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CodePush自定义更新弹框及下载进度条
阅读量:6956 次
发布时间:2019-06-27

本文共 8988 字,大约阅读时间需要 29 分钟。

CodePush 热更新之自定义更新弹框及下载进度

先来几张弹框效果图

  • 非强制更新场景

image

  • 强制更新场景

image

  • 更新包下载进度效果

image

核心代码

这里的热更新Modal框,是封装成一个功能独立的组件来使用的,需不需要更新以及是否为强制更新等逻辑均在组件内实现

image

UpdateComp 热更新组件核心代码如下:

/** * Created by guangqiang on 2018/3/29. */import React, {Component} from 'react'import {View, Text, StyleSheet, Modal, TouchableOpacity, Image} from 'react-native'import Progress from './index'import {GlobalStyles} from '../../../constants/GlobalStyles'import {deviceInfo} from "../../../constants/DeviceInfo"import {Icon} from '../../../utils/iconFont'import CodePush from "react-native-code-push"import {Toast} from "../../../utils/toast"const CODE_PUSH_KEY = 'jE39cjdnkzqfpXgRylPXDDNkEzJm3ac740b8-b071-474f-afbf-369c6e4642ab'let codePushOptions = {  checkFrequency : CodePush.CheckFrequency.ON_APP_START}class ProgressBar extends Component {  constructor(props) {    super(props)    this.currProgress = 0.0    this.syncMessage = ''    this.state = {      modalVisible: false,      isMandatory: false,      immediateUpdate: false,      updateInfo: {}    }  }  codePushStatusDidChange(syncStatus) {    if (this.state.immediateUpdate) {      switch(syncStatus) {        case CodePush.SyncStatus.CHECKING_FOR_UPDATE:          this.syncMessage = 'Checking for update'          break;        case CodePush.SyncStatus.DOWNLOADING_PACKAGE:          this.syncMessage = 'Downloading package'          break;        case CodePush.SyncStatus.AWAITING_USER_ACTION:          this.syncMessage = 'Awaiting user action'          break;        case CodePush.SyncStatus.INSTALLING_UPDATE:          this.syncMessage = 'Installing update'          break;        case CodePush.SyncStatus.UP_TO_DATE:          this.syncMessage = 'App up to date.'          break;        case CodePush.SyncStatus.UPDATE_IGNORED:          this.syncMessage = 'Update cancelled by user'          break;        case CodePush.SyncStatus.UPDATE_INSTALLED:          this.syncMessage = 'Update installed and will be applied on restart.'          break;        case CodePush.SyncStatus.UNKNOWN_ERROR:          this.syncMessage = 'An unknown error occurred'          Toast.showError('更新出错,请重启应用!')          this.setState({modalVisible: false})          break;      }    }  }  codePushDownloadDidProgress(progress) {    if (this.state.immediateUpdate) {      this.currProgress = parseFloat(progress.receivedBytes / progress.totalBytes).toFixed(2)      if(this.currProgress >= 1) {        this.setState({modalVisible: false})      } else {        this.refs.progressBar.progress = this.currProgress      }    }  }  syncImmediate() {    CodePush.checkForUpdate(CODE_PUSH_KEY).then((update) => {      console.log('-------' + update)      if (!update) {        Toast.showLongSuccess('已是最新版本!')      } else {        this.setState({modalVisible: true, updateInfo: update, isMandatory: update.isMandatory})      }    })  }  componentWillMount() {    CodePush.disallowRestart()    this.syncImmediate()  }  componentDidMount() {    CodePush.allowRestart()  }  _immediateUpdate() {    this.setState({immediateUpdate: true})    CodePush.sync(        {deploymentKey: CODE_PUSH_KEY, updateDialog: {}, installMode: CodePush.InstallMode.IMMEDIATE},        this.codePushStatusDidChange.bind(this),        this.codePushDownloadDidProgress.bind(this)    )  }  renderModal() {    return (        
alert("Modal has been closed.")}>
{ !this.state.immediateUpdate ?
更新内容
{this.state.updateInfo.description}
wifi情况下更新不到30秒
{ !this.state.isMandatory ?
this.setState({modalVisible: false})}>
残忍拒绝
this._immediateUpdate()} >
极速下载
:
this._immediateUpdate()} >
立即更新
}
:
版本正在努力更新中,请等待
}
) } render(){ return(
{this.renderModal()}
) }}const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: GlobalStyles.bgColor }, modal: { height: deviceInfo.deviceHeight, width: deviceInfo.deviceWidth, alignItems: 'center', justifyContent: 'center', backgroundColor: 'rgba(0,0,0,0.3)' }, modalContainer: { marginHorizontal: 60, borderBottomLeftRadius: 10, borderBottomRightRadius: 10, }})export default CodePush(codePushOptions)(ProgressBar)

下载进度条组件Progress 这里也是封装成一个组件,核心代码如下:

image

/** * Created by guangqiang on 2018/3/29. */import React, {Component}from 'react'import {View, StyleSheet, Animated, Easing}from 'react-native'import PropTypes from 'prop-types'export default class CusProgressBar extends Component {  static propTypes = {    ...View.propTypes,    // 当前进度    progress: PropTypes.number,    // second progress进度    buffer: PropTypes.number,    // 进度条颜色    progressColor: PropTypes.string,    // buffer进度条颜色    bufferColor: PropTypes.string,    // 进度动画时长    progressAniDuration: PropTypes.number,    // buffer动画时长    bufferAniDuration: PropTypes.number  }  static defaultProps = {    // 进度条颜色    progressColor: 'white',    // buffer进度条颜色    bufferColor: 'rgba(255,0,0,0.7)',    // 进度条动画时长    progressAniDuration: 100,    // buffer进度条动画时长    bufferAniDuration: 100  }  constructor(props) {    super(props)    this._progressAni = new Animated.Value(0)    this._bufferAni = new Animated.Value(0)  }  componentWillReceiveProps(nextProps) {    this._progress = nextProps.progress    this._buffer = nextProps.buffer  }  componentWillMount() {    this._progress = this.props.progress    this._buffer = this.props.buffer  }  render() {    return (        
) } _onLayout({nativeEvent: {layout:{width, height}}}) { // 防止多次调用,当第一次获取后,后面就不再去获取了 if (width > 0 && this.totalWidth !== width) { // 获取progress控件引用 let progress = this._getProgress() // 获取buffer控件引用 let buffer = this._getBuffer() // 获取父布局宽度 this.totalWidth = width //给progress控件设置高度 progress.setNativeProps({ style: { height: height } }) // 给buffer控件设置高度 buffer.setNativeProps({ style: { height: height } }) // 开始执行进度条动画 this._startAniProgress(this.progress) // 开始执行buffer动画 this._startAniBuffer(this.buffer) } } _startAniProgress(progress) { if (this._progress >= 0 && this.totalWidth !== 0) { Animated.timing(this._progressAni, { toValue: progress * this.totalWidth, duration: this.props.progressAniDuration, easing: Easing.linear }).start() } } _startAniBuffer(buffer) { if (this._buffer >= 0 && this.totalWidth !== 0) { Animated.timing(this._bufferAni, { toValue: buffer * this.totalWidth, duration: this.props.bufferAniDuration, }).start() } } _getProgress() { if (typeof this.refs.progress.refs.node !== 'undefined') { return this.refs.progress.refs.node } return this.refs.progress._component } _getBuffer() { if (typeof this.refs.buffer.refs.node !== 'undefined') { return this.refs.buffer.refs.node; } return this.refs.buffer._component; }}Object.defineProperty(CusProgressBar.prototype, 'progress', { set(value){ if (value >= 0 && this._progress !== value) { this._progress = value; this._startAniProgress(value); } }, get() { return this._progress; }, enumerable: true,})Object.defineProperty(CusProgressBar.prototype, 'buffer', { set(value){ if (value >= 0 && this._buffer !== value) { this._buffer = value; this._startAniBuffer(value); } }, get() { return this._buffer; }, enumerable: true,})const styles = StyleSheet.create({ container: { height: 4, backgroundColor: 'blue' }})

UpdateComp组件中的热更新核心代码讲解

image

这我们在UpdateComp 组件中,在 componentWillMount 的生命周期函数中,我们调用codepush提供的这两个函数:并在syncImmediate 函数中,我们调用codepush的checkForUpdate 函数来检查是否已有新版本,以及新版本的信息等,具体代码实现如下:

image

注意:

codepush有两个代理函数我们需要调用:

image

  • codePushStatusDidChange: codepush状态的变化的钩子函数
  • codePushDownloadDidProgress: codepush下载更新包的进度钩子函数

当我们处理完上面的内容,codepush的基本功能我们就处理完毕了,剩下的工作就是处理一些逻辑了,包括该不该弹更新框,以及更新弹框和更新进度的处理

总结:

本篇教程主要是讲解codepush中如何处理安装包的下载进度,以及如何自定义更新弹框和下载进度条,上面的弹框功能和下载进度条功能基本都已处理完毕,可以直接复制两个组件代码到自己项目中,稍作修改即可使用。如果还有小伙伴对codepush详细的接入流程不熟悉的,请点击查看作者的 一文,如果还有其他的问题,也可以简书留言或者进群提问

RN实战总结

  • 作者React Native开源项目OneM地址(按照企业开发标准搭建框架完成开发的)::欢迎小伙伴们 star
  • 作者简书主页:包含60多篇RN开发相关的技术文章 欢迎小伙伴们:多多关注多多点赞
  • 作者React Native QQ技术交流群:620792950 欢迎小伙伴进群交流学习
  • 友情提示:在开发中有遇到RN相关的技术问题,欢迎小伙伴加入交流群(620792950),在群里提问、互相交流学习。交流群也定期更新最新的RN学习资料给大家,谢谢大家支持!

转载地址:http://qztil.baihongyu.com/

你可能感兴趣的文章
stl之multiset容器的应用
查看>>
LeetCode 205 Isomorphic Strings(同构的字符串)(string、vector、map)(*)
查看>>
Django REST Framework限速
查看>>
洪涝淹没分析输出淹没范围图、深度图及面积体积等信息【转】
查看>>
树莓派(Debian)系统开启iptables的raw表实现日志输出
查看>>
图像滤镜实现万能方法研究
查看>>
nginx-启动gzip、虚拟主机、请求转发、负载均衡
查看>>
magento 2.3安装测试数据
查看>>
大数据开发实战:数据平台大图和离线数据平台整体架构
查看>>
Git 收集别名
查看>>
操作系统日志分析中常见的搜索条目 20160715
查看>>
《CLR via C#》笔记——异常和状态管理
查看>>
将matlab的figure保存为pdf,避免图片太大缺失
查看>>
Spring MVC 3 深入总结
查看>>
原创4:dell sc1425老服务器安装vmware虚拟机esxi 5.0-更新Dell SCSI Hard Drive Firmware
查看>>
JAVA多线程学习Runnable接口
查看>>
AE Geoprocessor 实现 AnalysisTool Union功能
查看>>
深入理解JVM
查看>>
微观ORACLE(一):PMON Release Lock
查看>>
NC57银行档案和客商银行账号为建行04 UPDATE
查看>>