【发布时间】:2021-09-08 04:04:03
【问题描述】:
我正在开发一个有声读物收听应用程序。我有我的主页,它由 3 个页面小部件组成,这些小部件通过页面视图链接,我可以通过滑动浏览这些页面。在每一页上,我都放置了一个来自google_mobile_ads 包的横幅广告。问题是,如果我添加这 3 个横幅,我的应用程序开始滞后很多,我确实检查了我的应用程序的发布版本,它仍然滞后。为了更好地了解情况,我将解释我的广告加载是如何工作的。
我有一个文件,其中存储有关这些横幅广告的类:
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:flutter/material.dart';
late AnchoredAdaptiveBannerAdSize adaptiveBannerSize;
class AdWidgets {
static Container? libraryPag;
static Container? homePag;
static Container? settingsPag;
}
void _setLoaded() {
AdState.loaded = true;
}
class AdState {
static bool loaded = false;
late Future<InitializationStatus> initialization;
AdState(this.initialization);
String get bannerAdUnitId => 'ca-app-pub-3940256099942544/6300978111';
BannerAdListener get adListener => _adListener;
BannerAdListener _adListener = BannerAdListener(
onAdLoaded: (ad) {
_setLoaded();
}
);
}
有一个 AdState 类,我通过向它们提供 BannerAdListener 和 AdUnitId 来加载我的横幅广告,bool loaded 用于显示这些横幅的小部件中,以便他们知道广告是否已加载并可以正常显示。
接下来我有一个 Stateful Widget Content,我用它来浏览我的应用程序路线:
class _ContentState extends State<Content> with SingleTickerProviderStateMixin {
@override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
final adState = Provider.of<AdState>(context);
adState.initialization.then((status) {
AdWidgets.libraryPag = Container(
width: MediaQuery.of(context).size.width,
height: adaptiveBannerSize.height.toDouble(),
child: AdWidget(
ad: BannerAd(
adUnitId: adState.bannerAdUnitId,
size: adaptiveBannerSize,
request: AdRequest(),
listener: adState.adListener
)
..load(),
)
);
AdWidgets.homePag = Container(
width: 320,
height: 100,
child: AdWidget(ad: BannerAd(
adUnitId: adState.bannerAdUnitId,
size: AdSize.largeBanner,
request: AdRequest(),
listener: adState.adListener
)
..load()),
);
AdWidgets.settingsPag = Container(
width: 320,
height: 250,
child: AdWidget(ad: BannerAd(
adUnitId: adState.bannerAdUnitId,
size: AdSize.mediumRectangle,
request: AdRequest(),
listener: adState.adListener
)
..load()
)
);
});
}
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: Settings.theme,
builder: (context, value, _) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Settings.theme.value == 'Dark' ? Brightness.light : Brightness.dark,
));
return WillPopScope(
onWillPop: () async {
if (bottomBarIndex.value != 1) {
moveHome();
}
return false;
},
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Navigator(
key: Content.contentNavigatorKey,
initialRoute: '/',
onGenerateRoute: (RouteSettings settings) {
Widget builder;
switch (settings.name) {
case '/':
builder = MainPage();
break;
case '/bookPage':
Book book = settings.arguments as Book;
builder = BookPage(book: book);
bottomBarIndex.value = -1;
break;
case '/addBook':
builder = AddBookPage();
bottomBarIndex.value = -1;
break;
case '/changeCover':
Book book = settings.arguments as Book;
builder = ChangeCoverPage(book: book);
bottomBarIndex.value = -1;
break;
default:
throw Exception('Invalid route: ${settings.name}');
}
return PageRouteBuilder(
transitionDuration: Duration(milliseconds: 300),
transitionsBuilder:
(context, animation, secAnimation, child) {
animation = CurvedAnimation(
parent: animation, curve: Curves.easeIn);
return FadeTransition(
opacity: animation,
child: child,
);
},
pageBuilder: (context, animation, secAnimation) {
return builder;
});
},
onPopPage: (route, result) {
return route.didPop(result);
},
),
));
},
);
}
}
在 didChangeDependencies 方法中,我初始化了 adState(在 Monetizing apps with Flutter 官方教程中完成的方式),然后将三个横幅小部件分配给来自 AdWidgets 自定义类的 static Container 中的每一个。然后我就随意显示那些容器,例如:
class LibraryPage extends StatefulWidget{
const LibraryPage({Key? key}) : super(key: key);
@override
_LibraryPageState createState() => _LibraryPageState();
}
class _LibraryPageState extends State<LibraryPage> with TickerProviderStateMixin {
late TabController _tabController;
late AppBar appBar;
@override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
appBar = AppBar(
brightness: Settings.theme.value == 'Dark' ? Brightness.dark : Brightness.light,
shadowColor: Settings.theme.value == 'Dark' ? Color.fromRGBO(0, 0, 0, 0.1) : Color.fromRGBO(0, 0, 0, 0.5),
backgroundColor: Settings.colors[2],
title: Text('Library'),
bottom: TabBar(
controller: _tabController,
labelPadding: EdgeInsets.zero,
labelStyle: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500
),
labelColor: Settings.colors[3],
indicator: UnderlineTabIndicator(
borderSide: BorderSide(color: Settings.colors[3], width: 2)
),
tabs: [
Tab(
text: 'Reading',
),
Tab(
text: 'New',
),
Tab(
text: 'Read',
)
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Settings.colors[1],
resizeToAvoidBottomInset: false,
appBar: appBar,
body: Column(
children: [
if (AdWidgets.libraryPag != null && AdState.loaded)
AdWidgets.libraryPag!
else
Container(
width: MediaQuery.of(context).size.width,
height: adaptiveBannerSize.height.toDouble(),
color: Settings.colors[0],
child: Center(
child: Text(
'Ad not loaded',
style: TextStyle(
color: Settings.colors[4],
fontFamily: 'Open Sans'),
)),
),
ScrollConfiguration(
behavior: MyBehavior(),
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - appBar.preferredSize.height - appBar.bottom!.preferredSize.height - adaptiveBannerSize.height,
child: TabBarView(
controller: _tabController,
children: [
Category(category: 'reading'),
Category(category: 'new'),
Category(category: 'read')
],
),
),
),
],
),
);
}
}
如您所见,我检查AdWidgets.libraryPag 是否不为空,广告是否已加载,如果为真,我会显示我的广告。
主要问题是 - 当我从一个页面导航到另一个页面或向下滚动时,即使在发布版本中它也非常滞后,而且我的底部导航栏也开始闪烁很多。此外,当我在我的应用程序中执行任何类型的操作时,我会在控制台日志中收到一堆消息,上面写着D/AudioManager(30711): getStreamVolume isRestricted mode = 0。我的猜测是广告重新加载过于频繁会导致一些性能问题。
这是我的控制台日志的一小部分:
W/ContentCatcher(30711): Failed to notify a WebView
W/Choreographer(30711): Already have a pending vsync event. There should only be one at a time.
W/Choreographer(30711): OPTS_INPUT: First frame was drawed before optimized, so skip!
W/ContentCatcher(30711): Failed to notify a WebView
W/ContentCatcher(30711): Failed to notify a WebView
W/Choreographer(30711): Already have a pending vsync event. There should only be one at a time.
W/Choreographer(30711): Already have a pending vsync event. There should only be one at a time.
W/ContentCatcher(30711): Failed to notify a WebView
W/ContentCatcher(30711): Failed to notify a WebView
W/Choreographer(30711): OPTS_INPUT: First frame was drawed before optimized, so skip!
W/Choreographer(30711): OPTS_INPUT: First frame was drawed before optimized, so skip!
W/ContentCatcher(30711): Failed to notify a WebView
I/Ads (30711): Use RequestConfiguration.Builder().setTestDeviceIds(Arrays.asList("B0B49AF69923DB48675A21F6F88D2525")) to get test ads on this device.
D/AudioManager(30711): getStreamVolume isRestricted mode = 0
D/AudioManager(30711): getStreamVolume isRestricted mode = 0
如何解决这个性能问题?
【问题讨论】:
标签: android flutter dart admob ads