匿名内部类 this.val$的问题

本文解析了反编译代码中出现的匿名内部类使用外部参数未加final、构造器参数错误及奇怪的val$用法等问题,并给出了正确的代码修改方案。

反编译一个项目,出现以下代码

 

public FlexgridView insertFlexgrid(FlexgridView flexgridView){
    Flexgrid flexgrid = FlexgridViewUtils.getFlexgrid(flexgridView);
    Flexgrid newFlexgrid = 
        (Flexgrid)getTransactionTemplate()
            .execute(new TransactionCallback(flexgrid) {
                public Object doInTransaction(TransactionStatus arg0) {
                    return        FlexgridServiceImpl.this.getFlexgridDomain().insertFlexgrid(this.val$flexgrid);
                }
        });
        return FlexgridViewUtils.getFlexgridView(newFlexgrid);
}

 

可参考链接:

http://www.mindfiresolutions.com/A-tip-on-val$-field-in-Java-decompiled-code-1725.php

 

    这些代码都是编译器反编译的时候自己添加上去的。

  第一个问题:匿名内部类要使用外面的参数,必须要加final。而代码中却没有加。

  第二个问题:new TransactionCallback这个类没有带参数的构造器。

  第三个问题:this.val$这种用法很怪异,val$是哪里来的。

  这些问题都是反编译器给我们搞的鬼。

  匿名内部类要使用外部的变量,或者参数,这个变量和参数都必须是final类型。而且匿名内部类没有构造器他的构造器是继承于父类,这就还有一个问题就是那我们如何初始化内名内部类中的变量,只需要使用“{}”在里面初始化变量不需要任何修饰。再就是在匿名内部类中this表示当前对象,如果要使用外部类对象需要加上Outclass.this这才是外部对象。

  所以以上代码做如下修改:

 

public FlexgridView insertFlexgrid(FlexgridView flexgridView) {
		final Flexgrid flexgrid = FlexgridViewUtils.getFlexgrid(flexgridView);//参数加上final
		Flexgrid newFlexgrid = (Flexgrid) getTransactionTemplate().execute(
				new TransactionCallback() {//额外的参数去掉
					public Object doInTransaction(TransactionStatus arg0) {
						return FlexgridServiceImpl.this.getFlexgridDomain()
								.insertFlexgrid(flexgrid);//"this.val$"  多余的去掉
					}
				});
		return FlexgridViewUtils.getFlexgridView(newFlexgrid);
}

 

 

 

这是我uniapp 的视频播放器 目前点击播放之后 出现了暂停图标 但是没有自动消失 , 怎么优化一下呢 , 还有个问题就是 安卓播放视频 不会暂停上一次播放的视频 <!-- eslint-disable --> <template> <view class="player-wrapper" :id="videoWrapperId" :parentId="id" :randomNum="randomNum" :change:randomNum="domVideoPlayer.randomNumChange" :viewportProps="viewportProps" :change:viewportProps="domVideoPlayer.viewportChange" :videoSrc="videoSrc" :change:videoSrc="domVideoPlayer.initVideoPlayer" :command="eventCommand" :change:command="domVideoPlayer.triggerCommand" :func="renderFunc" :change:func="domVideoPlayer.triggerFunc" > <!-- 默认播放控制图标 --> <cover-view class="control-icon-wrapper"> <cover-image class="control-icon" :src="playing ? '/static/pause.png' : '/static/play.png'" @click.stop="togglePlay" ></cover-image> </cover-view> </view> </template> <script> export default { props: { src: { type: String, default: '' }, autoplay: { type: Boolean, default: false }, loop: { type: Boolean, default: false }, controls: { type: Boolean, default: false }, objectFit: { type: String, default: 'contain' }, muted: { type: Boolean, default: false }, playbackRate: { type: Number, default: 1 }, isLoading: { type: Boolean, default: false }, poster: { type: String, default: '' }, id: { type: String, default: '' } }, data() { return { randomNum: Math.floor(Math.random() * 100000000), videoSrc: '', showControls: false, eventCommand: null, renderFunc: { name: null, params: null }, currentTime: 0, duration: 0, playing: false // 新增播放状态 } }, watch: { src: { handler(val) { if (!val) return setTimeout(() => { this.videoSrc = val }, 0) }, immediate: true } }, computed: { videoWrapperId() { return `video-wrapper-${this.randomNum}` }, viewportProps() { return { autoplay: this.autoplay, muted: this.muted, controls: this.showControls && this.controls, loop: this.loop, objectFit: this.objectFit, poster: this.poster, isLoading: this.isLoading, playbackRate: this.playbackRate } } }, methods: { togglePlay() { if (this.playing) { this.pause() } else { this.play() } this.playing = !this.playing }, toggleControls() { this.showControls = !this.showControls }, eventEmit({ event, data }) { this.$emit(event, data) }, setViewData({ key, value }) { key && this.$set(this, key, value) }, resetEventCommand() { this.eventCommand = null }, play() { this.eventCommand = 'play' }, pause() { this.eventCommand = 'pause' }, resetFunc() { this.renderFunc = { name: null, params: null } }, remove(params) { this.renderFunc = { name: 'removeHandler', params } }, fullScreen(params) { this.renderFunc = { name: 'fullScreenHandler', params } }, toSeek(sec, isDelay = false) { this.renderFunc = { name: 'toSeekHandler', params: { sec, isDelay } } } } } </script> <script module="domVideoPlayer" lang="renderjs"> const PLAYER_ID = 'DOM_VIDEO_PLAYER' export default { data() { return { num: '', videoEl: null, loadingEl: null, delayFunc: null, renderProps: {}, activePlayers: new Map() } }, computed: { playerId() { return `${PLAYER_ID}_${this.num}` }, wrapperId() { return `video-wrapper-${this.num}` } }, methods: { isApple() { const ua = navigator.userAgent.toLowerCase() return ua.indexOf('iphone') !== -1 || ua.indexOf('ipad') !== -1 }, pauseAllOtherPlayers(currentId) { this.activePlayers.forEach((player, id) => { if (id !== currentId && !player.paused) { player.pause() } }) }, async initVideoPlayer(src) { this.delayFunc = null await this.$nextTick() if (!src) return if (this.videoEl) { if (!this.isApple() && this.loadingEl) { this.loadingEl.style.display = 'block' } this.videoEl.src = src return } const videoEl = document.createElement('video') this.videoEl = videoEl this.activePlayers.set(this.playerId, videoEl) this.listenVideoEvent() const { autoplay, muted, controls, loop, playbackRate, objectFit, poster } = this.renderProps videoEl.src = src videoEl.autoplay = autoplay videoEl.controls = controls videoEl.loop = loop videoEl.muted = muted videoEl.playbackRate = playbackRate videoEl.id = this.playerId videoEl.setAttribute('preload', 'auto') videoEl.setAttribute('playsinline', true) videoEl.setAttribute('webkit-playsinline', true) videoEl.setAttribute('crossorigin', 'anonymous') videoEl.setAttribute('controlslist', 'nodownload') videoEl.setAttribute('disablePictureInPicture', true) videoEl.style.objectFit = objectFit poster && (videoEl.poster = poster) videoEl.style.width = '100%' videoEl.style.height = '100%' const playerWrapper = document.getElementById(this.wrapperId) playerWrapper.insertBefore(videoEl, playerWrapper.firstChild) this.createLoading() }, createLoading() { const { isLoading } = this.renderProps if (!this.isApple() && isLoading) { const loadingEl = document.createElement('div') this.loadingEl = loadingEl loadingEl.className = 'loading-wrapper' loadingEl.style.position = 'absolute' loadingEl.style.top = '0' loadingEl.style.left = '0' loadingEl.style.zIndex = '1' loadingEl.style.width = '100%' loadingEl.style.height = '100%' loadingEl.style.backgroundColor = 'black' document.getElementById(this.wrapperId).appendChild(loadingEl) const animationEl = document.createElement('div') animationEl.className = 'loading' animationEl.style.zIndex = '2' animationEl.style.position = 'absolute' animationEl.style.top = '50%' animationEl.style.left = '50%' animationEl.style.marginTop = '-15px' animationEl.style.marginLeft = '-15px' animationEl.style.width = '30px' animationEl.style.height = '30px' animationEl.style.border = '2px solid #FFF' animationEl.style.borderTopColor = 'rgba(255, 255, 255, 0.2)' animationEl.style.borderRightColor = 'rgba(255, 255, 255, 0.2)' animationEl.style.borderBottomColor = 'rgba(255, 255, 255, 0.2)' animationEl.style.borderRadius = '100%' animationEl.style.animation = 'circle infinite 0.75s linear' loadingEl.appendChild(animationEl) const style = document.createElement('style') const keyframes = ` @keyframes circle { 0% { transform: rotate(0); } 100% { transform: rotate(360deg); } } ` style.type = 'text/css' if (style.styleSheet) { style.styleSheet.cssText = keyframes } else { style.appendChild(document.createTextNode(keyframes)) } document.head.appendChild(style) } }, listenVideoEvent() { const playHandler = () => { this.pauseAllOtherPlayers(this.playerId) this.$ownerInstance.callMethod('eventEmit', { event: 'play' }) this.$ownerInstance.callMethod('setViewData', { key: 'playing', value: true }) if (this.loadingEl) { this.loadingEl.style.display = 'none' } } this.videoEl.removeEventListener('play', playHandler) this.videoEl.addEventListener('play', playHandler) const pauseHandler = () => { this.$ownerInstance.callMethod('eventEmit', { event: 'pause' }) this.$ownerInstance.callMethod('setViewData', { key: 'playing', value: false }) } this.videoEl.removeEventListener('pause', pauseHandler) this.videoEl.addEventListener('pause', pauseHandler) const endedHandler = () => { this.$ownerInstance.callMethod('eventEmit', { event: 'ended' }) this.$ownerInstance.callMethod('resetEventCommand') } this.videoEl.removeEventListener('ended', endedHandler) this.videoEl.addEventListener('ended', endedHandler) const canPlayHandler = () => { this.$ownerInstance.callMethod('eventEmit', { event: 'canplay' }) this.execDelayFunc() } this.videoEl.removeEventListener('canplay', canPlayHandler) this.videoEl.addEventListener('canplay', canPlayHandler) const errorHandler = (e) => { if (this.loadingEl) { this.loadingEl.style.display = 'block' } this.$ownerInstance.callMethod('eventEmit', { event: 'error' }) } this.videoEl.removeEventListener('error', errorHandler) this.videoEl.addEventListener('error', errorHandler) const loadedMetadataHandler = () => { this.$ownerInstance.callMethod('eventEmit', { event: 'loadedmetadata' }) const duration = this.videoEl.duration this.$ownerInstance.callMethod('eventEmit', { event: 'durationchange', data: duration }) this.$ownerInstance.callMethod('setViewData', { key: 'duration', value: duration }) this.loadFirstFrame() } this.videoEl.removeEventListener('loadedmetadata', loadedMetadataHandler) this.videoEl.addEventListener('loadedmetadata', loadedMetadataHandler) const timeupdateHandler = (e) => { const currentTime = e.target.currentTime this.$ownerInstance.callMethod('eventEmit', { event: 'timeupdate', data: currentTime }) this.$ownerInstance.callMethod('setViewData', { key: 'currentTime', value: currentTime }) } this.videoEl.removeEventListener('timeupdate', timeupdateHandler) this.videoEl.addEventListener('timeupdate', timeupdateHandler) const ratechangeHandler = (e) => { const playbackRate = e.target.playbackRate this.$ownerInstance.callMethod('eventEmit', { event: 'ratechange', data: playbackRate }) } this.videoEl.removeEventListener('ratechange', ratechangeHandler) this.videoEl.addEventListener('ratechange', ratechangeHandler) if (this.isApple()) { const webkitbeginfullscreenHandler = () => { const presentationMode = this.videoEl.webkitPresentationMode let isFullScreen = null if (presentationMode === 'fullscreen') { isFullScreen = true } else { isFullScreen = false } this.$ownerInstance.callMethod('eventEmit', { event: 'fullscreenchange', data: isFullScreen }) } this.videoEl.removeEventListener('webkitpresentationmodechanged', webkitbeginfullscreenHandler) this.videoEl.addEventListener('webkitpresentationmodechanged', webkitbeginfullscreenHandler) } else { const fullscreenchangeHandler = () => { let isFullScreen = null if (document.fullscreenElement) { isFullScreen = true } else { isFullScreen = false } this.$ownerInstance.callMethod('eventEmit', { event: 'fullscreenchange', data: isFullScreen }) } document.removeEventListener('fullscreenchange', fullscreenchangeHandler) document.addEventListener('fullscreenchange', fullscreenchangeHandler) } }, loadFirstFrame() { let { autoplay, muted } = this.renderProps if (this.isApple()) { this.videoEl.play() if (!autoplay) { this.videoEl.pause() } } else { this.videoEl.muted = true setTimeout(() => { this.videoEl.play() this.videoEl.muted = muted if (!autoplay) { setTimeout(() => { this.videoEl.pause() }, 100) } }, 10) } }, triggerCommand(eventType) { if (eventType) { this.$ownerInstance.callMethod('resetEventCommand') this.videoEl && this.videoEl[eventType]() } }, triggerFunc(func) { const { name, params } = func || {} if (name) { this[name](params) this.$ownerInstance.callMethod('resetFunc') } }, removeHandler() { if (this.videoEl) { this.videoEl.pause() this.videoEl.src = '' this.$ownerInstance.callMethod('setViewData', { key: 'videoSrc', value: '' }) this.videoEl.load() } }, fullScreenHandler() { if (this.isApple()) { this.videoEl.webkitEnterFullscreen() } else { this.videoEl.requestFullscreen() } }, toSeekHandler({ sec, isDelay }) { const func = () => { if (this.videoEl) { this.videoEl.currentTime = sec } } if (isDelay) { this.delayFunc = func } else { func() } }, execDelayFunc() { this.delayFunc && this.delayFunc() this.delayFunc = null }, viewportChange(props) { this.renderProps = props const { autoplay, muted, controls, loop, playbackRate } = props if (this.videoEl) { this.videoEl.autoplay = autoplay this.videoEl.controls = controls this.videoEl.loop = loop this.videoEl.muted = muted this.videoEl.playbackRate = playbackRate } }, randomNumChange(val) { this.num = val } } } </script> <style scoped> .player-wrapper { position: relative; height: 100%; } /* 控制图标样式 */ .control-icon-wrapper { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10; } .control-icon { width: 80rpx; height: 80rpx; opacity: 0.8; } </style>
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值